diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 7159a0b..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-2.7-bullseye - -RUN wget https://github.com/errata-ai/vale/releases/download/v2.21.0/vale_2.21.0_Linux_64-bit.tar.gz -O /tmp/vale.tar.gz \ - && cd /usr/local/bin \ - && tar xf /tmp/vale.tar.gz \ - && rm /tmp/vale.tar.gz \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 1d206de..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,13 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/ruby -{ - "name": "Ruby", - "build": { - "dockerfile": "Dockerfile" - }, - "runArgs": ["--userns=keep-id"], - - "remoteUser": "vscode", - "containerUser": "vscode", - "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/${localWorkspaceFolderBasename},type=bind,Z" -} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 508b6b2..0000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -_site/ -.swp -.sass-cache/ -.jekyll-metadata -.bundle/ -vendor/ -.styles/ -.vscode/ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/.vale.ini b/.vale.ini deleted file mode 100644 index 777f626..0000000 --- a/.vale.ini +++ /dev/null @@ -1,7 +0,0 @@ -StylesPath = .styles -MinAlertLevel = suggestion -Packages = Microsoft, write-good - -[*] -BasedOnStyles = Vale, Microsoft, write-good -write-good.E-Prime = NO \ No newline at end of file diff --git a/2011/11/webpack-industrial-complex/index.html b/2011/11/webpack-industrial-complex/index.html new file mode 100644 index 0000000..64e0d9c --- /dev/null +++ b/2011/11/webpack-industrial-complex/index.html @@ -0,0 +1,32 @@ +The webpack industrial complex | The Old Speice Guy
Skip to main content

The webpack industrial complex

· 5 min read
Bradlee Speice

This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).

+

The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.

+

Starting strong

+

The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser."

+

Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an onEvent handler and a function easy.

+

Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical."

+

Continuing on

+

Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?

+

The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API was missing. After searching out Github issues and (unsuccessfully) tweaking the .tsconfig settings, I settled on installing a package and moving on.

+

The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use new URL(<local path>, import.meta.url) and it worked! Well, kind of:

+

Browser error

+

That file has the audio processor code, so why does it get served with Content-Type: video/mp2t?

+

Floundering about

+

Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to just use JavaScript and stuck by the original TypeScript requirement.

+

I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package.

+

I tried three different CRA tools - react-app-rewired, craco, customize-react-app - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well.

+

I tried changing the webpack configuration: using new loaders, setting asset rules, even changing how webpack detects worker resources. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up.

+

I tried so many application frameworks. Next.js looked like a good candidate, but added its own bespoke webpack complexity to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work.

+

Learning and reflecting

+

I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned.

+

For myself:

+
    +
  • I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work
  • +
  • I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts
  • +
+

For the tools:

+
    +
  • Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity
  • +
  • Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaks
  • +
  • There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it
  • +
+

In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down.

\ No newline at end of file diff --git a/2015/11/autocallable/index.html b/2015/11/autocallable/index.html new file mode 100644 index 0000000..5530117 --- /dev/null +++ b/2015/11/autocallable/index.html @@ -0,0 +1,95 @@ +Autocallable Bonds | The Old Speice Guy
Skip to main content

Autocallable Bonds

· 12 min read
Bradlee Speice

For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.

+

My only non-core class this semester has been in Structure Products. We've been surveying a wide variety of products, and the final project was to pick one to report on. +Because these are all very similar, we decided to demonstrate all 3 products at once.

+

What follows below is a notebook demonstrating the usage of Julia for Monte-Carlo simulation of some exotic products.

+
+
using Gadfly
+

Athena/Phoenix Simulation

+

Underlying simulation

+

In order to price the autocallable bonds, we need to simulate the underlying assets. Let's go ahead and set up the simulation first, as this lays the foundation for what we're trying to do. We're going to use JNJ as the basis for our simulation. This implies the following parameters:

+
    +
  • S0S_0 = $102.2 (as of time of writing)
  • +
  • qq = 2.84%
  • +
  • rr = [.49, .9, 1.21, 1.45, 1.69] (term structure as of time of writing, linear interpolation)
  • +
  • μ\mu = rqr - q (note that this implies a negative drift because of current low rates)
  • +
  • σ\sigma = σimp\sigma_{imp} = 15.62% (from VIX implied volatility)
  • +
+

We additionally define some parameters for simulation:

+
    +
  • T: The number of years to simulate
  • +
  • m: The number of paths to simulate
  • +
  • n: The number of steps to simulate in a year
  • +
+
S0 = 102.2
nominal = 100
q = 2.84 / 100
σ = 15.37 / 100
term = [0, .49, .9, 1.21, 1.45, 1.69] / 100 + 1

###
# Potential: Based on PEP
# S0 = 100.6
# σ = 14.86
# q = 2.7
###

# Simulation parameters
T = 5 # Using years as the unit of time
n = 250 # simulations per year
m = 100000 # paths
num_simulations = 5; # simulation rounds per price
+

Defining the simulation

+

To make things simpler, we simulate a single year at a time. This allows us to easily add in a dividend policy without too much difficulty, and update the simulation every year to match the term structure. The underlying uses GBM for simulation between years.

+
simulate_gbm = function(S0, μ, σ, T, n)
# Set the initial state
m = length(S0)
t = T / n
motion = zeros(m, n)
motion[:,1] = S0

# Build out all states
for i=1:(n-1)
motion[:,i+1] = motion[:,i] .* exp((μ - σ^2/2)*t) .* exp(sqrt(t) * σ .* randn(m))
end

return motion
end

function display_motion(motion, T)
# Given a matrix of paths, display the motion
n = length(motion[1,:])
m = length(motion[:,1])
x = repmat(1:n, m)

# Calculate the ticks we're going to use. We'd like to
# have an xtick every month, so calculate where those
# ticks will actually be at.
if (T > 3)
num_ticks = T
xlabel = "Years"
else
num_ticks = T * 12
xlabel = "Months"
end
tick_width = n / num_ticks
x_ticks = []
for i=1:round(num_ticks)
x_ticks = vcat(x_ticks, i*tick_width)
end

# Use one color for each path. I'm not sure if there's
# a better way to do this without going through DataFrames
colors = []
for i = 1:m
colors = vcat(colors, ones(n)*i)
end

plot(x=x, y=motion', color=colors, Geom.line,
Guide.xticks(ticks=x_ticks, label=false),
Guide.xlabel(xlabel),
Guide.ylabel("Value"))
end;
+

Example simulation

+

Let's go ahead and run a sample simulation to see what the functions got us!

+
initial = ones(5) * S0
# Using μ=0, T=.25 for now, we'll use the proper values later
motion = simulate_gbm(initial, 0, σ, .25, 200)

display_motion(motion, .25)
+

+

Computing the term structure

+

Now that we've got the basic motion set up, let's start making things a bit more sophisticated for the model. We're going to assume that the drift of the stock is the difference between the implied forward rate and the quarterly dividend rate.

+

We're given the yearly term structure, and need to calculate the quarterly forward rate to match this structure. The term structure is assumed to follow:

+

d(0,t)=d(0,t1)fi1,id(0, t) = d(0,t-1)\cdot f_{i-1, i}

+

Where fi1,if_{i-1, i} is the quarterly forward rate.

+
forward_term = function(yearly_term)
# It is assumed that we have a yearly term structure passed in, and starts at year 0
# This implies a nominal rate above 0 for the first year!
years = length(term)-1 # because we start at 0
structure = [(term[i+1] / term[i]) for i=1:years]
end;
+

Illustrating the term structure

+

Now that we've got our term structure, let's validate that we're getting the correct results! If we've done this correctly, then:

+
term[2] == term[1] * structure[1]
+
# Example term structure taken from:
# http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield
# Linear interpolation used years in-between periods, assuming real-dollar
# interest rates
forward_yield = forward_term(term)
calculated_term2 = term[1] * forward_yield[1]

println("Actual term[2]: $(term[2]); Calculated term[2]: $(calculated_term2)")
+
    Actual term[2]: 1.0049; Calculated term[2]: 1.0049
+

The full underlying simulation

+

Now that we have the term structure set up, we can actually start doing some real simulation! Let's construct some paths through the full 5-year time frame. In order to do this, we will simulate 1 year at a time, and use the forward rates at those times to compute the drift. Thus, there will be 5 total simulations batched together.

+
full_motion = ones(5) * S0
full_term = vcat(term[1], forward_yield)
for i=1:T
μ = (full_term[i] - 1 - q)
year_motion = simulate_gbm(full_motion[:,end], μ, σ, 1, n)
full_motion = hcat(full_motion, year_motion)
end

display_motion(full_motion, T)
+

+

Final simulation

+

We're now going to actually build out the full motion that we'll use for computing the pricing of our autocallable products. It will be largely the same, but we will use far more sample paths for the simulation.

+
full_simulation = function(S0, T, n, m, term)
forward = vcat(term[1], forward_term(term))

# And an S0 to kick things off.
final_motion = ones(m) * S0
for i=1:T
μ = (forward[i] - 1 - q)
year_motion = simulate_gbm(final_motion[:,end], μ, σ, 1, n)
final_motion = hcat(final_motion, year_motion)
end
return final_motion
end

tic()
full_simulation(S0, T, n, m, term)
time = toq()
@printf("Time to run simulation: %.2fs", time)
+
    Time to run simulation: 5.34s
+

Athena Simulation

+

Now that we've defined our underlying simulation, let's actually try and price an Athena note. Athena has the following characteristics:

+
    +
  • Automatically called if the underlying is above the call barrier at observation
  • +
  • Accelerated coupon paid if the underlying is above the call barrier at observation +
      +
    • The coupon paid is cic \cdot i with ii as the current year, and cc the coupon rate
    • +
    +
  • +
  • Principle protection up until a protection barrier at observation; All principle at risk if this barrier not met
  • +
  • Observed yearly
  • +
+
call_barrier = S0
strike = S0
protection_barrier = S0 * .6
coupon = nominal * .07

price_athena = function(initial_price, year_prices, call_barrier,
protection_barrier, coupon, forward_structure)

total_coupons = 0

t = length(year_prices)

for i=1:t
price = year_prices[i]
if price call_barrier
return (nominal + coupon*i) * exp((prod(forward_structure[i:end])-1)*(t-i))
end
end

# We've reached maturity, time to check capital protection
if year_prices[end] > protection_barrier
return nominal
else
put = (strike - year_prices[end]) / strike
return nominal*(1-put)
end
end

forward_structure = forward_term(term)
price_function = (year_prices) -> price_athena(S0, year_prices,
call_barrier, protection_barrier, coupon, forward_structure)

athena = function()
year_indexes = [n*i for i=1:T]
motion = full_simulation(S0, T, n, m, term)
payoffs = [price_function(motion[i, year_indexes]) for i=1:m]
return mean(payoffs)
end

mean_payoffs = zeros(num_simulations)
for i=1:num_simulations
tic()
mean_payoffs[i] = athena()
time = toq()
@printf("Mean of simulation %i: \$%.4f; Simulation time: %.2fs\n", i, mean_payoffs[i], time)
end

final_mean = mean(mean_payoffs)
println("Mean over $num_simulations simulations: $(mean(mean_payoffs))")
pv = final_mean * (exp(-(prod(forward_structure)-1)*T))
@printf("Present value of Athena note: \$%.2f, notional: \$%.2f", pv, nominal)
+
    Mean of simulation 1: $103.2805; Simulation time: 5.59s
Mean of simulation 2: $103.3796; Simulation time: 5.05s
Mean of simulation 3: $103.4752; Simulation time: 5.18s
Mean of simulation 4: $103.4099; Simulation time: 5.37s
Mean of simulation 5: $103.3260; Simulation time: 5.32s
Mean over 5 simulations: 103.37421610015554
Present value of Athena note: $95.00, notional: $100.00
+

Phoenix without Memory Simulation

+

Let's move into pricing a Phoenix without memory. It's very similar to the Athena production, with the exception that we introduce a coupon barrier so coupons are paid even when the underlying is below the initial price.

+

The Phoenix product has the following characteristics (example here):

+
    +
  • Automatically called if the underlying is above the call barrier at observation
  • +
  • Coupon paid if the underlying is above a coupon barrier at observation
  • +
  • Principle protection up until a protection barrier at observation; All principle at risk if this barrier not met
  • +
  • Observed yearly
  • +
+

Some example paths (all assume that a call barrier of the current price, and coupon barrier some level below that):

+
    +
  • At the end of year 1, the stock is above the call barrier; the note is called and you receive the value of the stock plus the coupon being paid.
  • +
  • At the end of year 1, the stock is above the coupon barrier, but not the call barrier; you receive the coupon. At the end of year 2, the stock is below the coupon barrier; you receive nothing. At the end of year 3, the stock is above the call barrier; the note is called and you receive the value of the stock plus a coupon for year 3.
  • +
+

We're going to re-use the same simulation, with the following parameters:

+
    +
  • Call barrier: 100%
  • +
  • Coupon barrier: 70%
  • +
  • Coupon: 6%
  • +
  • Capital protection until 70% (at maturity)
  • +
+
call_barrier = S0
coupon_barrier = S0 * .8
protection_barrier = S0 * .6
coupon = nominal * .06

price_phoenix_no_memory = function(initial_price, year_prices, call_barrier, coupon_barrier,
protection_barrier, coupon, forward_structure)

total_coupons = 0
t = length(year_prices)

for i=1:t
price = year_prices[i]
if price call_barrier
return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))
elseif price coupon_barrier
total_coupons = total_coupons * exp(forward_structure[i]-1) + coupon
else
total_coupons *= exp(forward_structure[i]-1)
end
end

# We've reached maturity, time to check capital protection
if year_prices[end] > protection_barrier
return nominal + total_coupons
else
put = (strike - year_prices[end]) / strike
return nominal*(1-put)
end
end

forward_structure = forward_term(term)
price_function = (year_prices) -> price_phoenix_no_memory(S0, year_prices,
call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)

phoenix_no_memory = function()
year_indexes = [n*i for i=1:T]
motion = full_simulation(S0, T, n, m, term)
payoffs = [price_function(motion[i, year_indexes]) for i=1:m]
return mean(payoffs)
end

mean_payoffs = zeros(num_simulations)
for i=1:num_simulations
tic()
mean_payoffs[i] = phoenix_no_memory()
time = toq()
@printf("Mean of simulation %i: \$%.4f; Simulation time: %.2fs\n", i, mean_payoffs[i], time)
end

final_mean = mean(mean_payoffs)
println("Mean over $num_simulations simulations: $(mean(mean_payoffs))")
pv = final_mean * exp(-(prod(forward_structure)-1)*(T))
@printf("Present value of Phoenix without memory note: \$%.2f", pv)
+
    Mean of simulation 1: $106.0562; Simulation time: 5.72s
Mean of simulation 2: $106.0071; Simulation time: 5.85s
Mean of simulation 3: $105.9959; Simulation time: 5.87s
Mean of simulation 4: $106.0665; Simulation time: 5.93s
Mean of simulation 5: $106.0168; Simulation time: 5.81s
Mean over 5 simulations: 106.02850857209883
Present value of Phoenix without memory note: $97.44
+

Phoenix with Memory Simulation

+

The Phoenix with Memory structure is very similar to the Phoenix, but as the name implies, has a special "memory" property: It remembers any coupons that haven't been paid at prior observation times, and pays them all if the underlying crosses the coupon barrier. For example:

+
    +
  • Note issued with 100% call barrier, 70% coupon barrier. At year 1, the underlying is at 50%, so no coupons are paid. At year 2, the underlying is at 80%, so coupons for both year 1 and 2 are paid, resulting in a double coupon.
  • +
+

You can also find an example here.

+

Let's go ahead and set up the simulation! The parameters will be the same, but we can expect that the value will go up because of the memory attribute

+
call_barrier = S0
coupon_barrier = S0 * .8
protection_barrier = S0 * .6
coupon = nominal * .07

price_phoenix_with_memory = function(initial_price, year_prices, call_barrier,
coupon_barrier, protection_barrier, coupon, forward_structure)

last_coupon = 0
total_coupons = 0

t = length(year_prices)

for i=1:t
price = year_prices[i]
if price > call_barrier
return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))
elseif price > coupon_barrier
####################################################################
# The only difference between with/without memory is the below lines
memory_coupons = (i - last_coupon) * coupon
last_coupon = i
total_coupons = total_coupons * exp(forward_structure[i]-1) + memory_coupons
####################################################################
else
total_coupons *= exp(forward_structure[i]-1)
end
end

# We've reached maturity, time to check capital protection
if year_prices[end] > protection_barrier
return nominal + total_coupons
else
put = (strike - year_prices[end]) / strike
return nominal*(1-put)
end
end

forward_structure = forward_term(term)
price_function = (year_prices) -> price_phoenix_with_memory(S0, year_prices,
call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)

phoenix_with_memory = function()
year_indexes = [n*i for i=1:T]
motion = full_simulation(S0, T, n, m, term)
payoffs = [price_function(motion[i, year_indexes]) for i=1:m]
return mean(payoffs)
end

mean_payoffs = zeros(num_simulations)
for i=1:num_simulations
tic()
mean_payoffs[i] = phoenix_with_memory()
time = toq()
@printf("Mean of simulation %i: \$%.4f; Simulation time: %.2fs\n",
i, mean_payoffs[i], time)
end

final_mean = mean(mean_payoffs)
println("Mean over $num_simulations simulations: $(mean(mean_payoffs))")
pv = final_mean * exp(-(prod(forward_structure)-1)*(T))
@printf("Present value of Phoenix with memory note: \$%.2f", pv)
+
    Mean of simulation 1: $108.8612; Simulation time: 5.89s
Mean of simulation 2: $109.0226; Simulation time: 5.90s
Mean of simulation 3: $108.9175; Simulation time: 5.92s
Mean of simulation 4: $108.9426; Simulation time: 5.94s
Mean of simulation 5: $108.8087; Simulation time: 6.06s
Mean over 5 simulations: 108.91052564051816
Present value of Phoenix with memory note: $100.09
\ No newline at end of file diff --git a/2015/11/welcome/index.html b/2015/11/welcome/index.html new file mode 100644 index 0000000..486ad2d --- /dev/null +++ b/2015/11/welcome/index.html @@ -0,0 +1,47 @@ +Welcome, and an algorithm | The Old Speice Guy
Skip to main content

Welcome, and an algorithm

· 5 min read
Bradlee Speice

Hello! Glad to meet you. I'm currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I'm working on!

+

To start things off, Columbia has been hosting a trading competition that myself and another partner are competing in. I'm including a notebook of the algorithm that we're using, just to give a simple overview of a miniature algorithm.

+

The competition is scored in 3 areas:

+ +

Our algorithm uses a basic momentum strategy: in the given list of potential portfolios, pick the stocks that have been performing well in the past 30 days. Then, optimize for return subject to the drawdown being below a specific level. We didn't include the Sharpe ratio as a constraint, mostly because we were a bit late entering the competition.

+

I'll be updating this post with the results of our algorithm as they come along!

+
+

UPDATE 12/5/2015: Now that the competition has ended, I wanted to update how the algorithm performed. Unfortunately, it didn't do very well. I'm planning to make some tweaks over the coming weeks, and do another forward test in January.

+
    +
  • After week 1: Down .1%
  • +
  • After week 2: Down 1.4%
  • +
  • After week 3: Flat
  • +
+

And some statistics for all teams participating in the competition:

+
StatisticValue
Max Return74.1%
Min Return-97.4%
Average Return-.1%
Std Dev of Returns19.6%
+
+

Trading Competition Optimization

+

Goal: Max return given maximum Sharpe and Drawdown

+
from IPython.display import display
import Quandl
from datetime import datetime, timedelta

tickers = ['XOM', 'CVX', 'CLB', 'OXY', 'SLB']
market_ticker = 'GOOG/NYSE_VOO'
lookback = 30
d_col = 'Close'

data = {tick: Quandl.get('YAHOO/{}'.format(tick))[-lookback:] for tick in tickers}
market = Quandl.get(market_ticker)
+

Calculating the Return

+

We first want to know how much each ticker returned over the prior period.

+
returns = {tick: data[tick][d_col].pct_change() for tick in tickers}

display({tick: returns[tick].mean() for tick in tickers})
+
    {'CLB': -0.0016320202164526894,
'CVX': 0.0010319531629488911,
'OXY': 0.00093418904454400551,
'SLB': 0.00098431254720448159,
'XOM': 0.00044165797556096868}
+

Calculating the Sharpe ratio

+

Sharpe: RRMσ{R - R_M \over \sigma}

+

We use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive.

+
market_returns = market.pct_change()

sharpe = lambda ret: (ret.mean() - market_returns[d_col].mean()) / ret.std()
sharpes = {tick: sharpe(returns[tick]) for tick in tickers}

display(sharpes)
+
    {'CLB': -0.10578734457846127,
'CVX': 0.027303529817677398,
'OXY': 0.022622210057414487,
'SLB': 0.026950946344858676,
'XOM': -0.0053519259698605499}
+

Calculating the drawdown

+

This one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change?

+
drawdown = lambda ret: ret.abs().max()
drawdowns = {tick: drawdown(returns[tick]) for tick in tickers}

display(drawdowns)
+
    {'CLB': 0.043551495607375035,
'CVX': 0.044894389686214398,
'OXY': 0.051424517867144637,
'SLB': 0.034774627850375328,
'XOM': 0.035851524605672758}
+

Performing the optimization

+max  μωs.t.  1ω=1SωsDωdωl\begin{align*} +max\ \ & \mu \cdot \omega\\ +s.t.\ \ & \vec{1} \omega = 1\\ +& \vec{S} \omega \ge s\\ +& \vec{D} \cdot | \omega | \le d\\ +& \left|\omega\right| \le l\\ +\end{align*} +

We want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don't have huge long/short positions.

+
import numpy as np
from scipy.optimize import minimize

#sharpe_limit = .1
drawdown_limit = .05
leverage = 250

# Use the map so we can guarantee we maintain the correct order

# So we can write as upper-bound
# sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1
dd_a = np.array(list(map(lambda tick: drawdowns[tick], tickers)))

# Because minimizing
returns_a = np.array(list(map(lambda tick: returns[tick].mean(), tickers)))

meets_sharpe = lambda x: sum(abs(x) * sharpe_a) - sharpe_limit
def meets_dd(x):
portfolio = sum(abs(x))
if portfolio < .1:
# If there are no stocks in the portfolio,
# we can accidentally induce division by 0,
# or division by something small enough to cause infinity
return 0

return drawdown_limit - sum(abs(x) * dd_a) / sum(abs(x))

is_portfolio = lambda x: sum(x) - 1

def within_leverage(x):
return leverage - sum(abs(x))

objective = lambda x: sum(x * returns_a) * -1 # Because we're minimizing
bounds = ((None, None),) * len(tickers)
x = np.zeros(len(tickers))

constraints = [
{
'type': 'eq',
'fun': is_portfolio
}, {
'type': 'ineq',
'fun': within_leverage
#}, {
# 'type': 'ineq',
# 'fun': meets_sharpe
}, {
'type': 'ineq',
'fun': meets_dd
}
]

optimal = minimize(objective, x, bounds=bounds, constraints=constraints,
options={'maxiter': 500})

# Optimization time!
display(optimal.message)

display("Holdings: {}".format(list(zip(tickers, optimal.x))))

# multiply by -100 to scale, and compensate for minimizing
expected_return = optimal.fun * -100
display("Expected Return: {:.3f}%".format(expected_return))

expected_drawdown = sum(abs(optimal.x) * dd_a) / sum(abs(optimal.x)) * 100
display("Expected Max Drawdown: {0:.2f}%".format(expected_drawdown))

# TODO: Calculate expected Sharpe
+
    'Optimization terminated successfully.'
"Holdings: [('XOM', 5.8337945679814904),
('CVX', 42.935064321851307),
('CLB', -124.5),
('OXY', 36.790387773552119),
('SLB', 39.940753336615096)]"
'Expected Return: 32.375%'
'Expected Max Drawdown: 4.34%'
\ No newline at end of file diff --git a/2015/12/testing-cramer/index.html b/2015/12/testing-cramer/index.html new file mode 100644 index 0000000..b3f92db --- /dev/null +++ b/2015/12/testing-cramer/index.html @@ -0,0 +1,40 @@ +Testing Cramer | The Old Speice Guy
Skip to main content

Testing Cramer

· 9 min read
Bradlee Speice

Pursuant to attending a graduate school studying Financial Engineering, I've been a fan of the Mad Money TV show featuring the bombastic Jim Cramer. One of the things that he's said is that you shouldn't use the futures to predict where the stock market is going to go. But he says it often enough, I've begun to wonder - who is he trying to convince?

+

It makes sense that because futures on things like the S&P 500 are traded continuously, they would price in market information before the stock market opens. So is Cramer right to be convinced that strategies based on the futures are a poor idea? I wanted to test it out.

+

The first question is where to get the future's data. I've been part of Seeking Alpha for a bit, and they publish the Wall Street Breakfast newsletter which contains daily future's returns as of 6:20 AM EST. I'd be interested in using that data to see if we can actually make some money.

+

First though, let's get the data:

+

Downloading Futures data from Seeking Alpha

+

We're going to define two HTML parsing classes - one to get the article URL's from a page, and one to get the actual data from each article.

+
class ArticleListParser(HTMLParser):
"""Given a web page with articles on it, parse out the article links"""

articles = []

def handle_starttag(self, tag, attrs):
#if tag == 'div' and ("id", "author_articles_wrapper") in attrs:
# self.fetch_links = True
if tag == 'a' and ('class', 'dashboard_article_link') in attrs:
href = list(filter(lambda x: x[0] == 'href', attrs))[0][1]
self.articles.append(href)

base_url = "http://seekingalpha.com/author/wall-street-breakfast/articles"
article_page_urls = [base_url] + [base_url + '/{}'.format(i) for i in range(2, 20)]

global_articles = []
for page in article_page_urls:
# We need to switch the user agent, as SA blocks the standard requests agent
articles_html = requests.get(page,
headers={"User-Agent": "Wget/1.13.4"})
parser = ArticleListParser()
parser.feed(articles_html.text)
global_articles += (parser.articles)
+
class ArticleReturnParser(HTMLParser):
"Given an article, parse out the futures returns in it"

record_font_tags = False
in_font_tag = False
counter = 0
# data = {} # See __init__

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.data = {}

def handle_starttag(self, tag, attrs):
if tag == 'span' and ('itemprop', 'datePublished') in attrs:
date_string = list(filter(lambda x: x[0] == 'content', attrs))[0][1]
date = dtparser.parse(date_string)
self.data['date'] = date

self.in_font_tag = tag == 'font'

def safe_float(self, string):
try:
return float(string[:-1]) / 100
except ValueError:
return np.NaN

def handle_data(self, content):
if not self.record_font_tags and "Futures at 6" in content:
self.record_font_tags = True

if self.record_font_tags and self.in_font_tag:
if self.counter == 0:
self.data['DOW'] = self.safe_float(content)
elif self.counter == 1:
self.data['S&P'] = self.safe_float(content)
elif self.counter == 2:
self.data['NASDAQ'] = self.safe_float(content)
elif self.counter == 3:
self.data['Crude'] = self.safe_float(content)
elif self.counter == 4:
self.data['Gold'] = self.safe_float(content)

self.counter += 1

def handle_endtag(self, tag):
self.in_font_tag = False

def retrieve_data(url):
sa = "http://seekingalpha.com"
article_html = requests.get(sa + url,
headers={"User-Agent": "Wget/1.13.4"})
parser = ArticleReturnParser()
parser.feed(article_html.text)
parser.data.update({"url": url})
parser.data.update({"text": article_html.text})
return parser.data

# This copy **MUST** be in place. I'm not sure why,
# as you'd think that the data being returned would already
# represent a different memory location. Even so, it blows up
# if you don't do this.
article_list = list(set(global_articles))
article_data = [copy(retrieve_data(url)) for url in article_list]
# If there's an issue downloading the article, drop it.
article_df = pd.DataFrame.from_dict(article_data).dropna()
+

Fetching the Returns data

+

Now that we have the futures data, we're going to compare across 4 different indices - the S&P 500 index, Dow Jones Industrial, Russell 2000, and NASDAQ 100. Let's get the data off of Quandl to make things easier!

+
# article_df is sorted by date, so we get the first row.
start_date = article_df.sort_values(by='date').iloc[0]['date'] - relativedelta(days=1)
SPY = Quandl.get("GOOG/NYSE_SPY", trim_start=start_date)
DJIA = Quandl.get("GOOG/AMS_DIA", trim_start=start_date)
RUSS = Quandl.get("GOOG/AMEX_IWM", trim_start=start_date)
NASDAQ = Quandl.get("GOOG/EPA_QQQ", trim_start=start_date)
+

Running the Comparison

+

There are two types of tests I want to determine: How accurate each futures category is at predicting the index's opening change over the close before, and predicting the index's daily return.

+

Let's first calculate how good each future is at predicting the opening return over the previous day. I expect that the futures will be more than 50% accurate, since the information is recorded 3 hours before the markets open.

+
def calculate_opening_ret(frame):
# I'm not a huge fan of the appending for loop,
# but it's a bit verbose for a comprehension
data = {}
for i in range(1, len(frame)):
date = frame.iloc[i].name
prior_close = frame.iloc[i-1]['Close']
open_val = frame.iloc[i]['Open']
data[date] = (open_val - prior_close) / prior_close

return data

SPY_open_ret = calculate_opening_ret(SPY)
DJIA_open_ret = calculate_opening_ret(DJIA)
RUSS_open_ret = calculate_opening_ret(RUSS)
NASDAQ_open_ret = calculate_opening_ret(NASDAQ)

def signs_match(list_1, list_2):
# This is a surprisingly difficult task - we have to match
# up the dates in order to check if opening returns actually match
index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}

matches = []
for row in list_1.iterrows():
row_dt = row[1][1]
row_value = row[1][0]
index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)
if index_dt in list_2:
index_value = list_2[index_dt]
if (row_value > 0 and index_value > 0) or \
(row_value < 0 and index_value < 0) or \
(row_value == 0 and index_value == 0):
matches += [1]
else:
matches += [0]
#print("{}".format(list_2[index_dt]))
return matches


prediction_dict = {}
matches_dict = {}
count_dict = {}
index_dict = {"SPY": SPY_open_ret, "DJIA": DJIA_open_ret, "RUSS": RUSS_open_ret, "NASDAQ": NASDAQ_open_ret}
indices = ["SPY", "DJIA", "RUSS", "NASDAQ"]
futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"]
for index in indices:
matches_dict[index] = {future: signs_match(article_df[[future, 'date']],
index_dict[index]) for future in futures}
count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}
prediction_dict[index] = {future: np.mean(matches_dict[index][future])
for future in futures}
print("Articles Checked: ")
print(pd.DataFrame.from_dict(count_dict))
print()
print("Prediction Accuracy:")
print(pd.DataFrame.from_dict(prediction_dict))
+
    Articles Checked: 
DJIA NASDAQ RUSS SPY
Crude 268 268 271 271
DOW 268 268 271 271
Gold 268 268 271 271
NASDAQ 268 268 271 271
S&P 268 268 271 271

Prediction Accuracy:
DJIA NASDAQ RUSS SPY
Crude 0.544776 0.522388 0.601476 0.590406
DOW 0.611940 0.604478 0.804428 0.841328
Gold 0.462687 0.455224 0.464945 0.476015
NASDAQ 0.615672 0.608209 0.797048 0.830258
S&P 0.604478 0.597015 0.811808 0.848708
+

This data is very interesting. Some insights:

+
    +
  • Both DOW and NASDAQ futures are pretty bad at predicting their actual market openings
  • +
  • NASDAQ and Dow are fairly unpredictable; Russell 2000 and S&P are very predictable
  • +
  • Gold is a poor predictor in general - intuitively Gold should move inverse to the market, but it appears to be about as accurate as a coin flip.
  • +
+

All said though it appears that futures data is important for determining market direction for both the S&P 500 and Russell 2000. Cramer is half-right: futures data isn't very helpful for the Dow and NASDAQ indices, but is great for the S&P and Russell indices.

+

The next step - Predicting the close

+

Given the code we currently have, I'd like to predict the close of the market as well. We can re-use most of the code, so let's see what happens:

+
def calculate_closing_ret(frame):
# I'm not a huge fan of the appending for loop,
# but it's a bit verbose for a comprehension
data = {}
for i in range(0, len(frame)):
date = frame.iloc[i].name
open_val = frame.iloc[i]['Open']
close_val = frame.iloc[i]['Close']
data[date] = (close_val - open_val) / open_val

return data

SPY_close_ret = calculate_closing_ret(SPY)
DJIA_close_ret = calculate_closing_ret(DJIA)
RUSS_close_ret = calculate_closing_ret(RUSS)
NASDAQ_close_ret = calculate_closing_ret(NASDAQ)

def signs_match(list_1, list_2):
# This is a surprisingly difficult task - we have to match
# up the dates in order to check if opening returns actually match
index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}

matches = []
for row in list_1.iterrows():
row_dt = row[1][1]
row_value = row[1][0]
index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)
if index_dt in list_2:
index_value = list_2[index_dt]
if (row_value > 0 and index_value > 0) or \
(row_value < 0 and index_value < 0) or \
(row_value == 0 and index_value == 0):
matches += [1]
else:
matches += [0]
#print("{}".format(list_2[index_dt]))
return matches


matches_dict = {}
count_dict = {}
prediction_dict = {}
index_dict = {"SPY": SPY_close_ret, "DJIA": DJIA_close_ret,
"RUSS": RUSS_close_ret, "NASDAQ": NASDAQ_close_ret}
indices = ["SPY", "DJIA", "RUSS", "NASDAQ"]
futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"]
for index in indices:
matches_dict[index] = {future: signs_match(article_df[[future, 'date']],
index_dict[index]) for future in futures}
count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}
prediction_dict[index] = {future: np.mean(matches_dict[index][future])
for future in futures}

print("Articles Checked:")
print(pd.DataFrame.from_dict(count_dict))
print()
print("Prediction Accuracy:")
print(pd.DataFrame.from_dict(prediction_dict))
+
    Articles Checked:
DJIA NASDAQ RUSS SPY
Crude 268 268 271 271
DOW 268 268 271 271
Gold 268 268 271 271
NASDAQ 268 268 271 271
S&P 268 268 271 271

Prediction Accuracy:
DJIA NASDAQ RUSS SPY
Crude 0.533582 0.529851 0.501845 0.542435
DOW 0.589552 0.608209 0.535055 0.535055
Gold 0.455224 0.451493 0.483395 0.512915
NASDAQ 0.582090 0.626866 0.531365 0.538745
S&P 0.585821 0.608209 0.535055 0.535055
+

Well, it appears that the futures data is terrible at predicting market close. NASDAQ predicting NASDAQ is the most interesting data point, but 63% accuracy isn't accurate enough to make money consistently.

+

Final sentiments

+

The data bears out very close to what I expected would happen:

+
    +
  • Futures data is more accurate than a coin flip for predicting openings, which makes sense since it is recorded only 3 hours before the actual opening
  • +
  • Futures data is about as acccurate as a coin flip for predicting closings, which means there is no money to be made in trying to predict the market direction for the day given the futures data.
  • +
+

In summary:

+
    +
  • Cramer is half right: Futures data is not good for predicting the market open of the Dow and NASDAQ indices. Contrary to Cramer though, it is very good for predicting the S&P and Russell indices - we can achieve an accuracy slightly over 80% for each.
  • +
  • Making money in the market is hard. We can't just go to the futures and treat them as an oracle for where the market will close.
  • +
+

I hope you've enjoyed this, I quite enjoyed taking a deep dive in the analytics this way. I'll be posting more soon!

\ No newline at end of file diff --git a/2016/01/cloudy-in-seattle/index.html b/2016/01/cloudy-in-seattle/index.html new file mode 100644 index 0000000..a4bd74f --- /dev/null +++ b/2016/01/cloudy-in-seattle/index.html @@ -0,0 +1,41 @@ +Cloudy in Seattle | The Old Speice Guy
Skip to main content

Cloudy in Seattle

· 4 min read
Bradlee Speice

Building on prior analysis, is Seattle's reputation as a depressing city actually well-earned?

+
import pickle
import pandas as pd
import numpy as np
from bokeh.plotting import output_notebook, figure, show
from bokeh.palettes import RdBu4 as Palette
from datetime import datetime
import warnings

output_notebook()
+
BokehJS successfully loaded.
+

Examining other cities

+

After taking some time to explore how the weather in North Carolina stacked up over the past years, I was interested in doing the same analysis for other cities. Growing up with family from Binghamton, NY I was always told it was very cloudy there. And Seattle has a nasty reputation for being very depressing and cloudy. All said, the cities I want to examine are:

+
    +
  • Binghamton, NY
  • +
  • Cary, NC
  • +
  • Seattle, WA
  • +
  • New York City, NY
  • +
+

I'd be interested to try this analysis worldwide at some point - comparing London and Seattle might be an interesting analysis. For now though, we'll stick with trying out the US data.

+

There will be plenty of charts. I want to know: How has average cloud cover and precipitation chance changed over the years for each city mentioned? This will hopefully tell us whether Seattle has actually earned its reputation for being a depressing city.

+
city_forecasts = pickle.load(open('city_forecasts.p', 'rb'))
forecasts_df = pd.DataFrame.from_dict(city_forecasts)
+
cities = ['binghamton', 'cary', 'nyc', 'seattle']
city_colors = {cities[i]: Palette[i] for i in range(0, 4)}

def safe_cover(frame):
if frame and 'cloudCover' in frame:
return frame['cloudCover']
else:
return np.NaN

def monthly_avg_cloudcover(city, year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
cloud_cover_vals = list(map(lambda x: safe_cover(forecasts_df[city][x]['currently']), dates))
cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))
# Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below.
with warnings.catch_warnings():
warnings.simplefilter('ignore')
return np.nanmean(cloud_cover_vals), cloud_cover_samples
+
years = range(1990, 2016)
def city_avg_cc(city, month):
return [monthly_avg_cloudcover(city, y, month) for y in years]

months = [
('July', 7),
('August', 8),
('September', 9),
('October', 10),
('November', 11)
]

for month, month_id in months:
month_averages = {city: city_avg_cc(city, month_id) for city in cities}
f = figure(title="{} Average Cloud Cover".format(month),
x_axis_label='Year',
y_axis_label='Cloud Cover Percentage')
for city in cities:
f.line(years, [x[0] for x in month_averages[city]],
legend=city, color=city_colors[city])
show(f)
+

July average cloud cover chart +August average cloud cover chart +September average cloud cover chart +October average cloud cover chart +November average cloud cover chart

+

Well, as it so happens it looks like there are some data issues. July's data is a bit sporadic, and 2013 seems to be missing from most months as well. I think really only two things can really be confirmed here:

+
    +
  • Seattle, specifically for the months of October and November, is in fact significantly more cloudy on average than are other cities
  • +
  • All cities surveyed have seen average cloud cover decline over the months studied. There are data issues, but the trend seems clear.
  • +
+

Let's now move from cloud cover data to looking at average rainfall chance.

+
def safe_precip(frame):
if frame and 'precipProbability' in frame:
return frame['precipProbability']
else:
return np.NaN

def monthly_avg_precip(city, year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
precip_vals = list(map(lambda x: safe_precip(forecasts_df[city][x]['currently']), dates))
precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))
# Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below.
with warnings.catch_warnings():
warnings.simplefilter('ignore')
return np.nanmean(precip_vals), precip_samples

def city_avg_precip(city, month):
return [monthly_avg_precip(city, y, month) for y in years]

for month, month_id in months:
month_averages = {city: city_avg_cc(city, month_id) for city in cities}
f = figure(title="{} Average Precipitation Chance".format(month),
x_axis_label='Year',
y_axis_label='Precipitation Chance Percentage')
for city in cities:
f.line(years, [x[0] for x in month_averages[city]],
legend=city, color=city_colors[city])
show(f)
+

July average precipitation chance chart +August average precipitation chance chart +September average precipitation chance chart +October average precipitation chance chart +November average precipitation chance chart

+

The same data issue caveats apply here: 2013 seems to be missing some data, and July has some issues as well. However, this seems to confirm the trends we saw with cloud cover:

+
    +
  • Seattle, specifically for the months of August, October, and November has had a consistently higher chance of rain than other cities surveyed.
  • +
  • Average precipitation chance, just like average cloud cover, has been trending down over time.
  • +
+

Conclusion

+

I have to admit I was a bit surprised after doing this analysis. Seattle showed a higher average cloud cover and average precipitation chance than did the other cities surveyed. Maybe Seattle is actually an objectively more depressing city to live in.

+

Well that's all for weather data at the moment. It's been a great experiment, but I think this is about as far as I'll be able to get with weather data without some domain knowledge. Talk again soon!

\ No newline at end of file diff --git a/2016/01/complaining-about-the-weather/index.html b/2016/01/complaining-about-the-weather/index.html new file mode 100644 index 0000000..6953095 --- /dev/null +++ b/2016/01/complaining-about-the-weather/index.html @@ -0,0 +1,30 @@ +Complaining about the weather | The Old Speice Guy
Skip to main content

Complaining about the weather

· 8 min read
Bradlee Speice

Figuring out whether people should be complaining about the recent weather in North Carolina.

+
from bokeh.plotting import figure, output_notebook, show
from bokeh.palettes import PuBuGn9 as Palette
import pandas as pd
import numpy as np
from datetime import datetime
import pickle

output_notebook()
+
BokehJS successfully loaded.
+

I'm originally from North Carolina, and I've been hearing a lot of people talking about how often it's been raining recently. They're excited for any day that has sun.

+

So I got a bit curious: Has North Carolina over the past few months actually had more cloudy and rainy days recently than in previous years? This shouldn't be a particularly challenging task, but I'm interested to know if people's perceptions actually reflect reality.

+

The data we'll use comes from forecast.io, since they can give us a cloud cover percentage. I've gone ahead and retrieved the data to a pickle file, and included the code that was used to generate it. First up: What was the average cloud cover in North Carolina during August - November, and how many days were cloudy? We're going to assume that a "cloudy" day is defined as any day in which the cloud cover is above 50%.

+
city_forecasts = pickle.load(open('city_forecasts.p', 'rb'))
forecast_df = pd.DataFrame.from_dict(city_forecasts)
+
cary_forecast = forecast_df['cary']
years = range(1990, 2016)
months = range(7, 12)
months_str = ['July', 'August', 'September', 'October', 'November']

def safe_cover(frame):
if frame and 'cloudCover' in frame:
return frame['cloudCover']
else:
return np.NaN

def monthly_avg_cloudcover(year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates))
cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))
return np.nanmean(cloud_cover_vals), cloud_cover_samples


monthly_cover_vals = [[monthly_avg_cloudcover(y, m)[0] for y in years] for m in months]

f = figure(title='Monthly Average Cloud Cover',
x_range=(1990, 2015),
x_axis_label='Year')
for x in range(0, len(months)):
f.line(years, monthly_cover_vals[x], legend=months_str[x], color=Palette[x])
show(f)
+

Monthly average cloud cover chart

+

As we can see from the chart above, on the whole the monthly average cloud cover has been generally trending down over time. The average cloud cover is also lower than it was last year - it seems people are mostly just complaining. There are some data issues that start in 2012 that we need to be aware of - the cloud cover percentage doesn't exist for all days. Even so, the data that we have seems to reflect the wider trend, so we'll assume for now that the missing data doesn't skew our results.

+

There's one more metric we want to check though - how many cloudy days were there? This is probably a better gauge of sentiment than the average monthly cover.

+
def monthly_cloudy_days(year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates))
cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))
cloudy_days = [cover > .5 for cover in cloud_cover_vals]
return np.count_nonzero(cloudy_days), cloud_cover_samples

monthly_days_vals = [[monthly_cloudy_days(y, m)[0] for y in years] for m in months]
monthly_cover_samples = [[monthly_cloudy_days(y, m)[1] for y in years] for m in months]

f = figure(title='Monthly Cloudy Days',
x_range=(1990, 2015),
x_axis_label='Year')
for x in range(0, len(months)):
f.line(years, monthly_days_vals[x], legend=months_str[x], color=Palette[x])
show(f)

f = figure(title='Monthly Cloud Cover Samples',
x_range=(1990, 2015),
x_axis_label='Year',
height=300)
for x in range(0, len(months)):
f.line(years, monthly_cover_samples[x], legend=months_str[x], color=Palette[x])
show(f)
+

Monthly cloudy days chart

+

Monthly cloud cover samples chart

+

On the whole, the number of cloudy days seems to reflect the trend with average cloud cover - it's actually becoming more sunny as time progresses. That said, we need to be careful in how we view this number - because there weren't as many samples in 2015 as previous years, the number of days can get thrown off. In context though, even if most days not recorded were in fact cloudy, the overall count for 2015 would still be lower than previous years.

+

In addition to checking cloud cover, I wanted to check precipitation data as well - what is the average precipitation chance over a month, and how many days during a month is rain likely? The thinking is that days with a high-precipitation chance will also be days in which it is cloudy or depressing.

+
def safe_precip(frame):
if frame and 'precipProbability' in frame:
return frame['precipProbability']
else:
return np.NaN

def monthly_avg_precip(year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
precip_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates))
precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))
return np.nanmean(precip_vals), precip_samples

monthly_avg_precip_vals = [[monthly_avg_precip(y, m)[0] for y in years] for m in months]

f = figure(title='Monthly Average Precipitation Chance',
x_range=(1990, 2015),
x_axis_label='Year')
for x in range(0, len(months)):
f.line(years, monthly_avg_precip_vals[x], legend=months_str[x], color=Palette[x])
show(f)
+

Monthly average precipitation chance chart

+

As we can see from the chart, the average chance of precipitation over a month more or less stays within a band of 0 - .1 for all months over all years. This is further evidence that the past few months are no more cloudy or rainy than previous years. Like the cloud cover though, we still want to get a count of all the rainy days, in addition to the average chance. We'll define a "rainy day" as any day in which the chance of rain is greater than 25%.

+
def monthly_rainy_days(year, month):
dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),
end=datetime(year, month + 1, 1, 12),
freq='D', closed='left')
precip_prob_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates))
precip_prob_samples = len(list(filter(lambda x: x is not np.NaN, precip_prob_vals)))
precip_days = [prob > .25 for prob in precip_prob_vals]
return np.count_nonzero(precip_days), precip_prob_samples

monthly_precip_days_vals = [[monthly_rainy_days(y, m)[0] for y in years] for m in months]
monthly_precip_samples = [[monthly_rainy_days(y, m)[1] for y in years] for m in months]

f = figure(title='Monthly Rainy Days',
x_range=(1990, 2015),
x_axis_label='Year')
for x in range(0, len(months)):
f.line(years, monthly_precip_days_vals[x], legend=months_str[x], color=Palette[x])
show(f)

f = figure(title='Monthly Rainy Days Samples',
x_range=(1990, 2015),
x_axis_label='Year',
height=300)
for x in range(0, len(months)):
f.line(years, monthly_precip_samples[x], legend=months_str[x], color=Palette[x])
show(f)
+

Monthly rainy days chart

+

Monthly rainy days samples chart

+

After trying to find the number of days that are rainy, we can see that November hit its max value for rainy days in 2015. However, that value is 6, as compared to a previous maximum of 5. While it is a new record, the value isn't actually all that different. And for other months, the values are mostly in-line with the averages.

+

Summary and Conclusions

+

After having looked at forecast data for Cary, it appears that the months of July - November this year in terms of weather were at worst on par with prior years, if not slightly more sunny. This seems to be a case of confirmation bias: someone complains about a string of cloudy or rainy days, and suddenly you start noticing them more.

+

While this analysis doesn't take into account other areas of North Carolina, my initial guess would be to assume that other areas also will show similar results: nothing interesting is happening. Maybe that will be for another blog post later!

+

Coming soon: I'll compare rain/cloud conditions in North Carolina to some other places in the U.S.!

+

Generating the Forecast file

+

The following code was generates the file that was used throughout the blog post. Please note that I'm retrieving data for other cities to use in a future blog post, only Cary data was used for this post.

+
import pandas as pd
from functools import reduce
import requests
from datetime import datetime

# Coordinate data from http://itouchmap.com/latlong.html
cary_loc = (35.79154,-78.781117)
nyc_loc = (40.78306,-73.971249)
seattle_loc = (47.60621,-122.332071)
binghamton_loc = (42.098687,-75.917974)
cities = {
'cary': cary_loc,
'nyc': nyc_loc,
'seattle': seattle_loc,
'binghamton': binghamton_loc
}

apikey = '' # My super-secret API Key

def get_forecast(lat, long, date=None):
forecast_base = "https://api.forecast.io/forecast/"
if date is None:
url = forecast_base + apikey + '/{},{}'.format(lat, long)
else:
epoch = int(date.timestamp())
url = forecast_base + apikey + '/{},{},{}'.format(lat, long, epoch)

return requests.get(url).json()

years = range(1990,2016)
# For datetimes, the 12 is for getting the weather at noon.
# We're doing this over midnight because we're more concerned
# with what people see, and people don't typically see the weather
# at midnight.
dt_indices = [pd.date_range(start=datetime(year, 7, 1, 12),
end=datetime(year, 11, 30, 12))
for year in years]
dt_merge = reduce(lambda x, y: x.union(y), dt_indices)

# Because we have to pay a little bit to use the API, we use for loops here
# instead of a comprehension - if something breaks, we want to preserve the
# data already retrieved
city_forecasts = {}
for city, loc in cities.items():
print("Retrieving data for {} starting at {}".format(city,
datetime.now().strftime("%I:%M:%S %p")))
for dt in dt_merge:
try:
city_forecasts[(city, dt)] = get_forecast(*loc, dt)
except Exception as e:
print(e)
city_forecasts[(city, dt)] = None
print("End forecast retrieval: {}".format(datetime.now().strftime("%I:%M:%S %p")))

import pickle
pickle.dump(city_forecasts, open('city_forecasts.p', 'wb'))

### Output:
# Retrieving data for binghamton starting at 05:13:42 PM
# Retrieving data for seattle starting at 05:30:51 PM
# Retrieving data for nyc starting at 05:48:30 PM
# Retrieving data for cary starting at 06:08:32 PM
# End forecast retrieval: 06:25:21 PM
\ No newline at end of file diff --git a/2016/02/guaranteed-money-maker/index.html b/2016/02/guaranteed-money-maker/index.html new file mode 100644 index 0000000..d4e6766 --- /dev/null +++ b/2016/02/guaranteed-money-maker/index.html @@ -0,0 +1,75 @@ +Guaranteed money maker | The Old Speice Guy
Skip to main content

Guaranteed money maker

· 8 min read
Bradlee Speice

Developing an investment strategy based on the Martingale betting strategy

+

If you can see into the future, that is.

+

My previous class in Stochastic Calculus covered a lot of interesting topics, and the important one for today is the Gambler's Ruin problem. If you're interested in some of the theory behind it, also make sure to check out random walks. The important bit is that we studied the Martingale Betting Strategy, which describes for us a guaranteed way to eventually make money.

+

The strategy goes like this: You are going to toss a fair coin with a friend. If you guess heads or tails correctly, you get back double the money you bet. If you guess incorrectly, you lose money. How should you bet?

+

The correct answer is that you should double your bet each time you lose. Then when you finally win, you'll be guaranteed to make back everything you lost and then $1 extra! Consider the scenario:

+
    +
  1. You bet $1, and guess incorrectly. You're 1 dollar in the hole.
  2. +
  3. You bet $2, and guess incorrectly. You're 3 dollars in the hole now.
  4. +
  5. You bet $4, and guess incorrectly. You're 7 dollars in the hole.
  6. +
  7. You bet $8, and guess correctly! You now get back those 8 dollars you bet, plus 8 extra for winning, for a total profit of one dollar!
  8. +
+

Mathematically, we can prove that as long as you have unlimited money to bet, you are guaranteed to make money.

+

Applying the Martingale Strategy

+

But we're all realistic people, and once you start talking about "unlimited money" eyebrows should be raised. Even still, this is an interesting strategy to investigate, and I want to apply it to the stock market. As long as we can guarantee there's a single day in which the stock goes up, we should be able to make money right? The question is just how much we have to invest to guarantee this.

+

Now it's time for the math. We'll use the following definitions:

+
    +
  • oio_i = the share price at the opening of day ii
  • +
  • cic_i = the share price at the close of day ii
  • +
  • did_i = the amount of money we want to invest at the beginning of day ii
  • +
+

With those definitions in place, I'd like to present the formula that is guaranteed to make you money. I call it Bradlee's Investment Formula:

+

cni=1ndioi>i=1ndic_n \sum_{i=1}^n \frac{d_i}{o_i} > \sum_{i=1}^{n} d_i

+

It might not look like much, but if you can manage to make it so that this formula holds true, you will be guaranteed to make money. The intuition behind the formula is this: The closing share price times the number of shares you have purchased ends up greater than the amount of money you invested.

+

That is, on day nn, if you know what the closing price will be you can set up the amount of money you invest that day to guarantee you make money. I'll even teach you to figure out how much money that is! Take a look:

+cni=1n1dioi+cndnon>i=1n1di+dncndnondn>i=1n1(dicndioi)dn(cnonon)>i=1n1di(1cnoi)dn>oncnoni=1n1di(11oi)\begin{align*} +c_n \sum_{i=1}^{n-1} \frac{d_i}{o_i} + \frac{c_nd_n}{o_n} &> \sum_{i=1}^{n-1}d_i + d_n\\ +\frac{c_nd_n}{o_n} - d_n &> \sum_{i=1}^{n-1}(d_i - \frac{c_nd_i}{o_i})\\ +d_n (\frac{c_n - o_n}{o_n}) &> \sum_{i=1}^{n-1} d_i(1 - \frac{c_n}{o_i})\\ +d_n &> \frac{o_n}{c_n - o_n} \sum_{i=1}^{n-1} d_i(1 - \frac{1}{o_i}) +\end{align*} +

If you invest exactly dnd_n that day, you'll break even. But if you can make sure the money you invest is greater than that quantity on the right (which requires that you have a crystal ball tell you the stock's closing price) you are guaranteed to make money!

+

Interesting Implications

+

On a more serious note though, the formula above tells us a couple of interesting things:

+
    +
  1. It's impossible to make money without the closing price at some point being greater than the opening price (or vice-versa if you are short selling) - there is no amount of money you can invest that will turn things in your favor.
  2. +
  3. Close prices of the past aren't important if you're concerned about the bottom line. While chart technicians use price history to make judgment calls, in the end, the closing price on anything other than the last day is irrelevant.
  4. +
  5. It's possible to make money as long as there is a single day where the closing price is greater than the opening price! You might have to invest a lot to do so, but it's possible.
  6. +
  7. You must make a prediction about where the stock will close at if you want to know how much to invest. That is, we can set up our investment for the day to make money if the stock goes up 1%, but if it only goes up .5% we'll still lose money.
  8. +
  9. It's possible the winning move is to scale back your position. Consider the scenario: +
      +
    • You invest money and the stock closes down the day .5%
    • +
    • You invest tomorrow expecting the stock to go up 1%
    • +
    • The winning investment to break even (assuming a 1% increase) is to scale back the position, since the shares you purchased at the beginning would then be profitable
    • +
    +
  10. +
+

Running the simulation

+

So now that we've defined our investment formula,we need to tweak a couple things in order to make an investment strategy we can actually work with. There are two issues we need to address:

+
    +
  1. The formula only tells us how much to invest if we want to break even (dnd_n). If we actually want to turn a profit, we need to invest more than that, which we will refer to as the bias.
  2. +
  3. The formula assumes we know what the closing price will be on any given day. If we don't know this, we can still invest assuming the stock price will close at a level we choose. If the price doesn't meet this objective, we try again tomorrow! This predetermined closing price will be referred to as the expectation.
  4. +
+

Now that we've defined our bias and expectation, we can actually build a strategy we can simulate. Much like the martingale strategy told you to bet twice your previous bet in order to make money, we've designed a system that tells us how much to bet in order to make money as well.

+

Now, let's get to the code!

+
using Quandl
api_key = ""
daily_investment = function(current_open, current_close, purchase_history, open_history)
# We're not going to safeguard against divide by 0 - that's the user's responsibility
t1 = current_close / current_open - 1
t2 = sum(purchase_history - purchase_history*current_close ./ open_history)
return t2 / t1
end;
+

And let's code a way to run simulations quickly:

+
is_profitable = function(current_price, purchase_history, open_history)
shares = sum(purchase_history ./ open_history)
return current_price*shares > sum(purchase_history)
end

simulate = function(name, start, init, expected, bias)
ticker_info = quandlget(name, from=start, api_key=api_key)
open_vals = ticker_info["Open"].values
close_vals = ticker_info["Close"].values
invested = [init]

# The simulation stops once we've made a profit
day = 1
profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||
is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])
while !profitable
expected_close = open_vals[day+1] * expected
todays_purchase = daily_investment(open_vals[day+1], expected_close, invested, open_vals[1:day])
invested = [invested; todays_purchase + bias]
# expected_profit = expected_close * sum(invested ./ open_vals[1:length(invested)]) - sum(invested)
day += 1
profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||
is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])
end

shares = sum(invested ./ open_vals[1:length(invested)])
max_profit = max(close_vals[day], open_vals[day+1])
profit = shares * max_profit - sum(invested)
return (invested, profit)
end

sim_summary = function(investments, profit)
leverages = [sum(investments[1:i]) for i=1:length(investments)]
max_leverage = maximum(leverages) / investments[1]
println("Max leverage: $(max_leverage)")
println("Days invested: $(length(investments))")
println("Profit: $profit")
end;
+

Now, let's get some data and run a simulation! Our first test:

+
    +
  • We'll invest 100 dollars in LMT, and expect that the stock will close up 1% every day. We'll invest dnd_n + 10 dollars every day that we haven't turned a profit, and end the simulation once we've made a profit.
  • +
+
investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.01, 10)
sim_summary(investments, profit)
+
    Max leverage: 5.590373200042106
Days invested: 5
Profit: 0.6894803101560001
+

The result: We need to invest 5.6x our initial position over a period of 5 days to make approximately .69¢

+
    +
  • Now let's try the same thing, but we'll assume the stock closes up 2% instead.
  • +
+
investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.02, 10)
sim_summary(investments, profit)
+
    Max leverage: 1.854949900247809
Days invested: 25
Profit: 0.08304813163696423
+

In this example, we only get up to a 1.85x leveraged position, but it takes 25 days to turn a profit of 8¢

+

Summary

+

We've defined an investment strategy that can tell us how much to invest when we know what the closing position of a stock will be. We can tweak the strategy to actually make money, but plenty of work needs to be done so that we can optimize the money invested.

+

In the next post I'm going to post more information about some backtests and strategy tests on this strategy (unless of course this experiment actually produces a significant profit potential, and then I'm keeping it for myself).

+

Side note and disclaimer

+

The claims made in this presentation about being able to guarantee making money are intended as a joke and do not constitute investment advice of any sort.

\ No newline at end of file diff --git a/2016/02/profitability-using-the-investment-formula/index.html b/2016/02/profitability-using-the-investment-formula/index.html new file mode 100644 index 0000000..5d4150a --- /dev/null +++ b/2016/02/profitability-using-the-investment-formula/index.html @@ -0,0 +1,51 @@ +Profitability using the investment formula | The Old Speice Guy
Skip to main content

Profitability using the investment formula

· 8 min read
Bradlee Speice

After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?

+

I've previously talked about crafting an Investment Formula that would guarantee making money if you could predict which direction the stock market was going to go. This is going to be the first in a series of posts trying to flesh out what an actual investment strategy based on this formula would look like.

+

But first, the formula doesn't take into account two very important things: leverage, and the number of days invested. That's why I want to set up what I'm going to call the Profitability Score.

+

The definition is going to be very simple:

+
    +
  • pp: Profit made once you exit the investment
  • +
  • ii: Initial investment into the asset
  • +
  • mm: Maximum investment in the asset
  • +
  • l=m/il = m / i: The maximum leverage of an investment, as the ratio of maximum invested to initial investment
  • +
  • dd: The number of days it takes to turn a profit
  • +
+

s=1000pi(l+d)=1000pm+ids = \frac{1000 p}{i(l + d)} = \frac{1000 p}{m + i\cdot d}

+

Crazy, right? The score is simply the (normalized) profit you made divided by the leverage plus days invested. The 1000\cdot 1000 is just to turn the number into something more reasonable - people don't like hearing something with a profitability score of .001 for example.

+

Theoretical Justification

+

The formula itself is designed to be simple in principle: I like making a profit, and I want to penalize the leverage you incur and days you have to invest. Ideally, we want to have a stock that goes up all the time. However, the investment formula takes advantage of a different case: trying to profit from highly volatile assets. If we can make money when the investment only has one day up, let's do it!

+

Even so, there are two potential issues: First, stocks that trend upward will have a higher profitability score - both leverage and days invested will be 1. To protect against only investing in this trend, I can do things like taking log(d)\log(d). I don't want to start biasing the scoring function until I have a practical reason to do so, so right now I'll leave it standing.

+

The second issue is how to penalize leverage and days invested relative to each other. As it currently stands, a leverage of 6x with only 1 day invested is the same as leveraging 2x with 3 days invested. In the future, I'd again want to look at making the impact of days invested smaller - I can get over an extra 3 days in the market if it means that I don't have to incur a highly leveraged position.

+

So there could be things about the scoring function we change in the future, but I want to run some actual tests before we start worrying about things like that!

+

Running a simulation

+

This won't be an incredibly rigorous backtest, I just want to see some results from the work so far. Let's set up the simulation code again, and start looking into some random stocks. If you've read the last blog post, you can skip over the code. The only difference is that it's been ported to python to make the data-wrangling easier. Julia doesn't yet support some of the multi-index things I'm trying to do.

+
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from Quandl import get as qget
%matplotlib inline
api_key = ''

profitability = lambda p, i, m, d: 1000*p / (m + i*d)

def is_profitable(current_price, purchase_history, open_history):
shares = (purchase_history / open_history).sum()
return current_price * shares > sum(purchase_history)

def daily_investment(current_open, current_close, purchase_history, open_history):
t1 = current_close / current_open - 1
t2 = (purchase_history - purchase_history * current_close / open_history).sum()
return t2 / t1

def simulate_day(open_vals, close_vals, init, expected, bias):
invested = np.array([init])

day = 1
profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \
or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])

while not profitable:
expected_close = open_vals[day] * expected
todays_purchase = daily_investment(open_vals[day], expected_close, invested, open_vals[0:day])
invested = np.append(invested, todays_purchase + bias)
# expected_profit = expected_close * (invested / open_vals[0:len(invested)]).sum() - invested.sum()
day += 1
profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \
or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])

shares = (invested / open_vals[0:len(invested)]).sum()

# Make sure we can't see into the future - we know either today's close or tomorrow's open
# will be profitable, but we need to check which one.
if is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]):
ending_price = close_vals[day-1]
else:
ending_price = open_vals[day]

profit = shares * ending_price - sum(invested)
return invested, profit

def simulate_ts(name, start, end, initial, expected, bias):
ticker_info = qget(name, trim_start=start, api_key=api_key)
evaluation_times = ticker_info[:end].index

# Handle Google vs. YFinance data
if "Adjusted Close" in ticker_info.columns:
close_column = "Adjusted Close"
else:
close_column = "Close"

sim = {d: simulate_day(ticker_info[d:]["Open"], ticker_info[d:][close_column],
100, 1.02, 10) for d in evaluation_times}
sim_series = pd.Series(sim)
result = pd.DataFrame()
result["profit"] = sim_series.apply(lambda x: x[1])
result["max"] = sim_series.apply(lambda x: max(x[0]))
result["days"] = sim_series.apply(lambda x: len(x[0]))
result["score"] = sim_series.apply(lambda x: profitability(x[1], x[0][0], max(x[0]), len(x[0])))
result["investments"] = sim_series.apply(lambda x: x[0])

return result

def simulate_tickers(tickers):
from datetime import datetime
results = {}
for ticker in tickers:
start = datetime(2015, 1, 1)
results_df = simulate_ts(ticker, start, datetime(2016, 1, 1), 100, 1.01, 10)
results[ticker] = results_df

return pd.concat(list(results.values()), keys=list(results.keys()), axis=1)
+

And now the interesting part

+

Let's start looking into the data! FANG stocks have been big over the past year, let's see how they look:

+
fang_df = simulate_tickers(["YAHOO/FB", "YAHOO/AAPL", "YAHOO/NFLX", "YAHOO/GOOG"])
+
fang_df.xs('days', axis=1, level=1).hist()
plt.gcf().set_size_inches(18, 8);
plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18);
+

png

+
fang_df.xs('score', axis=1, level=1).plot()
plt.gcf().set_size_inches(18, 6)
plt.gcf().suptitle("Profitability score over time", fontsize=18);
+

png

+

Let's think about these graphs. First, the histogram. What we like seeing is a lot of 1's - that means there were a lot of days that the stock went up and we didn't have to worry about actually implementing the strategy - we were able to close the trade at a profit.

+

Looking at the profitability score over time though is a bit more interesting. First off, stocks that are more volatile will tend to have a higher profitability score, no two ways about that. However, Netflix consistently outperformed on this metric. We know that 2015 was a good year for Netflix, so that's a (small) sign the strategy is performing as expected.

+

The final interesting note happens around the end of August 2015. Around this period, the markets were selling off in a big way due to issues in China (not unlike what's happening now). Even so, all of the FANG stocks saw an uptick in profitability around this time. This is another sign that the strategy being developed performs better during periods of volatility, rather than from riding markets up or down.

+

What about FANG vs. some cyclicals?

+
cyclic_df = simulate_tickers(["YAHOO/X", "YAHOO/CAT", "YAHOO/NFLX", "YAHOO/GOOG"])
+
cyclic_df.xs('days', axis=1, level=1).hist()
plt.gcf().set_size_inches(18, 8);
plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18);
+

png

+
cyclic_df.xs('score', axis=1, level=1).plot()
plt.gcf().set_size_inches(18, 6)
plt.gcf().suptitle("Profitability score over time", fontsize=18);
+

png

+

Some more interesting results come from this as well. First off, US Steel (X) has a much smoother distribution of days until profitability - it doesn't have a huge number of values at 1 and then drop off. Intuitively, we're not terribly large fans of this, we want a stock to go up! However, on the profitability score it is the only serious contender to Netflix.

+

Second, we see the same trend around August - the algorithm performs well in volatile markets.

+

For a final test, let's try some biotech and ETFs!

+
biotech_df = simulate_tickers(['YAHOO/REGN', 'YAHOO/CELG', 'GOOG/NASDAQ_BIB', 'GOOG/NASDAQ_IBB'])
+
biotech_df.xs('days', axis=1, level=1).hist()
plt.gcf().set_size_inches(18, 8);
plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18);
+

png

+
biotech_df.xs('score', axis=1, level=1).plot()
plt.gcf().set_size_inches(18, 6)
plt.gcf().suptitle("Profitability score over time", fontsize=18);
+

png

+

In this example, we don't see a whole lot of interesting things: the scores are all fairly close together with notable exceptions in late August, and mid-October.

+

What is interesting is that during the volatile period, the ETF's performed significantly better than the stocks did in terms of profitability. The leveraged ETF (BIB) performed far above anyone else, and it appears that indeed, it is most profitable during volatile periods. Even so, it was far more likely to take multiple days to give a return. Its count of 1-day investments trails the other ETF and both stocks by a decent margin.

+

And consider me an OCD freak, but I just really like Celgene's distribution - it looks nice and smooth.

+

Summary and plans for the next post

+

So far I'm really enjoying playing with this strategy - there's a lot of depth here to understand, though the preliminary results seem to indicate that it profits mostly from taking the other side of a volatile trade. I'd be interested to run results later on data from January - It's been a particularly volatile start to the year so it would be neat to see whether this strategy would work then.

+

For the next post, I want to start playing with some of the parameters: How do the bias and expected close influence the process? The values have been fairly conservative so far, it will be interesting to see how the simulations respond afterward.

\ No newline at end of file diff --git a/2016/03/predicting-santander-customer-happiness/index.html b/2016/03/predicting-santander-customer-happiness/index.html new file mode 100644 index 0000000..c6be51a --- /dev/null +++ b/2016/03/predicting-santander-customer-happiness/index.html @@ -0,0 +1,48 @@ +Predicting Santander customer happiness | The Old Speice Guy
Skip to main content

Predicting Santander customer happiness

· 7 min read
Bradlee Speice

My first Kaggle competition.

+

It's time! After embarking on a Machine Learning class this semester, and with a Saturday in which I don't have much planned, I wanted to put this class and training to work. It's my first competition submission. I want to walk you guys through how I'm approaching this problem, because I thought it would be really neat. The competition is Banco Santander's Santander Customer Satisfaction competition. It seemed like an easy enough problem I could actually make decent progress on it.

+

Data Exploration

+

First up: we need to load our data and do some exploratory work. Because we're going to be using this data for model selection prior to testing, we need to make a further split. I've already gone ahead and done this work, please see the code in the appendix below.

+
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# Record how long it takes to run the notebook - I'm curious.
from datetime import datetime
start = datetime.now()

dataset = pd.read_csv('split_train.csv')
dataset.index = dataset.ID
X = dataset.drop(['TARGET', 'ID', 'ID.1'], 1)
y = dataset.TARGET
+
y.unique()
+
    array([0, 1], dtype=int64)
+
len(X.columns)
+
    369
+

Okay, so there are only two classes we're predicting: 1 for unsatisfied customers, 0 for satisfied customers. I would have preferred this to be something more like a regression, or predicting multiple classes: maybe the customer isn't the most happy, but is nowhere near closing their accounts. For now though, that's just the data we're working with.

+

Now, I'd like to make a scatter matrix of everything going on. Unfortunately as noted above, we have 369 different features. There's no way I can graphically make sense of that much data to start with.

+

We're also not told what the data actually represents: Are these survey results? Average time between contact with a customer care person? Frequency of contacting a customer care person? The idea is that I need to reduce the number of dimensions we're predicting across.

+

Dimensionality Reduction pt. 1 - Binary Classifiers

+

My first attempt to reduce the data dimensionality is to find all the binary classifiers in the dataset (i.e. 0 or 1 values) and see if any of those are good (or anti-good) predictors of the final data.

+
cols = X.columns
b_class = []
for c in cols:
if len(X[c].unique()) == 2:
b_class.append(c)

len(b_class)
+
    111
+

So there are 111 features in the dataset that are a binary label. Let's see if any of them are good at predicting the users satisfaction!

+
# First we need to `binarize` the data to 0-1; some of the labels are {0, 1},
# some are {0, 3}, etc.
from sklearn.preprocessing import binarize
X_bin = binarize(X[b_class])

accuracy = [np.mean(X_bin[:,i] == y) for i in range(0, len(b_class))]
acc_df = pd.DataFrame({"Accuracy": accuracy}, index=b_class)
acc_df.describe()
+
Accuracy
count111.000000
mean0.905159
std0.180602
min0.043598
25%0.937329
50%0.959372
75%0.960837
max0.960837
+

Wow! Looks like we've got some incredibly predictive features! So much so that we should be a bit concerned. My initial guess for what's happening is that we have a sparsity issue: so many of the values are 0, and these likely happen to line up with satisfied customers.

+

So the question we must now answer, which I likely should have asked long before now: What exactly is the distribution of un/satisfied customers?

+
unsat = y[y == 1].count()
print("Satisfied customers: {}; Unsatisfied customers: {}".format(len(y) - unsat, unsat))
naive_guess = np.mean(y == np.zeros(len(y)))
print("Naive guess accuracy: {}".format(naive_guess))
+
    Satisfied customers: 51131; Unsatisfied customers: 2083
Naive guess accuracy: 0.9608561656706882
+

This is a bit discouraging. A naive guess of "always satisfied" performs as well as our best individual binary classifier. What this tells me then, is that these data columns aren't incredibly helpful in prediction. I'd be interested in a polynomial expansion of this data-set, but for now, that's more computation than I want to take on.

+

Dimensionality Reduction pt. 2 - LDA

+

Knowing that our naive guess performs so well is a blessing and a curse:

+
    +
  • Curse: The threshold for performance is incredibly high: We can only "improve" over the naive guess by 4%
  • +
  • Blessing: All the binary classification features we just discovered are worthless on their own. We can throw them out and reduce the data dimensionality from 369 to 111.
  • +
+

Now, in removing these features from the dataset, I'm not saying that there is no "information" contained within them. There might be. But the only way we'd know is through a polynomial expansion, and I'm not going to take that on within this post.

+

My initial thought for a "next guess" is to use the LDA model for dimensionality reduction. However, it can only reduce dimensions to 1p1 - p, with pp being the number of classes. Since this is a binary classification, every LDA model that I try will have dimensionality one; when I actually try this, the predictor ends up being slightly less accurate than the naive guess.

+

Instead, let's take a different approach to dimensionality reduction: principle components analysis. This allows us to perform the dimensionality reduction without worrying about the number of classes. Then, we'll use a Gaussian Naive Bayes model to actually do the prediction. This model is chosen simply because it doesn't take a long time to fit and compute; because PCA will take so long, I just want a prediction at the end of this. We can worry about using a more sophisticated LDA/QDA/SVM model later.

+

Now into the actual process: We're going to test out PCA dimensionality reduction from 1 - 20 dimensions, and then predict using a Gaussian Naive Bayes model. The 20 dimensions upper limit was selected because the accuracy never improves after you get beyond that (I found out by running it myself). Hopefully, we'll find that we can create a model better than the naive guess.

+
from sklearn.naive_bayes import GaussianNB
from sklearn.decomposition import PCA

X_no_bin = X.drop(b_class, 1)

def evaluate_gnb(dims):
pca = PCA(n_components=dims)
X_xform = pca.fit_transform(X_no_bin)

gnb = GaussianNB()
gnb.fit(X_xform, y)
return gnb.score(X_xform, y)

dim_range = np.arange(1, 21)
plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy")
plt.axhline(naive_guess, label="Naive Guess", c='k')
plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k')
plt.gcf().set_size_inches(12, 6)
plt.legend();
+

png

+

sigh... After all the effort and computational power, we're still at square one: we have yet to beat out the naive guess threshold. With PCA in play we end up performing terribly, but not terribly enough that we can guess against ourselves.

+

Let's try one last-ditch attempt using the entire data set:

+
def evaluate_gnb_full(dims):
pca = PCA(n_components=dims)
X_xform = pca.fit_transform(X)

gnb = GaussianNB()
gnb.fit(X_xform, y)
return gnb.score(X_xform, y)

dim_range = np.arange(1, 21)
plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy")
plt.axhline(naive_guess, label="Naive Guess", c='k')
plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k')
plt.gcf().set_size_inches(12, 6)
plt.legend();
+

png

+

Nothing. It is interesting to note that the graphs are almost exactly the same: This would imply again that the variables we removed earlier (all the binary classifiers) indeed have almost no predictive power. It seems this problem is high-dimensional, but with almost no data that can actually inform our decisions.

+

Summary for Day 1

+

After spending a couple hours with this dataset, there seems to be a fundamental issue in play: We have very high-dimensional data, and it has no bearing on our ability to actually predict customer satisfaction. This can be a huge issue: it implies that no matter what model we use, we fundamentally can't perform well. I'm sure most of this is because I'm not an experienced data scientist. Even so, we have yet to develop a strategy that can actually beat out the village idiot; so far, the bank is best off just assuming all its customers are satisfied. Hopefully more to come soon.

+
end = datetime.now()
print("Running time: {}".format(end - start))
+
    Running time: 0:00:58.715714
+

Appendix

+

Code used to split the initial training data:

+
from sklearn.cross_validation import train_test_split
data = pd.read_csv('train.csv')
data.index = data.ID

data_train, data_validate = train_test_split(
data, train_size=.7)

data_train.to_csv('split_train.csv')
data_validate.to_csv('split_validate.csv')
\ No newline at end of file diff --git a/2016/03/tweet-like-me/index.html b/2016/03/tweet-like-me/index.html new file mode 100644 index 0000000..a1dbf92 --- /dev/null +++ b/2016/03/tweet-like-me/index.html @@ -0,0 +1,59 @@ +Tweet like me | The Old Speice Guy
Skip to main content

Tweet like me

· 9 min read
Bradlee Speice

In which I try to create a robot that will tweet like I tweet.

+

So, I'm taking a Machine Learning course this semester in school, and one of the topics we keep coming back to is natural language processing and the 'bag of words' data structure. That is, given a sentence:

+

How much wood would a woodchuck chuck if a woodchuck could chuck wood?

+

We can represent that sentence as the following list:

+

{ How: 1 much: 1 wood: 2 would: 2 a: 2 woodchuck: 2 chuck: 2 if: 1 }

+

Ignoring where the words happened, we're just interested in how often the words occurred. That got me thinking: I wonder what would happen if I built a robot that just imitated how often I said things? It's dangerous territory when computer scientists ask "what if," but I got curious enough I wanted to follow through.

+

The Objective

+

Given an input list of Tweets, build up the following things:

+
    +
  1. The distribution of starting words; since there are no "prior" words to go from, we need to treat this as a special case.
  2. +
  3. The distribution of words given a previous word; for example, every time I use the word woodchuck in the example sentence, there is a 50% chance it is followed by chuck and a 50% chance it is followed by could. I need this distribution for all words.
  4. +
  5. The distribution of quantity of hashtags; Do I most often use just one? Two? Do they follow something like a Poisson distribution?
  6. +
  7. Distribution of hashtags; Given a number of hashtags, what is the actual content? I'll treat hashtags as separate from the content of a tweet.
  8. +
+

The Data

+

I'm using as input my tweet history. I don't really use Twitter anymore, but it seems like a fun use of the dataset. I'd like to eventually build this to a point where I can imitate anyone on Twitter using their last 100 tweets or so, but I'll start with this as example code.

+

The Algorithm

+

I'll be using the NLTK library for doing a lot of the heavy lifting. First, let's import the data:

+
import pandas as pd

tweets = pd.read_csv('tweets.csv')
text = tweets.text

# Don't include tweets in reply to or mentioning people
replies = text.str.contains('@')
text_norep = text.loc[~replies]
+

And now that we've got data, let's start crunching. First, tokenize and build out the distribution of first word:

+
from nltk.tokenize import TweetTokenizer
tknzr = TweetTokenizer()
tokens = text_norep.map(tknzr.tokenize)

first_words = tokens.map(lambda x: x[0])
first_words_alpha = first_words[first_words.str.isalpha()]
first_word_dist = first_words_alpha.value_counts() / len(first_words_alpha)
+

Next, we need to build out the conditional distributions. That is, what is the probability of the next word given the current word is XX? This one is a bit more involved. First, find all unique words, and then find what words proceed them. This can probably be done in a more efficient manner than I'm currently doing here, but we'll ignore that for the moment.

+
from functools import reduce

# Get all possible words
all_words = reduce(lambda x, y: x+y, tokens, [])
unique_words = set(all_words)
actual_words = set([x if x[0] != '.' else None for x in unique_words])

word_dist = {}
for word in iter(actual_words):
indices = [i for i, j in enumerate(all_words) if j == word]
proceeding = [all_words[i+1] for i in indices]
word_dist[word] = proceeding
+

Now that we've got the tweet analysis done, it's time for the fun part: hashtags! Let's count how many hashtags are in each tweet, I want to get a sense of the distribution.

+
import matplotlib.pyplot as plt
%matplotlib inline

hashtags = text_norep.str.count('#')
bins = hashtags.unique().max()
hashtags.plot(kind='hist', bins=bins)
+
    <matplotlib.axes._subplots.AxesSubplot at 0x18e59dc28d0>
+

png

+

That looks like a Poisson distribution, kind of as I expected. I'm guessing my number of hashtags per tweet is Poi(1)\sim Poi(1), but let's actually find the most likely estimator which in this case is just λˉ\bar{\lambda}:

+
mle = hashtags.mean()
mle
+
    0.870236869207003
+

Pretty close! So we can now simulate how many hashtags are in a tweet. Let's also find what hashtags are actually used:

+
hashtags = [x for x in all_words if x[0] == '#']
n_hashtags = len(hashtags)

unique_hashtags = list(set([x for x in unique_words if x[0] == '#']))
hashtag_dist = pd.DataFrame({'hashtags': unique_hashtags,
'prob': [all_words.count(h) / n_hashtags
for h in unique_hashtags]})
len(hashtag_dist)
+
    603
+

Turns out I have used 603 different hashtags during my time on Twitter. That means I was using a unique hashtag for about every third tweet.

+

In better news though, we now have all the data we need to go about actually constructing tweets! The process will happen in a few steps:

+
    +
  1. Randomly select what the first word will be.
  2. +
  3. Randomly select the number of hashtags for this tweet, and then select the actual hashtags.
  4. +
  5. Fill in the remaining space of 140 characters with random words taken from my tweets.
  6. +
+

And hopefully, we won't have anything too crazy come out the other end. The way we do the selection follows a Multinomial Distribution: given a lot of different values with specific probability, pick one. Let's give a quick example:

+
x: .33
y: .5
z: .17
+

That is, I pick x with probability 33%, y with probability 50%, and so on. In context of our sentence construction, I've built out the probabilities of specific words already - now I just need to simulate that distribution. Time for the engine to actually be developed!

+
import numpy as np

def multinom_sim(n, vals, probs):
occurrences = np.random.multinomial(n, probs)
results = occurrences * vals
return ' '.join(results[results != ''])

def sim_n_hashtags(hashtag_freq):
return np.random.poisson(hashtag_freq)

def sim_hashtags(n, hashtag_dist):
return multinom_sim(n, hashtag_dist.hashtags, hashtag_dist.prob)

def sim_first_word(first_word_dist):
probs = np.float64(first_word_dist.values)
return multinom_sim(1, first_word_dist.reset_index()['index'], probs)

def sim_next_word(current, word_dist):
dist = pd.Series(word_dist[current])
probs = np.ones(len(dist)) / len(dist)
return multinom_sim(1, dist, probs)
+

Pulling it all together

+

I've now built out all the code I need to actually simulate a sentence written by me. Let's try doing an example with five words and a single hashtag:

+
first = sim_first_word(first_word_dist)
second = sim_next_word(first, word_dist)
third = sim_next_word(second, word_dist)
fourth = sim_next_word(third, word_dist)
fifth = sim_next_word(fourth, word_dist)
hashtag = sim_hashtags(1, hashtag_dist)

' '.join((first, second, third, fourth, fifth, hashtag))
+
    'My first all-nighter of friends #oldschool'
+

Let's go ahead and put everything together! We're going to simulate a first word, simulate the hashtags, and then simulate to fill the gap until we've either taken up all the space or reached a period.

+
def simulate_tweet():
chars_remaining = 140
first = sim_first_word(first_word_dist)
n_hash = sim_n_hashtags(mle)
hashtags = sim_hashtags(n_hash, hashtag_dist)

chars_remaining -= len(first) + len(hashtags)

tweet = first
current = first
while chars_remaining > len(tweet) + len(hashtags) and current[0] != '.' and current[0] != '!':
current = sim_next_word(current, word_dist)
tweet += ' ' + current

tweet = tweet[:-2] + tweet[-1]

return ' '.join((tweet, hashtags)).strip()
+

The results

+

And now for something completely different: twenty random tweets dreamed up by my computer and my Twitter data. Here you go:

+
for i in range(0, 20):
print(simulate_tweet())
print()
+
    Also , I'm at 8 this morning. #thursdaysgohard #ornot

Turns out of us breathe the code will want to my undergraduate career is becoming more night trying ? Religion is now as a chane #HYPE

You know what recursion is to review the UNCC. #ornot

There are really sore 3 bonfires in my first writing the library ground floor if awesome. #realtalk #impressed

So we can make it out there's nothing but I'm not let us so hot I could think I may be good. #SwingDance

Happy Christmas , at Harris Teeter to be be godly or Roman Catholic ). #4b392b#4b392b #Isaiah26

For context , I in the most decisive factor of the same for homework. #accomplishment

Freaking done. #loveyouall

New blog post : Don't jump in a quiz in with a knife fight. #haskell #earlybirthday

God shows me legitimately want to get some food and one day.

Stormed the queen city. #mindblown

The day of a cold at least outside right before the semester ..

Finished with the way back. #winners

Waking up , OJ , I feel like Nick Jonas today.

First draft of so hard drive. #humansvszombies

Eric Whitacre is the wise creation.

Ethics paper first , music in close to everyone who just be posting up with my sin , and Jerry Springr #TheLittleThings

Love that you know enough time I've eaten at 8 PM. #deepthoughts #stillblownaway

Lead. #ThinkingTooMuch #Christmas

Aamazing conference when you married #DepartmentOfRedundancyDepartment Yep , but there's a legitimate challenge.
+

...Which all ended up being a whole lot more nonsensical than I had hoped for. There are some good ones, so I'll call that an accomplishment! I was banking on grammar not being an issue: since my tweets use impeccable grammar, the program modeled off them should have pretty good grammar as well. There are going to be some hilarious edge cases (I'm looking at you, Ethics paper first, music in close to everyone) that make no sense, and some hilarious edge cases (Waking up, OJ, I feel like Nick Jonas today) that make me feel like I should have a Twitter rap career. On the whole though, the structure came out alright.

+

Moving on from here

+

During class we also talked about an interesting idea: trying to analyze corporate documents and corporate speech. I'd be interested to know what this analysis applied to something like a couple of bank press releases could do. By any means, the code needs some work to clean it up before I get that far.

+

For further reading

+

I'm pretty confident I re-invented a couple wheels along the way - what I'm doing feels a lot like what Markov Chain Monte Carlo is intended to do. But I've never worked explicitly with that before, so more research is needed.

\ No newline at end of file diff --git a/2016/04/tick-tock/index.html b/2016/04/tick-tock/index.html new file mode 100644 index 0000000..cd1113e --- /dev/null +++ b/2016/04/tick-tock/index.html @@ -0,0 +1,83 @@ +Tick tock... | The Old Speice Guy
Skip to main content

Tick tock...

· 11 min read
Bradlee Speice

If all we have is a finite number of heartbeats left, what about me?

+

Warning: this one is a bit creepier. But that's what you get when you come up with data science ideas as you're drifting off to sleep.

+

2.5 Billion

+

If PBS is right, that's the total number of heartbeats we get. Approximately once every second that number goes down, and down, and down again...

+
total_heartbeats = 2500000000
+

I got a Fitbit this past Christmas season, mostly because I was interested in the data and trying to work on some data science projects with it. This is going to be the first project, but there will likely be more (and not nearly as morbid). My idea was: If this is the final number that I'm running up against, how far have I come, and how far am I likely to go? I've currently had about 3 months' time to estimate what my data will look like, so let's go ahead and see: given a lifetime 2.5 billion heart beats, how much time do I have left?

+

Statistical Considerations

+

Since I'm starting to work with health data, there are a few considerations I think are important before I start digging through my data.

+
    +
  1. The concept of 2.5 billion as an agreed-upon number is tenuous at best. I've seen anywhere from 2.21 billion to 3.4 billion so even if I knew exactly how many times my heart had beaten so far, the ending result is suspect at best. I'm using 2.5 billion because that seems to be about the midpoint of the estimates I've seen so far.
  2. +
  3. Most of the numbers I've seen so far are based on extrapolating number of heart beats from life expectancy. As life expectancy goes up, the number of expected heart beats goes up too.
  4. +
  5. My estimation of the number of heartbeats in my life so far is based on 3 months worth of data, and I'm extrapolating an entire lifetime based on this.
  6. +
+

So while the ending number is not useful in any medical context, it is still an interesting project to work with the data I have on hand.

+

Getting the data

+

Fitbit has an API available for people to pull their personal data off the system. It requires registering an application, authentication with OAuth, and some other complicated things. If you're not interested in how I fetch the data, skip here.

+

Registering an application

+

I've already registered a personal application with Fitbit, so I can go ahead and retrieve things like the client secret from a file.

+
# Import all the OAuth secret information from a local file
from secrets import CLIENT_SECRET, CLIENT_ID, CALLBACK_URL
+

Handling OAuth 2

+

So, all the people that know what OAuth 2 is know what's coming next. For those who don't: OAuth is how people allow applications to access other data without having to know your password. Essentially the dialog goes like this:

+
Application: I've got a user here who wants to use my application, but I need their data.
Fitbit: OK, what data do you need access to, and for how long?
Application: I need all of these scopes, and for this amount of time.
Fitbit: OK, let me check with the user to make sure they really want to do this.

Fitbit: User, do you really want to let this application have your data?
User: I do! And to prove it, here's my password.
Fitbit: OK, everything checks out. I'll let the application access your data.

Fitbit: Application, you can access the user's data. Use this special value whenever you need to request data from me.
Application: Thank you, now give me all the data.
+

Effectively, this allows an application to gain access to a user's data without ever needing to know the user's password. That way, even if the other application is hacked, the user's original data remains safe. Plus, the user can let the data service know to stop providing the application access any time they want. All in all, very secure.

+

It does make handling small requests a bit challenging, but I'll go through the steps here. We'll be using the Implicit Grant workflow, as it requires fewer steps in processing.

+

First, we need to set up the URL the user would visit to authenticate:

+
import urllib

FITBIT_URI = 'https://www.fitbit.com/oauth2/authorize'
params = {
# If we need more than one scope, must be a CSV string
'scope': 'heartrate',
'response_type': 'token',
'expires_in': 86400, # 1 day
'redirect_uri': CALLBACK_URL,
'client_id': CLIENT_ID
}

request_url = FITBIT_URI + '?' + urllib.parse.urlencode(params)
+

Now, here you would print out the request URL, go visit it, and get the full URL that it sends you back to. Because that is very sensitive information (specifically containing my CLIENT_ID that I'd really rather not share on the internet), I've skipped that step in the code here, but it happens in the background.

+
# The `response_url` variable contains the full URL that
# FitBit sent back to us, but most importantly,
# contains the token we need for authorization.
access_token = dict(urllib.parse.parse_qsl(response_url))['access_token']
+

Requesting the data

+

Now that we've actually set up our access via the access_token, it's time to get the actual heart rate data. I'll be using data from January 1, 2016 through March 31, 2016, and extrapolating wildly from that.

+

Fitbit only lets us fetch intraday data one day at a time, so I'll create a date range using pandas and iterate through that to pull down all the data.

+
from requests_oauthlib import OAuth2Session
import pandas as pd
from datetime import datetime

session = OAuth2Session(token={
'access_token': access_token,
'token_type': 'Bearer'
})

format_str = '%Y-%m-%d'
start_date = datetime(2016, 1, 1)
end_date = datetime(2016, 3, 31)
dr = pd.date_range(start_date, end_date)

url = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json'
hr_responses = [session.get(url.format(d.strftime(format_str))) for d in dr]

def record_to_df(record):
if 'activities-heart' not in record:
return None
date_str = record['activities-heart'][0]['dateTime']
df = pd.DataFrame(record['activities-heart-intraday']['dataset'])

df.index = df['time'].apply(
lambda x: datetime.strptime(date_str + ' ' + x, '%Y-%m-%d %H:%M:%S'))
return df

hr_dataframes = [record_to_df(record.json()) for record in hr_responses]
hr_df_concat = pd.concat(hr_dataframes)


# There are some minutes with missing data, so we need to correct that
full_daterange = pd.date_range(hr_df_concat.index[0],
hr_df_concat.index[-1],
freq='min')
hr_df_full = hr_df_concat.reindex(full_daterange, method='nearest')

print("Heartbeats from {} to {}: {}".format(hr_df_full.index[0],
hr_df_full.index[-1],
hr_df_full['value'].sum()))
+
    Heartbeats from 2016-01-01 00:00:00 to 2016-03-31 23:59:00: 8139060
+

And now we've retrieved all the available heart rate data for January 1st through March 31st! Let's get to the actual analysis.

+

Wild Extrapolations from Small Data

+

A fundamental issue of this data is that it's pretty small. I'm using 3 months of data to make predictions about my entire life. But, purely as an exercise, I'll move forward.

+

How many heartbeats so far?

+

The first step is figuring out how many of the 2.5 billion heartbeats I've used so far. We're going to try and work backward from the present day to when I was born to get that number. The easy part comes first: going back to January 1st, 1992. That's because I can generalize how many 3-month increments there were between now and then, account for leap years, and call that section done.

+

Between January 1992 and January 2016 there were 96 quarters, and 6 leap days. The number we're looking for is:

+hrqnhrd(nm)\begin{equation*} +hr_q \cdot n - hr_d \cdot (n-m) +\end{equation*} +
    +
  • hrqhr_q: Number of heartbeats per quarter
  • +
  • hrdhr_d: Number of heartbeats on leap day
  • +
  • nn: Number of quarters, in this case 96
  • +
  • mm: Number of leap days, in this case 6
  • +
+
quarterly_count = hr_df_full['value'].sum()
leap_day_count = hr_df_full[(hr_df_full.index.month == 2) &
(hr_df_full.index.day == 29)]['value'].sum()
num_quarters = 96
leap_days = 6

jan_92_jan_16 = quarterly_count * num_quarters - leap_day_count * (num_quarters - leap_days)
jan_92_jan_16
+
    773609400
+

So between January 1992 and January 2016 I've used \approx 774 million heartbeats. Now, I need to go back to my exact birthday. I'm going to first find on average how many heartbeats I use in a minute, and multiply that by the number of minutes between my birthday and January 1992.

+

For privacy purposes I'll put the code here that I'm using, but without any identifying information:

+
minute_mean = hr_df_full['value'].mean()
# Don't you wish you knew?
# birthday_minutes = ???

birthday_heartbeats = birthday_minutes * minute_mean

heartbeats_until_2016 = int(birthday_heartbeats + jan_92_jan_16)
remaining_2016 = total_heartbeats - heartbeats_until_2016

print("Heartbeats so far: {}".format(heartbeats_until_2016))
print("Remaining heartbeats: {}".format(remaining_2016))
+
    Heartbeats so far: 775804660
Remaining heartbeats: 1724195340
+

It would appear that my heart has beaten 775,804,660 times between my moment of birth and January 1st 2016, and that I have 1.72 billion left.

+

How many heartbeats longer?

+

Now comes the tricky bit. I know how many heart beats I've used so far, and how many I have remaining, so I'd like to come up with a (relatively) accurate estimate of when exactly my heart should give out. We'll do this in a few steps, increasing in granularity.

+

First step, how many heartbeats do I use in a 4-year period? I have data for a single quarter including leap day, so I want to know:

+hrqnhrd(nm)\begin{equation*} +hr_q \cdot n - hr_d \cdot (n - m) +\end{equation*} +
    +
  • hrqhr_q: Heartbeats per quarter
  • +
  • hrdhr_d: Heartbeats per leap day
  • +
  • nn: Number of quarters = 16
  • +
  • mm: Number of leap days = 1
  • +
+
heartbeats_4year = quarterly_count * 16 - leap_day_count * (16 - 1)
heartbeats_4year
+
    128934900
+

Now, I can fast forward from 2016 the number of periods of 4 years I have left.

+
four_year_periods = remaining_2016 // heartbeats_4year
remaining_4y = remaining_2016 - four_year_periods * heartbeats_4year

print("Four year periods remaining: {}".format(four_year_periods))
print("Remaining heartbeats after 4 year periods: {}".format(remaining_4y))
+
    Four year periods remaining: 13
Remaining heartbeats after 4 year periods: 48041640
+

Given that there are 13 four-year periods left, I can move from 2016 all the way to 2068, and find that I will have 48 million heart beats left. Let's drop down to figuring out how many quarters that is. I know that 2068 will have a leap day (unless someone finally decides to get rid of them), so I'll subtract that out first. Then, I'm left to figure out how many quarters exactly are left.

+
remaining_leap = remaining_4y - leap_day_count
# Ignore leap day in the data set
heartbeats_quarter = hr_df_full[(hr_df_full.index.month != 2) &
(hr_df_full.index.day != 29)]['value'].sum()
quarters_left = remaining_leap // heartbeats_quarter
remaining_year = remaining_leap - quarters_left * heartbeats_quarter

print("Quarters left starting 2068: {}".format(quarters_left))
print("Remaining heartbeats after that: {}".format(remaining_year))
+
    Quarters left starting 2068: 8
Remaining heartbeats after that: 4760716
+

So, that analysis gets me through until January 1st 2070. Final step, using that minute estimate to figure out how many minutes past that I'm predicted to have:

+
from datetime import timedelta

base = datetime(2070, 1, 1)
minutes_left = remaining_year // minute_mean

kaput = timedelta(minutes=minutes_left)
base + kaput
+
    datetime.datetime(2070, 2, 23, 5, 28)
+

According to this, I've got until February 23rd, 2070 at 5:28 PM in the evening before my heart gives out.

+

Summary

+

Well, that's kind of a creepy date to know. As I said at the top though, this number is totally useless in any medical context. It ignores the rate at which we continue to get better at making people live longer, and is extrapolating from 3 months' worth of data the rest of my life. Additionally, throughout my time developing this post I made many minor mistakes. I think they're all fixed now, but it's easy to mix a number up here or there and the analysis gets thrown off by a couple years.

+

Even still, I think philosophically humans have a desire to know how much time we have left in the world. Man is but a breath, and it's scary to think just how quickly that date may be coming up. This analysis asks an important question though: what are you going to do with the time you have left?

+

Thanks for sticking with me on this one, I promise it will be much less depressing next time!

\ No newline at end of file diff --git a/2016/05/the-unfair-casino/index.html b/2016/05/the-unfair-casino/index.html new file mode 100644 index 0000000..741d3c7 --- /dev/null +++ b/2016/05/the-unfair-casino/index.html @@ -0,0 +1,180 @@ +The unfair casino | The Old Speice Guy
Skip to main content

The unfair casino

· 15 min read
Bradlee Speice

Trying to figure out how exactly two dice are loaded in a cheating casino.

+

In the ongoing eternal cycle of mathematicians asking generally useless questions about probability, I dreamt up another one. The scenario is as follows:

+

You're playing a game with two die, and you do not get to see what the outcome of the die are on each roll. All you get to see is their sum. Given an arbitrarily long list of the sum of two rolls, can you determine if one or both die are loaded, and what those loadings are?

+

Proving we can detect cheating

+

My first question is simply, is this possible? There's a lot of trivial cases that make it obvious that there's cheating going on. But there are some edge cases that might give us more difficulty. First though, let's get a picture of what the fair distribution looks like. In principle, we can only detect cheating if the distribution of the fair die differs from the distribution of the loaded die.

+
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

fair_1 = np.random.randint(1, 7, 10000)
fair_2 = np.random.randint(1, 7, 10000)

pd.Series(fair_1 + fair_2).plot(kind='hist', bins=11);
plt.title('Fair Distribution');
+

png

+

This distribution makes sense: there are many ways to make a 7 (the most frequent observed value) and very few ways to make a 12 or 2; an important symmetry. As a special note, you can notice that the sum of two fair dice is a discrete case of the Triangle Distribution, which is itself a special case of the Irwin-Hall Distribution.

+

The Edge Cases

+

Given that we understand how the results of two fair dice are distributed, let's see some of the interesting edge cases that come up. This will give us assurance that when a casino is cheating, it is detectable (given sufficient data). To make this as hard as possible, we will think of scenarios where the expected value of the sum of loaded dice is the same as the expected value of the sum of fair dice.

+

Edge Case 1

+

What happens when one die is biased low, and one die is biased high? That is, where:

+D1={1w.p.1/32w.p.1/33w.p.1/124w.p.1/125w.p.1/126w.p.1/12D2={1w.p.1/122w.p.1/123w.p.1/124w.p.1/125w.p.1/36w.p.1/3E[D1]=2.5E[D2]=4.5E[D1+D2]=7=E[Dfair+Dfair]\begin{align*} +\begin{array}{cc} +D_1 = \left\{ +\begin{array}{lr} +1 & w.p. 1/3\\ +2 & w.p. 1/3\\ +3 & w.p. 1/12\\ +4 & w.p. 1/12\\ +5 & w.p. 1/12\\ +6 & w.p. 1/12 +\end{array} +\right. & +D_2 = \left\{ +\begin{array}{lr} +1 & w.p. 1/12\\ +2 & w.p. 1/12\\ +3 & w.p. 1/12\\ +4 & w.p. 1/12\\ +5 & w.p. 1/3\\ +6 & w.p. 1/3 +\end{array} +\right. \\ +\mathbb{E}[D_1] = 2.5 & \mathbb{E}[D_2] = 4.5 +\end{array}\\ +\mathbb{E}[D_1 + D_2] = 7 = \mathbb{E}[D_{fair} + D_{fair}] +\end{align*} +
def unfair_die(p_vals, n):
x = np.random.multinomial(1, p_vals, n)
return x.nonzero()[1] + 1

d1 = [1/3, 1/3, 1/12, 1/12, 1/12, 1/12]
d2 = [1/12, 1/12, 1/12, 1/12, 1/3, 1/3]

x1 = unfair_die(d1, 10000)
x2 = unfair_die(d2, 10000)

pd.Series(x1 + x2).plot(kind='hist', bins=11);
plt.title('$D_1$ biased low, $D_2$ biased high');
+

png

+

We can see that while the 7 value remains the most likely (as expected), the distribution is not so nicely shaped any more.

+

Edge Case 2

+

When one die is loaded low, and one is loaded high, we've seen how we can detect them. How about when two die are loaded both low and high? That is, we have the following distribution:

+D1={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3D2={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3E[D1]=3.5E[D2]=3.5E[D1+D2]=7=E[Dfair+Dfair]\begin{align*} +\begin{array}{cc} +D_1 = \left\{ +\begin{array}{lr} +1 & w.p. 1/3\\ +2 & w.p. 1/12\\ +3 & w.p. 1/12\\ +4 & w.p. 1/12\\ +5 & w.p. 1/12\\ +6 & w.p. 1/3 +\end{array} +\right. & +D_2 = \left\{ +\begin{array}{lr} +1 & w.p. 1/3\\ +2 & w.p. 1/12\\ +3 & w.p. 1/12\\ +4 & w.p. 1/12\\ +5 & w.p. 1/12\\ +6 & w.p. 1/3 +\end{array} +\right. \\ +\mathbb{E}[D_1] = 3.5 & \mathbb{E}[D_2] = 3.5 +\end{array}\\ +\mathbb{E}[D_1 + D_2] = 7 = \mathbb{E}[D_{fair} + D_{fair}] +\end{align*} +

We can see even that the expected value of each individual die is the same as the fair die! However, the distribution (if we are doing this correctly) should still be skewed:

+
d1 = [1/3, 1/12, 1/12, 1/12, 1/12, 1/3]
d2 = d1

x1 = unfair_die(d1, 10000)
x2 = unfair_die(d2, 10000)

pd.Series(x1 + x2).plot(kind='hist', bins=11)
plt.title("$D_1$ and $D_2$ biased to 1 and 6");
+

png

+

In a very un-subtle way, we have of course made the values 2 and 12 far more likely.

+

Detection Conclusion

+

There are some trivial examples of cheating that are easy to detect: whenever the expected value of the sum of two fair dice deviates from the expected value for the sum of two fair dice, we can immediately conclude that there is cheating at stake.

+

The interesting edge cases occur when the expected value of the sum of loaded dice matches the expected value of the sum of fair dice. Considering the above examples (and a couple more I ran through in developing this), we have seen that in every circumstance having two unfair dice leads to a distribution of results different from the fair results.

+

We can thus finally state: just by looking at the distribution of results from this game, we can immediately conclude whether there is cheating.

+

Simulated Annealing

+

What we really would like to do though, is see if there is any way to determine how exactly the dice are loaded. This is significantly more complicated, but we can borrow some algorithms from Machine Learning to figure out exactly how to perform this process. I'm using the Simulated Annealing algorithm, and I discuss why this works and why I chose it over some of the alternatives in the justification. If you don't care about how I set up the model and just want to see the code, check out the actual code.

+

Simulated Annealing is a variation of the Metropolis-Hastings Algorithm, but the important thing for us is: Simulated Annealing allows us to quickly optimize high-dimensional problems. But what exactly are we trying to optimize? Ideally, we want a function that can tell us whether one distribution for the dice better explains the results than another distribution. This is known as the likelihood function.

+

Deriving the Likelihood function

+

To derive our likelihood function, we want to know: what is the probability of seeing a specific result given those hidden parameters? This is actually a surprisingly difficult problem. While we can do a lot of calculations by hand, we need a more general solution since we will be working with very some interesting die distributions.

+

We first note that the sum of two dice can take on 11 different values - 2 through 12. This implies that each individual sum follows a Categorical distribution. That is:

+L(x)={p2x=2p3x=3p11x=11p12x=12\begin{align*} +\mathcal{L(x)} = \left\{ +\begin{array}{lr} +p_2 & x = 2\\ +p_3 & x = 3\\ +\ldots & \\ +p_{11} & x = 11\\ +p_{12} & x = 12 +\end{array} +\right. +\end{align*} +

Where each pip_i is the probability of seeing that specific result. However, we need to calculate what each probability is! I'll save you the details, but this author explains how to do it.

+

Now, we would like to know the likelihood of our entire data-set. This is trivial:

+L(X)=i=1nL(x)\begin{align*} +\mathcal{L(\mathbf{X})} &= \prod_{i=1}^n L(x) +\end{align*} +

However, it's typically much easier to work with the log(L)\log(\mathcal{L}) function instead. This is critically important from a computational perspective: when you multiply so many small numbers together (i.e. the product of L(x)L(x) terms) the computer suffers from rounding error; if we don't control for this, we will find that no matter the distributions we choose for each die, the "likelihood" will be close to zero because the computer is not precise enough.

+log(L)=i=1nlog(L)\begin{align*} +\log(\mathcal{L}) &= \sum_{i=1}^n \log(L) +\end{align*} +

The process of Simulated Annealing

+

The means by which we optimize our likelihood function is the simulated annealing algorithm. The way it works is as follows:

+
    +
  1. +

    Start with a random guess for the parameters we are trying to optimize. In our case we are trying to guess the distribution of two dice, and so we "optimize" until we have a distribution that matches the data.

    +
  2. +
  3. +

    For each iteration of the algorithm:

    +
      +
    1. Generate a new "proposed" set of parameters based on the current parameters - +i.e. slightly modify the current parameters to get a new set of parameters.
    2. +
    3. Calculate the value of log(L)\log(\mathcal{L}) for each set of parameters. If the function value for the +proposed parameter set is higher than for the current, automatically switch to the new parameter set +and continue the next iteration.
    4. +
    5. Given the new parameter set performs worse, determine a probability of switching to the new parameter set anyways: P(pcurrent,pproposed)\mathcal{P}(p_{current}, p_{proposed})
    6. +
    7. Switch to the new parameter set with probability P\mathcal{P}. If you fail to switch, begin the next iteration.
    8. +
    +
  4. +
  5. +

    The algorithm is complete after we fail to make a transition nn times in a row.

    +
  6. +
+

If everything goes according to plan, we will have a value that is close to the true distribution of each die.

+

The actual code

+

We start by defining the score function. This will tell us how well the proposed die densities actually explain the results.

+
import numpy as np
from numpy import polynomial

def density_coef(d1_density, d2_density):
# Calculating the probabilities of each outcome was taken
# from this author: http://math.stackexchange.com/a/1710392/320784
d1_p = polynomial.Polynomial(d1_density)
d2_p = polynomial.Polynomial(d2_density)
coefs = (d1_p * d2_p).coef
return coefs

def score(x, d1_density, d2_density):
# We've now got the probabilities of each event, but we need
# to shift the array a bit so we can use the x values to actually
# index into it. This will allow us to do all the calculations
# incredibly quickly
coefs = density_coef(d1_density, d2_density)
coefs = np.hstack((0, 0, coefs))
return np.log(coefs[x]).sum()
+

Afterward, we need to write something to permute the proposal densities. We make random modifications, and eventually the best one survives.

+
def permute(d1_density, d2_density):
# To ensure we have legitimate densities, we will randomly
# increase one die face probability by `change`,
# and decrease one by `change`.
# This means there are something less than (1/`change`)^12 possibilities
# we are trying to search over.
change = .01

d1_index1, d1_index2 = np.random.randint(0, 6, 2)
d2_index1, d2_index2 = np.random.randint(0, 6, 2)

# Also make sure to copy. I've had some weird aliasing issues
# in the past that made everything blow up.
new_d1 = np.float64(np.copy(d1_density))
new_d2 = np.float64(np.copy(d2_density))

# While this doesn't account for the possibility that some
# values go negative, in practice this never happens
new_d1[d1_index1] += change
new_d1[d1_index2] -= change
new_d2[d2_index1] += change
new_d2[d2_index2] -= change

return new_d1, new_d2
+

Now we've got the main algorithm code to do. This is what brings all the pieces together.

+
def optimize(data, conv_count=10, max_iter=1e4):
switch_failures = 0
iter_count = 0

# Start with guessing fair dice
cur_d1 = np.repeat(1/6, 6)
cur_d2 = np.repeat(1/6, 6)
cur_score = score(data, cur_d1, cur_d2)

# Keep track of our best guesses - may not be
# what we end with
max_score = cur_score
max_d1 = cur_d1
max_d2 = cur_d2

# Optimization stops when we have failed to switch `conv_count`
# times (presumably because we have a great guess), or we reach
# the maximum number of iterations.
while switch_failures < conv_count and iter_count < max_iter:
iter_count += 1
if iter_count % (max_iter / 10) == 0:
print('Iteration: {}; Current score (higher is better): {}'.format(
iter_count, cur_score))

new_d1, new_d2 = permute(cur_d1, cur_d2)
new_score = score(data, new_d1, new_d2)

if new_score > max_score:
max_score = new_score
max_d1 = new_d1
max_d2 = new_d2

if new_score > cur_score:
# If the new permutation beats the old one,
# automatically select it.
cur_score = new_score
cur_d1 = new_d1
cur_d2 = new_d2
switch_failures = 0
else:
# We didn't beat the current score, but allow
# for possibly switching anyways.
accept_prob = np.exp(new_score - cur_score)
coin_toss = np.random.rand()
if coin_toss < accept_prob:
# We randomly switch to the new distribution
cur_score = new_score
cur_d1 = new_d1
cur_d2 = new_d2
switch_failures = 0
else:
switch_failures += 1

# Return both our best guess, and the ending guess
return max_d1, max_d2, cur_d1, cur_d2
+

And now we have finished the hard work!

+

Catching the Casino

+

Let's go through a couple of scenarios and see if we can catch the casino cheating with some loaded dice. In every scenario we start with an assumption of fair dice, and then try our hand to figure out what the actual distribution was.

+

Attempt 1

+

The casino is using two dice that are both biased low. How well can we recover the distribution?

+
import time
def simulate_casino(d1_dist, d2_dist, n=10000):
d1_vals = unfair_die(d1_dist, n)
d2_vals = unfair_die(d2_dist, n)

start = time.perf_counter()
max_d1, max_d2, final_d1, final_d2 = optimize(d1_vals + d2_vals)
end = time.perf_counter()
print("Simulated Annealing time: {:.02f}s".format(end - start))

coef_range = np.arange(2, 13) - .5
plt.subplot(221)
plt.bar(coef_range, density_coef(d1_dist, d2_dist), width=1)
plt.title('True Distribution')

plt.subplot(222)
plt.hist(d1_vals + d2_vals, bins=11)
plt.title('Empirical Distribution')

plt.subplot(223)
plt.bar(coef_range, density_coef(max_d1, max_d2), width=1)
plt.title('Recovered Distribution')

plt.gcf().set_size_inches(10, 10)


simulate_casino([2/9, 2/9, 2/9, 1/9, 1/9, 1/9],
[2/9, 2/9, 2/9, 1/9, 1/9, 1/9])
+
    Iteration: 1000; Current score (higher is better): -22147.004400281654
Simulated Annealing time: 0.30s
+

png

+

Attempt 2

+

The casino now uses dice that are both biased towards 1 and 6.

+
simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],
[1/3, 1/12, 1/12, 1/12, 1/12, 1/3])
+
    Simulated Annealing time: 0.08s
+

png

+

Attempt 3

+

The casino will now use one die biased towards 1 and 6, and one die towards 3 and 4.

+
simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],
[1/12, 1/12, 1/3, 1/3, 1/12, 1/12])
+
    Simulated Annealing time: 0.09s
+

png

+

Attempt 4

+

We'll now finally go to a fair casino to make sure that we can still recognize a positive result.

+
simulate_casino(np.repeat(1/6, 6), np.repeat(1/6, 6))
+
    Simulated Annealing time: 0.02s
+

png

+

Attempt 5

+

We've so far been working with a large amount of data - 10,000 data points. Can we now scale things back to only 250 throws? We'll start with two dice biased high.

+
simulate_casino([1/9, 1/9, 1/9, 2/9, 2/9, 2/9],
[1/9, 1/9, 1/9, 2/9, 2/9, 2/9],
n=250)
+
    Iteration: 1000; Current score (higher is better): -551.6995384525453
Iteration: 2000; Current score (higher is better): -547.7803673440676
Iteration: 3000; Current score (higher is better): -547.9805613193807
Iteration: 4000; Current score (higher is better): -546.7574874775273
Iteration: 5000; Current score (higher is better): -549.5798007672656
Iteration: 6000; Current score (higher is better): -545.0354060154496
Iteration: 7000; Current score (higher is better): -550.1134504086606
Iteration: 8000; Current score (higher is better): -549.9306537114975
Iteration: 9000; Current score (higher is better): -550.7075182119111
Iteration: 10000; Current score (higher is better): -549.400679551826
Simulated Annealing time: 1.94s
+

png

+

The results are surprisingly good. While the actual optimization process took much longer to finish than in the other examples, we still have a very good guess. As a caveat though: the recovered distribution tends to overfit the data. That is, if the data doesn't fit the underlying distribution well, the model will also fail.

+

Conclusion

+

Given the results above, we can see that we have indeed come up with a very good algorithm to determine the distribution of two dice given their results. As a benefit, we have even seen that results come back very quickly; it's not uncommon for the optimization to converge within a tenth of a second.

+

Additionally, we have seen that the algorithm can intuit the distribution even when there is not much data. While the final example shows that we can 'overfit' on the dataset, we can still get valuable information from a relatively small dataset.

+

We can declare at long last: the mathematicians have again triumphed over the casino.

+
+

Justification of Simulated Annealing

+

Why Simulated Annealing?

+

So why even use an algorithm with a fancy title like Simulated Annealing? First of all, because the title is sexy. Second of all, because this is a reasonably complicated problem to try and solve. We have a parameter space where each value pij(0,1);i,j{1,,6}p_{ij} \in (0, 1); i, j \in \{1, \ldots, 6\}, for a total of 12 different variables we are trying to optimize over. Additionally, given a 12-dimensional function we are trying to optimize, simulated annealing makes sure that we don't fall into a local minimum.

+

Why not something else?

+

This is a fair question. There are two classes of algorithms that can also be used to solve this problem: Non-linear optimization methods, and the EM algorithm.

+
    +
  1. +

    I chose not to use non-linear optimization simply because I'm a bit concerned that it will trap me in a local maximum. Instead of running multiple different optimizations from different starting points, I can just use simulated annealing to take that into account. In addition, throughout the course of testing the simulated annealing code converged incredibly quickly - far more quickly than any non-linear solver would be able to accomplish.

    +
  2. +
  3. +

    The EM Algorithm was originally what I intended to write this blog post with. Indeed, the post was inspired by the crooked casino example which uses the EM algorithm to solve it. However, after modeling the likelihood function I realized that the algebra would very quickly get out of hand. Trying to compute all the polynomial terms would not be fun, which would be needed to actually optimize for each parameter. So while the EM algorithm would likely be much faster in raw speed terms, the amount of time needed to program and verify it meant that I was far better off using a different method for optimization.

    +
  4. +
\ No newline at end of file diff --git a/2016/06/event-studies-and-earnings-releases/index.html b/2016/06/event-studies-and-earnings-releases/index.html new file mode 100644 index 0000000..cbf34c0 --- /dev/null +++ b/2016/06/event-studies-and-earnings-releases/index.html @@ -0,0 +1,74 @@ +Event studies and earnings releases | The Old Speice Guy
Skip to main content

Event studies and earnings releases

· 17 min read
Bradlee Speice

Or, being suspicious of market insiders.

+

The Market Just Knew

+

I recently saw two examples of stock charts that have kept me thinking for a while. And now that the semester is complete, I finally have enough time to really look at them and give them the treatment they deserve. The first is good old Apple:

+
Code
from secrets import QUANDL_KEY
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
from matplotlib.finance import candlestick_ohlc
from matplotlib.dates import DateFormatter, WeekdayLocator,\
DayLocator, MONDAY
import quandl
from datetime import datetime
import pandas as pd
%matplotlib inline

def fetch_ticker(ticker, start, end):
# Quandl is currently giving me issues with returning
# the entire dataset and not slicing server-side.
# So instead, we'll do it client-side!
q_format = '%Y-%m-%d'
ticker_data = quandl.get('YAHOO/' + ticker,
start_date=start.strftime(q_format),
end_date=end.strftime(q_format),
authtoken=QUANDL_KEY)
return ticker_data

def ohlc_dataframe(data, ax=None):
# Much of this code re-used from:
# http://matplotlib.org/examples/pylab_examples/finance_demo.html
if ax is None:
f, ax = plt.subplots()

vals = [(date2num(date), *(data.loc[date]))
for date in data.index]
candlestick_ohlc(ax, vals)

mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
weekFormatter = DateFormatter('%b %d')
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
ax.xaxis.set_major_formatter(weekFormatter)
return ax
+
AAPL = fetch_ticker('AAPL', datetime(2016, 3, 1), datetime(2016, 5, 1))
ax = ohlc_dataframe(AAPL)
plt.vlines(date2num(datetime(2016, 4, 26, 12)),
ax.get_ylim()[0], ax.get_ylim()[1],
color='b',
label='Earnings Release')
plt.legend(loc=3)
plt.title("Apple Price 3/1/2016 - 5/1/2016");
+

png

+

The second chart is from Facebook:

+
FB = fetch_ticker('FB', datetime(2016, 3, 1), datetime(2016, 5, 5))
ax = ohlc_dataframe(FB)
plt.vlines(date2num(datetime(2016, 4, 27, 12)),
ax.get_ylim()[0], ax.get_ylim()[1],
color='b', label='Earnings Release')
plt.title('Facebook Price 3/5/2016 - 5/5/2016')
plt.legend(loc=2);
+

png

+

These two charts demonstrate two very specific phonomena: how the market prepares for earnings releases. Let's look at those charts again, but with some extra information. As we're about the see, the market "knew" in advance that Apple was going to perform poorly. The market expected that Facebook was going to perform poorly, and instead shot the lights out. Let's see that trend in action:

+
Code
def plot_hilo(ax, start, end, data):
ax.plot([date2num(start), date2num(end)],
[data.loc[start]['High'], data.loc[end]['High']],
color='b')
ax.plot([date2num(start), date2num(end)],
[data.loc[start]['Low'], data.loc[end]['Low']],
color='b')

f, axarr = plt.subplots(1, 2)

ax_aapl = axarr[0]
ax_fb = axarr[1]

# Plot the AAPL trend up and down
ohlc_dataframe(AAPL, ax=ax_aapl)
plot_hilo(ax_aapl, datetime(2016, 3, 1), datetime(2016, 4, 15), AAPL)
plot_hilo(ax_aapl, datetime(2016, 4, 18), datetime(2016, 4, 26), AAPL)
ax_aapl.vlines(date2num(datetime(2016, 4, 26, 12)),
ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],
color='g', label='Earnings Release')
ax_aapl.legend(loc=2)
ax_aapl.set_title('AAPL Price History')

# Plot the FB trend down and up
ohlc_dataframe(FB, ax=ax_fb)
plot_hilo(ax_fb, datetime(2016, 3, 30), datetime(2016, 4, 27), FB)
plot_hilo(ax_fb, datetime(2016, 4, 28), datetime(2016, 5, 5), FB)
ax_fb.vlines(date2num(datetime(2016, 4, 27, 12)),
ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],
color='g', label='Earnings Release')
ax_fb.legend(loc=2)
ax_fb.set_title('FB Price History')

f.set_size_inches(18, 6)
+

png

+

As we can see above, the market broke a prevailing trend on Apple in order to go down, and ultimately predict the earnings release. For Facebook, the opposite happened. While the trend was down, the earnings were fantastic and the market corrected itself much higher.

+

Formulating the Question

+

While these are two specific examples, there are plenty of other examples you could cite one way or another. Even if the preponderance of evidence shows that the market correctly predicts earnings releases, we need not accuse people of collusion; for a company like Apple with many suppliers we can generally forecast how Apple has done based on those same suppliers.

+

The question then, is this: how well does the market predict the earnings releases? It's an incredibly broad question that I want to disect in a couple of different ways:

+
    +
  1. Given a stock that has been trending down over the past N days before an earnings release, how likely does it continue downward after the release?
  2. +
  3. Given a stock trending up, how likely does it continue up?
  4. +
  5. Is there a difference in accuracy between large- and small-cap stocks?
  6. +
  7. How often, and for how long, do markets trend before an earnings release?
  8. +
+

I want to especially thank Alejandro Saltiel for helping me retrieve the data. He's great. And now for all of the interesting bits.

+

Event Studies

+

Before we go too much further, I want to introduce the actual event study. Each chart intends to capture a lot of information and present an easy-to-understand pattern:

+
Code
import numpy as np
import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
from datetime import datetime, timedelta

# If you remove rules, it removes them from *all* calendars
# To ensure we don't pop rules we don't want to, first make
# sure to fully copy the object
trade_calendar = USFederalHolidayCalendar()
trade_calendar.rules.pop(6) # Remove Columbus day
trade_calendar.rules.pop(7) # Remove Veteran's day
TradeDay = lambda days: CustomBusinessDay(days, calendar=trade_calendar)

def plot_study(array):
# Given a 2-d array, we assume the event happens at index `lookback`,
# and create all of our summary statistics from there.
lookback = int((array.shape[1] - 1) / 2)
norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)
centered_data = array / norm_factor - 1
lookforward = centered_data.shape[1] - lookback
means = centered_data.mean(axis=0)
lookforward_data = centered_data[:,lookforward:]
std_dev = np.hstack([0, lookforward_data.std(axis=0)])
maxes = lookforward_data.max(axis=0)
mins = lookforward_data.min(axis=0)

f, axarr = plt.subplots(1, 2)
range_begin = -lookback
range_end = lookforward
axarr[0].plot(range(range_begin, range_end), means)
axarr[1].plot(range(range_begin, range_end), means)
axarr[0].fill_between(range(0, range_end),
means[-lookforward:] + std_dev,
means[-lookforward:] - std_dev,
alpha=.5, label="$\pm$ 1 s.d.")
axarr[1].fill_between(range(0, range_end),
means[-lookforward:] + std_dev,
means[-lookforward:] - std_dev,
alpha=.5, label="$\pm$ 1 s.d.")

max_err = maxes - means[-lookforward+1:]
min_err = means[-lookforward+1:] - mins
axarr[0].errorbar(range(1, range_end),
means[-lookforward+1:],
yerr=[min_err, max_err], label='Max & Min')
axarr[0].legend(loc=2)
axarr[1].legend(loc=2)

axarr[0].set_xlim((-lookback-1, lookback+1))
axarr[1].set_xlim((-lookback-1, lookback+1))

def plot_study_small(array):
# Given a 2-d array, we assume the event happens at index `lookback`,
# and create all of our summary statistics from there.
lookback = int((array.shape[1] - 1) / 2)
norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)
centered_data = array / norm_factor - 1
lookforward = centered_data.shape[1] - lookback
means = centered_data.mean(axis=0)
lookforward_data = centered_data[:,lookforward:]
std_dev = np.hstack([0, lookforward_data.std(axis=0)])
maxes = lookforward_data.max(axis=0)
mins = lookforward_data.min(axis=0)

range_begin = -lookback
range_end = lookforward
plt.plot(range(range_begin, range_end), means)
plt.fill_between(range(0, range_end),
means[-lookforward:] + std_dev,
means[-lookforward:] - std_dev,
alpha=.5, label="$\pm$ 1 s.d.")

max_err = maxes - means[-lookforward+1:]
min_err = means[-lookforward+1:] - mins
plt.errorbar(range(1, range_end),
means[-lookforward+1:],
yerr=[min_err, max_err], label='Max & Min')
plt.legend(loc=2)
plt.xlim((-lookback-1, lookback+1))

def fetch_event_data(ticker, events, horizon=5):
# Use horizon+1 to account for including the day of the event,
# and half-open interval - that is, for a horizon of 5,
# we should be including 11 events. Additionally, using the
# CustomBusinessDay means we automatically handle issues if
# for example a company reports Friday afternoon - the date
# calculator will turn this into a "Saturday" release, but
# we effectively shift that to Monday with the logic below.
td_back = TradeDay(horizon+1)
td_forward = TradeDay(horizon+1)

start_date = min(events) - td_back
end_date = max(events) + td_forward
total_data = fetch_ticker(ticker, start_date, end_date)
event_data = [total_data.ix[event-td_back:event+td_forward]\
[0:horizon*2+1]\
['Adjusted Close']
for event in events]
return np.array(event_data)
+
# Generate a couple of random events

event_dates = [datetime(2016, 5, 27) - timedelta(days=1) - TradeDay(x*20) for x in range(1, 40)]
data = fetch_event_data('CELG', event_dates)
plot_study_small(data)
plt.legend(loc=3)
plt.gcf().set_size_inches(12, 6);


plt.annotate('Mean price for days leading up to each event',
(-5, -.01), (-4.5, .025),
arrowprops=dict(facecolor='black', shrink=0.05))
plt.annotate('', (-.1, .005), (-.5, .02),
arrowprops={'facecolor': 'black', 'shrink': .05})
plt.annotate('$\pm$ 1 std. dev. each day', (5, .055), (2.5, .085),
arrowprops={'facecolor': 'black', 'shrink': .05})
plt.annotate('Min/Max each day', (.9, -.07), (-1, -.1),
arrowprops={'facecolor': 'black', 'shrink': .05});
+

png

+

And as a quick textual explanation as well:

+
    +
  • The blue line represents the mean price for each day, represented as a percentage of the price on the '0-day'. For example, if we defined an 'event' as whenever the stock price dropped for three days, we would see a decreasing blue line to the left of the 0-day.
  • +
  • The blue shaded area represents one standard deviation above and below the mean price for each day following an event. This is intended to give us an idea of what the stock price does in general following an event.
  • +
  • The green bars are the minimum and maximum price for each day following an event. This instructs us as to how much it's possible for the stock to move.
  • +
+ +

The first type of event I want to study is how stocks perform when they've been trending down over the past couple of days prior to a release. However, we need to clarify what exactly is meant by "trending down." To do so, we'll use the following metric: the midpoint between each day's opening and closing price goes down over a period of N days.

+

It's probably helpful to have an example:

+
Code
f, axarr = plt.subplots(1, 2)
f.set_size_inches(18, 6)

FB_plot = axarr[0]
ohlc_dataframe(FB[datetime(2016, 4, 18):], FB_plot)

FB_truncated = FB[datetime(2016, 4, 18):datetime(2016, 4, 27)]
midpoint = FB_truncated['Open']/2 + FB_truncated['Close']/2
FB_plot.plot(FB_truncated.index, midpoint, label='Midpoint')
FB_plot.vlines(date2num(datetime(2016, 4, 27, 12)),
ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],
color='g', label='Earnings Release')
FB_plot.legend(loc=2)
FB_plot.set_title('FB Midpoint Plot')

AAPL_plot = axarr[1]
ohlc_dataframe(AAPL[datetime(2016, 4, 10):], AAPL_plot)
AAPL_truncated = AAPL[datetime(2016, 4, 10):datetime(2016, 4, 26)]
midpoint = AAPL_truncated['Open']/2 + AAPL_truncated['Close']/2
AAPL_plot.plot(AAPL_truncated.index, midpoint, label='Midpoint')
AAPL_plot.vlines(date2num(datetime(2016, 4, 26, 12)),
ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],
color='g', label='Earnings Release')
AAPL_plot.legend(loc=3)
AAPL_plot.set_title('AAPL Midpoint Plot');
+

png

+

Given these charts, we can see that FB was trending down for the four days preceding the earnings release, and AAPL was trending down for a whopping 8 days (we don't count the peak day). This will define the methodology that we will use for the study.

+

So what are the results? For a given horizon, how well does the market actually perform?

+
Code
# Read in the events for each stock;
# The file was created using the first code block in the Appendix
import yaml
from dateutil.parser import parse
from progressbar import ProgressBar

data_str = open('earnings_dates.yaml', 'r').read()
# Need to remove invalid lines
filtered = filter(lambda x: '{' not in x, data_str.split('\n'))
earnings_data = yaml.load('\n'.join(filtered))

# Convert our earnings data into a list of (ticker, date) pairs
# to make it easy to work with.
# This is horribly inefficient, but should get us what we need
ticker_dates = []
for ticker, date_list in earnings_data.items():
for iso_str in date_list:
ticker_dates.append((ticker, parse(iso_str)))

def does_trend_down(ticker, event, horizon):
# Figure out if the `event` has a downtrend for
# the `horizon` days preceding it
# As an interpretation note: it is assumed that
# the closing price of day `event` is the reference
# point, and we want `horizon` days before that.
# The price_data.hdf was created in the second appendix code block
try:
ticker_data = pd.read_hdf('price_data.hdf', ticker)
data = ticker_data[event-TradeDay(horizon):event]
midpoints = data['Open']/2 + data['Close']/2

# Shift dates one forward into the future and subtract
# Effectively: do we trend down over all days?
elems = midpoints - midpoints.shift(1)
return len(elems)-1 == len(elems.dropna()[elems <= 0])
except KeyError:
# If the stock doesn't exist, it doesn't qualify as trending down
# Mostly this is here to make sure the entire analysis doesn't
# blow up if there were issues in data retrieval
return False

def study_trend(horizon, trend_function):
five_day_events = np.zeros((1, horizon*2 + 1))
invalid_events = []
for ticker, event in ProgressBar()(ticker_dates):
if trend_function(ticker, event, horizon):
ticker_data = pd.read_hdf('price_data.hdf', ticker)
event_data = ticker_data[event-TradeDay(horizon):event+TradeDay(horizon)]['Close']

try:
five_day_events = np.vstack([five_day_events, event_data])
except ValueError:
# Sometimes we don't get exactly the right number of values due to calendar
# issues. I've fixed most everything I can, and the few issues that are left
# I assume don't systemically bias the results (i.e. data could be missing
# because it doesn't exist, etc.). After running through, ~1% of events get
# discarded this way
invalid_events.append((ticker, event))


# Remove our initial zero row
five_day_events = five_day_events[1:,:]
plot_study(five_day_events)
plt.gcf().suptitle('Action over {} days: {} events'
.format(horizon,five_day_events.shape[0]))
plt.gcf().set_size_inches(18, 6)

# Start with a 5 day study
study_trend(5, does_trend_down)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:21:38 Time: 0:21:38
+

png

+

When a stock has been trending down for 5 days, once the earnings are announced it really doesn't move on average. However, the variability is incredible. This implies two important things:

+
    +
  1. The market is just as often wrong about an earnings announcement before it happens as it is correct
  2. +
  3. The incredible width of the min/max bars and standard deviation area tell us that the market reacts violently after the earnings are released.
  4. +
+

Let's repeat the same study, but over a time horizon of 8 days and 3 days. Presumably if a stock has been going down for 8 days at a time before the earnings, the market should be more accurate.

+
Code
# 8 day study next
study_trend(8, does_trend_down)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:29 Time: 0:20:29
+

png

+

However, looking only at stocks that trended down for 8 days prior to a release, the same pattern emerges: on average, the stock doesn't move, but the market reaction is often incredibly violent.

+
Code
# 3 day study after that
study_trend(3, does_trend_down)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:26 Time: 0:26:26
+

png

+

Finally, when we look at a 3-day horizon, we start getting some incredible outliers. Stocks have a potential to move over ~300% up, and the standard deviation width is again, incredible. The results for a 3-day horizon follow the same pattern we've seen in the 5- and 8-day horizons.

+ +

We're now going to repeat the analysis, but do it for uptrends instead. That is, instead of looking at stocks that have been trending down over the past number of days, we focus only on stocks that have been trending up.

+
Code
def does_trend_up(ticker, event, horizon):
# Figure out if the `event` has an uptrend for
# the `horizon` days preceding it
# As an interpretation note: it is assumed that
# the closing price of day `event` is the reference
# point, and we want `horizon` days before that.
# The price_data.hdf was created in the second appendix code block
try:
ticker_data = pd.read_hdf('price_data.hdf', ticker)
data = ticker_data[event-TradeDay(horizon):event]
midpoints = data['Open']/2 + data['Close']/2

# Shift dates one forward into the future and subtract
# Effectively: do we trend down over all days?
elems = midpoints - midpoints.shift(1)
return len(elems)-1 == len(elems.dropna()[elems >= 0])
except KeyError:
# If the stock doesn't exist, it doesn't qualify as trending down
# Mostly this is here to make sure the entire analysis doesn't
# blow up if there were issues in data retrieval
return False

study_trend(5, does_trend_up)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:22:51 Time: 0:22:51
+

png

+

The patterns here are very similar. With the exception of noting that stocks can go to nearly 400% after an earnings announcement (most likely this included a takeover announcement, etc.), we still see large min/max bars and wide standard deviation of returns.

+

We'll repeat the pattern for stocks going up for both 8 and 3 days straight, but at this point, the results should be very predictable:

+
Code
study_trend(8, does_trend_up)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:51 Time: 0:20:51
+

png

+
Code
study_trend(3, does_trend_up)
    100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:56 Time: 0:26:56
+

png

+

Conclusion and Summary

+

I guess the most important thing to summarize with is this: looking at the entire market, stock performance prior to an earnings release has no bearing on the stock's performance. Honestly: given the huge variability of returns after an earnings release, even when the stock has been trending for a long time, you're best off divesting before an earnings release and letting the market sort itself out.

+

However, there is a big caveat. These results are taken when we look at the entire market. So while we can say that the market as a whole knows nothing and just reacts violently, I want to take a closer look into this data. Does the market typically perform poorly on large-cap/high liquidity stocks? Do smaller companies have investors that know them better and can thus predict performance better? Are specific market sectors better at prediction? Presumably technology stocks are more volatile than the industrials.

+

So there are some more interesting questions I still want to ask with this data. Knowing that the hard work of data processing is largely already done, it should be fairly simple to continue this analysis and get much more refined with it. Until next time.

+

Appendix

+

Export event data for Russell 3000 companies:

+
Code
import pandas as pd
from html.parser import HTMLParser
from datetime import datetime, timedelta
import requests
import re
from dateutil import parser
import progressbar
from concurrent import futures
import yaml

class EarningsParser(HTMLParser):
store_dates = False
earnings_offset = None
dates = []

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.dates = []

def handle_starttag(self, tag, attrs):
if tag == 'table':
self.store_dates = True

def handle_data(self, data):
if self.store_dates:
match = re.match(r'\d+/\d+/\d+', data)
if match:
self.dates.append(match.group(0))

# If a company reports before the bell, record the earnings date
# being at midnight the day before. Ex: WMT reports 5/19/2016,
# but we want the reference point to be the closing price on 5/18/2016
if 'After Close' in data:
self.earnings_offset = timedelta(days=0)
elif 'Before Open' in data:
self.earnings_offset = timedelta(days=-1)

def handle_endtag(self, tag):
if tag == 'table':
self.store_dates = False

def earnings_releases(ticker):
#print("Looking up ticker {}".format(ticker))
user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) '\
'Gecko/20100101 Firefox/46.0'
headers = {'user-agent': user_agent}
base_url = 'http://www.streetinsider.com/ec_earnings.php?q={}'\
.format(ticker)
e = EarningsParser()
s = requests.Session()
a = requests.adapters.HTTPAdapter(max_retries=0)
s.mount('http://', a)
e.feed(str(s.get(base_url, headers=headers).content))

if e.earnings_offset is not None:
dates = map(lambda x: parser.parse(x) + e.earnings_offset, e.dates)
past = filter(lambda x: x < datetime.now(), dates)
return list(map(lambda d: d.isoformat(), past))

# Use a Russell-3000 ETF tracker (ticker IWV) to get a list of holdings
r3000 = pd.read_csv('https://www.ishares.com/us/products/239714/'
'ishares-russell-3000-etf/1449138789749.ajax?'
'fileType=csv&fileName=IWV_holdings&dataType=fund',
header=10)
r3000_equities = r3000[(r3000['Exchange'] == 'NASDAQ') |
(r3000['Exchange'] == 'New York Stock Exchange Inc.')]

dates_file = open('earnings_dates.yaml', 'w')

with futures.ThreadPoolExecutor(max_workers=8) as pool:
fs = {pool.submit(earnings_releases, r3000_equities.ix[t]['Ticker']): t
for t in r3000_equities.index}
pbar = progressbar.ProgressBar(term_width=80,
max_value=r3000_equities.index.max())

for future in futures.as_completed(fs):
i = fs[future]
pbar.update(i)
dates_file.write(yaml.dump({r3000_equities.ix[i]['Ticker']:
future.result()}))
+

Downloading stock price data needed for the event studies:

+
Code
from secrets import QUANDL_KEY
import pandas as pd
import yaml
from dateutil.parser import parse
from datetime import timedelta
import quandl
from progressbar import ProgressBar

def fetch_ticker(ticker, start, end):
# Quandl is currently giving me issues with returning
# the entire dataset and not slicing server-side.
# So instead, we'll do it client-side!
q_format = '%Y-%m-%d'
ticker_data = quandl.get('YAHOO/' + ticker,
start_date=start.strftime(q_format),
end_date=end.strftime(q_format),
authtoken=QUANDL_KEY)
return ticker_data

data_str = open('earnings_dates.yaml', 'r').read()
# Need to remove invalid lines
filtered = filter(lambda x: '{' not in x, data_str.split('\n'))
earnings_data = yaml.load('\n'.join(filtered))

# Get the first 1500 keys - split up into two statements
# because of Quandl rate limits
tickers = list(earnings_data.keys())

price_dict = {}
invalid_tickers = []
for ticker in ProgressBar()(tickers[0:1500]):
try:
# Replace '.' with '-' in name for some tickers
fixed = ticker.replace('.', '-')
event_strs = earnings_data[ticker]
events = [parse(event) for event in event_strs]
td = timedelta(days=20)
price_dict[ticker] = fetch_ticker(fixed,
min(events)-td, max(events)+td)
except quandl.NotFoundError:
invalid_tickers.append(ticker)

# Execute this after 10 minutes have passed
for ticker in ProgressBar()(tickers[1500:]):
try:
# Replace '.' with '-' in name for some tickers
fixed = ticker.replace('.', '-')
event_strs = earnings_data[ticker]
events = [parse(event) for event in event_strs]
td = timedelta(days=20)
price_dict[ticker] = fetch_ticker(fixed,
min(events)-td, max(events)+td)
except quandl.NotFoundError:
invalid_tickers.append(ticker)

prices_store = pd.HDFStore('price_data.hdf')
for ticker, prices in price_dict.items():
prices_store[ticker] = prices
\ No newline at end of file diff --git a/2016/10/rustic-repodcasting/index.html b/2016/10/rustic-repodcasting/index.html new file mode 100644 index 0000000..569bb30 --- /dev/null +++ b/2016/10/rustic-repodcasting/index.html @@ -0,0 +1,187 @@ +A Rustic re-podcasting server | The Old Speice Guy
Skip to main content

A Rustic re-podcasting server

· 11 min read
Bradlee Speice

Learning Rust by fire (it sounds better than learning by corrosion)

+

I listen to a lot of Drum and Bass music, because it's beautiful music. And +there's a particular site, Bassdrive.com that hosts +a lot of great content. Specifically, the +archives section of the site has a +list of the past shows that you can download and listen to. The issue is, it's +just a giant list of links to download. I'd really like +this in a podcast format to take with me on the road, etc.

+

So I wrote the elektricity web +application to actually accomplish all that. Whenever you request a feed, it +goes out to Bassdrive, processes all the links on a page, and serves up some +fresh, tasty RSS to satisfy your ears. I hosted it on Heroku using the free +tier because it's really not resource-intensive at all.

+

The issue so far is that I keep running out of free tier hours during a +month because my podcasting application likes to have a server scan for new +episodes constantly. Not sure why it's doing that, but I don't have a whole +lot of control over it. It's a phenomenal application otherwise.

+

My (over-engineered) solution: Re-write the application using the +Rust programming language. I'd like to run +this on a small hacker board I own, and doing this in Rust would allow me to +easily cross-compile it. Plus, I've been very interested in the Rust language +for a while and this would be a great opportunity to really learn it well. +The code is available here as development +progresses.

+

The Setup

+

We'll be using the iron library to handle the +server, and hyper to fetch the data we need from elsewhere +on the interwebs. HTML5Ever allows +us to ingest the content that will be coming from Bassdrive, and finally, +output is done with handlebars-rust.

+

It will ultimately be interesting to see how much more work must be done to +actually get this working over another language like Python. Coming from a +dynamic state of mind it's super easy to just chain stuff together, ship it out, +and call it a day. I think I'm going to end up getting much dirtier trying to +write all of this out.

+

Issue 1: Strings

+

Strings in Rust are hard. I acknowledge Python can get away with some things +that make strings super easy (and Python 3 has gotten better at cracking down +on some bad cases, str <-> bytes specifically), but Rust is hard.

+

Let's take for example the 404 error handler I'm trying to write. The result +should be incredibly simple: All I want is to echo back +Didn't find URL: <url>. Shouldn't be that hard right? In Python I'd just do +something like:

+
def echo_handler(request):
return "You're visiting: {}".format(request.uri)
+

And we'd call it a day. Rust isn't so simple. Let's start with the trivial +examples people post online:

+
fn hello_world(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, "You found the server!")))
}
+

Doesn't look too bad right? In fact, it's essentially the same as the Python +version! All we need to do is just send back a string of some form. So, we +look up the documentation for Request and see a url field that will contain +what we want. Let's try the first iteration:

+
fn hello_world(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, "You found the URL: " + req.url)))
}
+

Which yields the error:

+
    error[E0369]: binary operation `+` cannot be applied to type `&'static str`
+

OK, what's going on here? Time to start Googling for "concatenate strings in Rust". That's what we +want to do right? Concatenate a static string and the URL.

+

After Googling, we come across a helpful concat! macro that looks really nice! Let's try that one:

+
fn hello_world(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, concat!("You found the URL: ", req.url))))
}
+

And the error:

+
    error: expected a literal
+

Turns out Rust actually blows up because the concat! macro expects us to know +at compile time what req.url is. Which, in my outsider opinion, is a bit +strange. println! and format!, etc., all handle values they don't know at +compile time. Why can't concat!? By any means, we need a new plan of attack. +How about we try formatting strings?

+
fn hello_world(req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, format!("You found the URL: {}", req.url))))
}
+

And at long last, it works. Onwards!

+

Issue 2: Fighting with the borrow checker

+

Rust's single coolest feature is how the compiler can guarantee safety in your +program. As long as you don't use unsafe pointers in Rust, you're guaranteed +safety. And not having truly manual memory management is really cool; I'm +totally OK with never having to write malloc() again.

+

That said, even the Rust documentation makes a specific note:

+
+

Many new users to Rust experience something we like to call +‘fighting with the borrow checker’, where the Rust compiler refuses to +compile a program that the author thinks is valid.

+
+

If you have to put it in the documentation, it's not a helpful note: +it's hazing.

+

So now that we have a handler which works with information from the request, we +want to start making something that looks like an actual web application. +The router provided by iron isn't terribly difficult so I won't cover it. +Instead, the thing that had me stumped for a couple hours was trying to +dynamically create routes.

+

The unfortunate thing with Rust (in my limited experience at the moment) is that +there is a severe lack of non-trivial examples. Using the router is easy when +you want to give an example of a static function. But how do you you start +working on things that are a bit more complex?

+

We're going to cover that here. Our first try: creating a function which returns +other functions. This is a principle called currying. We set up a function that allows us to keep some data in scope +for another function to come later.

+
fn build_handler(message: String) -> Fn(&mut Request) -> IronResult<Response> {
move |_: &mut Request| {
Ok(Response::with((status::Ok, message)))
}
}
+

We've simply set up a function that returns another anonymous function with the +message parameter scoped in. If you compile this, you get not 1, not 2, but 5 +new errors. 4 of them are the same though:

+
    error[E0277]: the trait bound `for<'r, 'r, 'r> std::ops::Fn(&'r mut iron::Request<'r, 'r>) -> std::result::Result<iron::Response, iron::IronError> + 'static: std::marker::Sized` is not satisfied
+

...oookay. I for one, am not going to spend time trying to figure out what's +going on there.

+

And it is here that I will save the audience many hours of frustrated effort. +At this point, I decided to switch from iron to pure hyper since using +hyper would give me a much simpler API. All I would have to do is build a +function that took two parameters as input, and we're done. That said, it +ultimately posed many more issues because I started getting into a weird fight +with the 'static lifetime +and being a Rust newbie I just gave up on trying to understand it.

+

Instead, we will abandon (mostly) the curried function attempt, and instead +take advantage of something Rust actually intends us to use: struct and +trait.

+

Remember when I talked about a lack of non-trivial examples on the Internet? +This is what I was talking about. I could only find one example of this +available online, and it was incredibly complex and contained code we honestly +don't need or care about. There was no documentation of how to build routes that +didn't use static functions, etc. But, I'm assuming you don't really care about +my whining, so let's get to it.

+

The iron documentation mentions the Handler trait as being something we can implement. +Does the function signature for that handle() method look familiar? It's what +we've been working with so far.

+

The principle is that we need to define a new struct to hold our data, then +implement that handle() method to return the result. Something that looks +like this might do:

+
struct EchoHandler {
message: String
}

impl Handler for EchoHandler {
fn handle(&self, _: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, self.message)))
}
}

// Later in the code when we set up the router...
let echo = EchoHandler {
message: "Is it working yet?"
}
router.get("/", echo.handle, "index");
+

We attempt to build a struct, and give its handle method off to the router +so the router knows what to do.

+

You guessed it, more errors:

+
    error: attempted to take value of method `handle` on type `EchoHandler`
+

Now, the Rust compiler is actually a really nice fellow, and offers us help:

+
    help: maybe a `()` to call it is missing? If not, try an anonymous function
+

We definitely don't want to call that function, so maybe try an anonymous +function as it recommends?

+
router.get("/", |req: &mut Request| echo.handle(req), "index");
+

Another error:

+
    error[E0373]: closure may outlive the current function, but it borrows `echo`, which is owned by the current function
+

Another helpful message:

+
    help: to force the closure to take ownership of `echo` (and any other referenced variables), use the `move` keyword
+

We're getting closer though! Let's implement this change:

+
router.get("/", move |req: &mut Request| echo.handle(req), "index");
+

And here's where things get strange:

+
    error[E0507]: cannot move out of borrowed content
--> src/main.rs:18:40
|
18 | Ok(Response::with((status::Ok, self.message)))
| ^^^^ cannot move out of borrowed content
+

Now, this took me another couple hours to figure out. I'm going to explain it, +but keep this in mind: Rust only allows one reference at a time (exceptions +apply of course).

+

When we attempt to use self.message as it has been created in the earlier +struct, we essentially are trying to give it away to another piece of code. +Rust's semantics then state that we may no longer access it unless it is +returned to us (which iron's code does not do). There are two ways to fix +this:

+
    +
  1. Only give away references (i.e. &self.message instead of self.message) +instead of transferring ownership
  2. +
  3. Make a copy of the underlying value which will be safe to give away
  4. +
+

I didn't know these were the two options originally, so I hope this helps the +audience out. Because iron won't accept a reference, we are forced into the +second option: making a copy. To do so, we just need to change the function +to look like this:

+
Ok(Response::with((status::Ok, self.message.clone())))
+

Not so bad, huh? My only complaint is that it took so long to figure out exactly +what was going on.

+

And now we have a small server that we can configure dynamically. At long last.

+
+

Final sidenote: You can actually do this without anonymous functions. Just +change the router line to: +router.get("/", echo, "index");

+

Rust's type system seems to figure out that we want to use the handle() method.

+
+

Conclusion

+

After a good long days' work, we now have the routing functionality set up on +our application. We should be able to scale this pretty well in the future: +the RSS content we need to deliver in the future can be treated as a string, so +the building blocks are in place.

+

There are two important things I learned starting with Rust today:

+
    +
  1. Rust is a new language, and while the code is high-quality, the mindshare is coming.
  2. +
  3. I'm a terrible programmer.
  4. +
+

Number 1 is pretty obvious and not surprising to anyone. Number two caught me +off guard. I've gotten used to having either a garbage collector (Java, Python, +etc.) or playing a little fast and loose with scoping rules (C, C++). You don't +have to worry about object lifetime there. With Rust, it's forcing me to fully +understand and use well the memory in my applications. In the final mistake I +fixed (using .clone()) I would have been fine in C++ to just give away that +reference and never use it again. I wouldn't have run into a "use-after-free" +error, but I would have potentially been leaking memory. Rust forced me to be +incredibly precise about how I use it.

+

All said I'm excited for using Rust more. I think it's super cool, it's just +going to take me a lot longer to do this than I originally thought.

\ No newline at end of file diff --git a/2016/11/pca-audio-compression/index.html b/2016/11/pca-audio-compression/index.html new file mode 100644 index 0000000..31f3c9c --- /dev/null +++ b/2016/11/pca-audio-compression/index.html @@ -0,0 +1,66 @@ +PCA audio compression | The Old Speice Guy
Skip to main content

PCA audio compression

· 11 min read
Bradlee Speice

In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.

+

Towards a new (and pretty poor) compression scheme

+

I'm going to be working with some audio data for a while as I get prepared for a term project this semester. I'll be working (with a partner) to design a system for separating voices from music. Given my total lack of experience with Digital Signal Processing I figured that now was as good a time as ever to work on a couple of fun projects that would get me back up to speed.

+

The first project I want to work on: Designing a new compression scheme for audio data.

+

A Brief Introduction to Audio Compression

+

Audio files when uncompressed (files ending with .wav) are huge. Like, 10.5 Megabytes per minute huge. Storage is cheap these days, but that's still an incredible amount of data that we don't really need. Instead, we'd like to compress that data so that it's not taking up so much space. There are broadly two ways to accomplish this:

+
    +
  1. +

    Lossless compression - Formats like FLAC, ALAC, and Monkey's Audio (.ape) all go down this route. The idea is that when you compress and uncompress a file, you get exactly the same as what you started with.

    +
  2. +
  3. +

    Lossy compression - Formats like MP3, Ogg, and AAC (.m4a) are far more popular, but make a crucial tradeoff: We can reduce the file size even more during compression, but the decompressed file won't be the same.

    +
  4. +
+

There is a fundamental tradeoff at stake: Using lossy compression sacrifices some of the integrity of the resulting file to save on storage space. Most people (I personally believe it's everybody) can't hear the difference, so this is an acceptable tradeoff. You have files that take up a 10th of the space, and nobody can tell there's a difference in audio quality.

+

A PCA-based Compression Scheme

+

What I want to try out is a PCA approach to encoding audio. The PCA technique comes from Machine Learning, where it is used for a process called Dimensionality Reduction. Put simply, the idea is the same as lossy compression: if we can find a way that represents the data well enough, we can save on space. There are a lot of theoretical concerns that lead me to believe this compression style will not end well, but I'm interested to try it nonetheless.

+

PCA works as follows: Given a dataset with a number of features, I find a way to approximate those original features using some "new features" that are statistically as close as possible to the original ones. This is comparable to a scheme like MP3: Given an original signal, I want to find a way of representing it that gets approximately close to what the original was. The difference is that PCA is designed for statistical data, and not signal data. But we won't let that stop us.

+

The idea is as follows: Given a signal, reshape it into 1024 columns by however many rows are needed (zero-padded if necessary). Run the PCA algorithm, and do dimensionality reduction with a couple different settings. The number of components I choose determines the quality: If I use 1024 components, I will essentially be using the original signal. If I use a smaller number of components, I start losing some of the data that was in the original file. This will give me an idea of whether it's possible to actually build an encoding scheme off of this, or whether I'm wasting my time.

+

Running the Algorithm

+

The audio I will be using comes from the song Tabulasa, by Broke for Free. I'll be loading in the audio signal to Python and using Scikit-Learn to actually run the PCA algorithm.

+

We first need to convert the FLAC file I have to a WAV:

+
!ffmpeg -hide_banner -loglevel panic -i "Broke For Free/XXVII/01 Tabulasa.flac" "Tabulasa.wav" -c wav
+

Then, let's go ahead and load a small sample so you can hear what is going on.

+
from IPython.display import Audio
from scipy.io import wavfile

samplerate, tabulasa = wavfile.read('Tabulasa.wav')

start = samplerate * 14 # 10 seconds in
end = start + samplerate * 10 # 5 second duration
Audio(data=tabulasa[start:end, 0], rate=samplerate)
+ + +

Next, we'll define the code we will be using to do PCA. It's very short, as the PCA algorithm is very simple.

+
from sklearn.decomposition import PCA
import numpy as np

def pca_reduce(signal, n_components, block_size=1024):

# First, zero-pad the signal so that it is divisible by the block_size
samples = len(signal)
hanging = block_size - np.mod(samples, block_size)
padded = np.lib.pad(signal, (0, hanging), 'constant', constant_values=0)

# Reshape the signal to have 1024 dimensions
reshaped = padded.reshape((len(padded) // block_size, block_size))

# Second, do the actual PCA process
pca = PCA(n_components=n_components)
pca.fit(reshaped)

transformed = pca.transform(reshaped)
reconstructed = pca.inverse_transform(transformed).reshape((len(padded)))
return pca, transformed, reconstructed
+

Now that we've got our functions set up, let's try actually running something. First, we'll use n_components == block_size, which implies that we should end up with the same signal we started with.

+
tabulasa_left = tabulasa[:,0]

_, _, reconstructed = pca_reduce(tabulasa_left, 1024, 1024)

Audio(data=reconstructed[start:end], rate=samplerate)
+ + +

OK, that does indeed sound like what we originally had. Let's drastically cut down the number of components we're doing this with as a sanity check: the audio quality should become incredibly poor.

+
_, _, reconstructed = pca_reduce(tabulasa_left, 32, 1024)

Audio(data=reconstructed[start:end], rate=samplerate)
+ + +

As expected, our reconstructed audio does sound incredibly poor! But there's something else very interesting going on here under the hood. Did you notice that the bassline comes across very well, but that there's no midrange or treble? The drums are almost entirely gone.

+

Drop the (Treble)

+

It will help to understand PCA more fully when trying to read this part, but I'll do my best to break it down. PCA tries to find a way to best represent the dataset using "components." Think of each "component" as containing some of the information you need in order to reconstruct the full audio. For example, you might have a "low frequency" component that contains all the information you need in order to hear the bassline. There might be other components that explain the high frequency things like singers, or melodies, that you also need.

+

What makes PCA interesting is that it attempts to find the "most important" components in explaining the signal. In a signal processing world, this means that PCA is trying to find the signal amongst the noise in your data. In our case, this means that PCA, when forced to work with small numbers of components, will chuck out the noisy components first. It's doing it's best job to reconstruct the signal, but it has to make sacrifices somewhere.

+

So I've mentioned that PCA identifies the "noisy" components in our dataset. This is equivalent to saying that PCA removes the "high frequency" components in this case: it's very easy to represent a low-frequency signal like a bassline. It's far more difficult to represent a high-frequency signal because it's changing all the time. When you force PCA to make a tradeoff by using a small number of components, the best it can hope to do is replicate the low-frequency sections and skip the high-frequency things.

+

This is a very interesting insight, and it also has echos (pardon the pun) of how humans understand music in general. Other encoding schemes (like MP3, etc.) typically chop off a lot of the high-frequency range as well. There is typically a lot of high-frequency noise in audio that is nearly impossible to hear, so it's easy to remove it without anyone noticing. PCA ends up doing something similar, and while that certainly wasn't the intention, it is an interesting effect.

+

A More Realistic Example

+

So we've seen the edge cases so far: Using a large number of components results in audio very close to the original, and using a small number of components acts as a low-pass filter. How about we develop something that sounds "good enough" in practice, that we can use as a benchmark for size? We'll use ourselves as judges of audio quality, and build another function to help us estimate how much space we need to store everything in.

+
from bz2 import compress
import pandas as pd

def raw_estimate(transformed, pca):
# We assume that we'll be storing things as 16-bit WAV,
# meaning two bytes per sample
signal_bytes = transformed.tobytes()
# PCA stores the components as floating point, we'll assume
# that means 32-bit floats, so 4 bytes per element
component_bytes = transformed.tobytes()

# Return a result in megabytes
return (len(signal_bytes) + len(component_bytes)) / (2**20)

# Do an estimate for lossless compression applied on top of our
# PCA reduction
def bz2_estimate(transformed, pca):
bytestring = transformed.tobytes() + b';' + pca.components_.tobytes()
compressed = compress(bytestring)
return len(compressed) / (2**20)

compression_attempts = [
(1, 1),
(1, 2),
(1, 4),
(4, 32),
(16, 256),
(32, 256),
(64, 256),
(128, 1024),
(256, 1024),
(512, 1024),
(128, 2048),
(256, 2048),
(512, 2048),
(1024, 2048)
]

def build_estimates(signal, n_components, block_size):
pca, transformed, recon = pca_reduce(tabulasa_left, n_components, block_size)
raw_pca_estimate = raw_estimate(transformed, pca)
bz2_pca_estimate = bz2_estimate(transformed, pca)
raw_size = len(recon.tobytes()) / (2**20)
return raw_size, raw_pca_estimate, bz2_pca_estimate

pca_compression_results = pd.DataFrame([
build_estimates(tabulasa_left, n, bs)
for n, bs in compression_attempts
])

pca_compression_results.columns = ["Raw", "PCA", "PCA w/ BZ2"]
pca_compression_results.index = compression_attempts
pca_compression_results
+
RawPCAPCA w/ BZ2
(1, 1)69.054298138.10859716.431797
(1, 2)69.05430669.05430632.981380
(1, 4)69.05432134.52716116.715032
(4, 32)69.05444317.2636118.481735
(16, 256)69.0546888.6318364.274846
(32, 256)69.05468817.2636728.542909
(64, 256)69.05468834.52734417.097543
(128, 1024)69.05468817.2636729.430644
(256, 1024)69.05468834.52734418.870387
(512, 1024)69.05468869.05468837.800940
(128, 2048)69.0625008.6328126.185015
(256, 2048)69.06250017.26562512.366942
(512, 2048)69.06250034.53125024.736506
(1024, 2048)69.06250069.06250049.517493
+

As we can see, there are a couple of instances where we do nearly 20 times better on storage space than the uncompressed file. Let's here what that sounds like:

+
_, _, reconstructed = pca_reduce(tabulasa_left, 16, 256)
Audio(data=reconstructed[start:end], rate=samplerate)
+ + +

It sounds incredibly poor though. Let's try something that's a bit more realistic:

+
_, _, reconstructed = pca_reduce(tabulasa_left, 1, 4)
Audio(data=reconstructed[start:end], rate=samplerate)
+ + +

And just out of curiosity, we can try something that has the same ratio of components to block size. This should be close to an apples-to-apples comparison.

+
_, _, reconstructed = pca_reduce(tabulasa_left, 64, 256)
Audio(data=reconstructed[start:end], rate=samplerate)
+ + +

The smaller block size definitely has better high-end response, but I personally think the larger block size sounds better overall.

+

Conclusions

+

So, what do I think about audio compression using PCA?

+

Strangely enough, it actually works pretty well relative to what I expected. That said, it's a terrible idea in general.

+

First off, you don't really save any space. The component matrix needed to actually run the PCA algorithm takes up a lot of space on its own, so it's very difficult to save space without sacrificing a huge amount of audio quality. And even then, codecs like AAC sound very nice even at bitrates that this PCA method could only dream of.

+

Second, there's the issue of audio streaming. PCA relies on two components: the datastream, and a matrix used to reconstruct the original signal. While it is easy to stream the data, you can't stream that matrix. And even if you divided the stream up into small blocks to give you a small matrix, you must guarantee that the matrix arrives; if you don't have that matrix, the data stream will make no sense whatsoever.

+

All said, this was an interesting experiment. It's really cool seeing PCA used for signal analysis where I haven't seen it applied before, but I don't think it will lead to any practical results. Look forward to more signal processing stuff in the future!

\ No newline at end of file diff --git a/2018/01/captains-cookbook-part-1/index.html b/2018/01/captains-cookbook-part-1/index.html new file mode 100644 index 0000000..0e8e3cd --- /dev/null +++ b/2018/01/captains-cookbook-part-1/index.html @@ -0,0 +1,88 @@ +Captain's Cookbook: Project setup | The Old Speice Guy
Skip to main content

Captain's Cookbook: Project setup

· 8 min read
Bradlee Speice

A basic introduction to getting started with Cap'N Proto.

+

I've been working a lot with Cap'N Proto recently with Rust, but there's a real dearth of information +on how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's +fantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going.

+

So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with Protobuf +and FlatBuffers, but is better compared with FlatBuffers. The whole point behind it +is to define a schema language and serialization format such that:

+
    +
  1. Applications that do not share the same base programming language can communicate
  2. +
  3. The data and schema you use can naturally evolve over time as your needs change
  4. +
+

Accompanying this are typically code generators that take the schemas you define for your application and give you back +code for different languages to get data to and from that schema.

+

Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way +as is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.

+

We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some +examples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects. +If you want to follow along, feel free. If not, I've posted the final result +for reference.

+

Step 1: Installing capnp

+

The capnp binary itself is needed for taking the schema files you write and turning them into a format that can be used by the +code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed.

+

I'll refer you to Cap'N Proto's installation instructions here. As a quick TLDR though:

+
    +
  • Linux users will likely have a binary shipped by their package manager - On Ubuntu, apt install capnproto is enough
  • +
  • OS X users can use Homebrew as an easy install path. Just brew install capnp
  • +
  • Windows users are a bit more complicated. If you're using Chocolatey, there's a package available. If that doesn't work however, you need to download a release zip and make sure that the capnp.exe binary is in your %PATH% environment variable
  • +
+

The way you know you're done with this step is if the following command works in your shell:

+
capnp id
+

Step 2: Starting a Cap'N Proto Rust project

+

After the capnp binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple

+
mkdir capnp_cookbook_1
cd capnp_cookbook_1
cargo init --bin
+

We'll put the following content into Cargo.toml:

+
[package]
name = "capnp_cookbook_1"
version = "0.1.0"
authors = ["Bradlee Speice <bspeice@kcg.com>"]

[build-dependencies]
capnpc = "0.8" # 1

[dependencies]
capnp = "0.8" # 2
+

This sets up:

+
    +
  1. The Rust code generator (CAPNProto Compiler)
  2. +
  3. The Cap'N Proto runtime library (CAPNProto runtime)
  4. +
+

We've now got everything prepared that we need for writing a Cap'N Proto project.

+

Step 3: Writing a basic schema

+

We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure +you get familiar with how to start from a basic project.

+

First, we're going to create a top-level directory for storing the schema files in:

+
# Assuming we're starting from the `capnp_cookbook_1` directory created earlier

mkdir schema
cd schema
+

Now, we're going to put the following content in point.capnp:

+
@0xab555145c708dad2;

struct Point {
x @0 :Int32;
y @1 :Int32;
}
+

Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format.

+

Step 4: Setting up the build process

+

Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using. +This is typically done through a build.rs file to invoke the schema compiler.

+

In the same folder as your Cargo.toml file, please put the following content in build.rs:

+
extern crate capnpc;

fn main() {
::capnpc::CompilerCommand::new()
.src_prefix("schema") // 1
.file("schema/point.capnp") // 2
.run().expect("compiling schema");
}
+

This sets up the protocol compiler (capnpc from earlier) to compile the schema we've built so far.

+
    +
  1. Because Cap'N Proto schema files can re-use types specified in other files, the src_prefix() tells the compiler +where to look for those extra files at.
  2. +
  3. We specify the schema file we're including by hand. In a much larger project, you could presumably build the CompilerCommand +dynamically, but we won't worry too much about that one for now.
  4. +
+

Step 5: Running the build

+

If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code. +Run a cargo build command, and if you don't see cargo complaining, you're doing just fine!

+

So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated +code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives +somewhere in the target/ directory.

+

The long answer is that you're best off running a find command to get the actual file path:

+
# Assuming we're running from the capnp_cookbook_1 project folder
find . -name point_capnp.rs
+

Alternately, if the find command isn't available, the path will look something like:

+
./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs
+

See if there are any paths in your target directory that look similar.

+

Now, the file content looks pretty nasty. I've included an example here +if you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how +the schema we wrote for the "Point" message is tied to the generated code.

+

First, the Cap'N Proto library splits things up into Builder and Reader structs. These are best thought of the same way +Rust separates mut from non-mut code. Builders are mut versions of your message, and Readers are immutable versions.

+

For example, the Builder impl for point defines get_x(), set_x(), get_y(), and set_y() methods. +In comparison, the Reader impl only defines get_x() and get_y() methods.

+

So now we know that there are some get and set methods available for our x and y coordinates; +but what do we actually do with those?

+

Step 6: Making a point

+

So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building +Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code +should go in src/main.rs:

+
// Note that we use `capnp` here, NOT `capnpc`
extern crate capnp;

// We create a module here to define how we are to access the code
// being included.
pub mod point_capnp {
// The environment variable OUT_DIR is set by Cargo, and
// is the location of all the code that was built as part
// of the codegen step.
// point_capnp.rs is the actual file to include
include!(concat!(env!("OUT_DIR"), "/point_capnp.rs"));
}

fn main() {

// The process of building a Cap'N Proto message is a bit tedious.
// We start by creating a generic Builder; it acts as the message
// container that we'll later be filling with content of our `Point`
let mut builder = capnp::message::Builder::new_default();

// Because we need a mutable reference to the `builder` later,
// we fence off this part of the code to allow sequential mutable
// borrows. As I understand it, non-lexical lifetimes:
// https://github.com/rust-lang/rust-roadmap/issues/16
// will make this no longer necessary
{
// And now we can set up the actual message we're trying to create
let mut point_msg = builder.init_root::<point_capnp::point::Builder>();

// Stuff our message with some content
point_msg.set_x(12);

point_msg.set_y(14);
}

// It's now time to serialize our message to binary. Let's set up a buffer for that:
let mut buffer = Vec::new();

// And actually fill that buffer with our data
capnp::serialize::write_message(&mut buffer, &builder).unwrap();

// Finally, let's deserialize the data
let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

// `deserialized` is currently a generic reader; it understands
// the content of the message we gave it (i.e. that there are two
// int32 values) but doesn't really know what they represent (the Point).
// This is where we map the generic data back into our schema.
let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// We can now get our x and y values back, and make sure they match
assert_eq!(point_reader.get_x(), 12);
assert_eq!(point_reader.get_y(), 14);
}
+

And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up +some practical examples of Cap'N Proto in action:

\ No newline at end of file diff --git a/2018/01/captains-cookbook-part-2/index.html b/2018/01/captains-cookbook-part-2/index.html new file mode 100644 index 0000000..a54b9dc --- /dev/null +++ b/2018/01/captains-cookbook-part-2/index.html @@ -0,0 +1,75 @@ +Captain's Cookbook: Practical usage | The Old Speice Guy
Skip to main content

Captain's Cookbook: Practical usage

· 7 min read
Bradlee Speice

A look at more practical usages of Cap'N Proto

+

Part 1 of this series took a look at a basic starting project +with Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty +basic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's +some documentation surrounding practical usage of the library.

+

As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps +here. Our current example is going to build on +the code we wrote there; after the deserialization step, we'll try and send the point_reader to a separate thread +for verification.

+

I'm going to walk through the attempts as I made them and my thinking throughout. +If you want to skip to the final project, check out the code available here

+

Attempt 1: Move the reference

+

As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from
// somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// By using `point_reader` inside the new thread, we're hoping that Rust can
// safely move the reference and invalidate the original thread's usage.
// Since the original thread doesn't use `point_reader` again, this should
// be safe, right?
let handle = std::thread:spawn(move || {

assert_eq!(point_reader.get_x(), 12);

assert_eq!(point_reader.get_y(), 14);
});

handle.join().unwrap()
}
+

Well, the Rust compiler doesn't really like this. We get four distinct errors back:

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`                                                                                                                
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating. +Pay attention to the text that keeps on getting repeated though: XYZ cannot be sent between threads safely.

+

This is a bit frustrating: we own the buffer from which all the content was derived, and we don't have any +unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility +of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust +preventing us from doing something that really should be legal?

+

This is what is known as fighting the borrow checker. +Let our crusade begin.

+

Attempt 2: Put the Reader in a Box

+

The Box type allows us to convert a pointer we have +(in our case the point_reader) into an "owned" value, which should be easier to send across threads. +Our next attempt looks something like this:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content
// from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

let boxed_reader = Box::new(point_reader);

// Now that the reader is `Box`ed, we've proven ownership, and Rust can
// move the ownership to the new thread, right?
let handle = std::thread::spawn(move || {

assert_eq!(boxed_reader.get_x(), 12);

assert_eq!(boxed_reader.get_y(), 14);
});

handle.join().unwrap();
}
+

Spoiler alert: still doesn't work. Same errors still show up.

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`                       
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Let's be a little bit smarter about the exceptions this time though. What is that +std::marker::Send thing the compiler keeps telling us about?

+

The documentation is pretty clear; Send is used to denote:

+
+

Types that can be transferred across thread boundaries.

+
+

In our case, we are seeing the error messages for two reasons:

+
    +
  1. +

    Pointers (*const u8) are not safe to send across thread boundaries. While we're nice in our code +making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make +that assumption, and so complains that we're not using this in a safe manner.

    +
  2. +
  3. +

    The point_capnp::point::Reader type is itself not safe to send across threads because it doesn't +implement the Send trait. Which is to say, the things that make up a Reader are themselves not thread-safe, +so the Reader is also not thread-safe.

    +
  4. +
+

So, how are we to actually transfer a parsed Cap'N Proto message between threads?

+

Attempt 3: The TypedReader

+

The TypedReader is a new API implemented in the Cap'N Proto Rust code. +We're interested in it here for two reasons:

+
    +
  1. +

    It allows us to define an object where the object owns the underlying data. In previous attempts, +the current context owned the data, but the Reader itself had no such control.

    +
  2. +
  3. +

    We can compose the TypedReader using objects that are safe to Send across threads, guaranteeing +that we can transfer parsed messages across threads.

    +
  4. +
+

The actual type info for the TypedReader +is a bit complex. And to be honest, I'm still really not sure what the whole point of the +PhantomData thing is either. +My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto +message represents. That is, technically the only thing we're storing is the untyped binary message; +PhantomData just enforces the principle that the binary represents some specific object that has been parsed.

+

Either way, we can carefully construct something which is safe to move between threads:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> =
capnp::message::TypedReader::new(deserialized);

// Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message
// (which is 'static lifetime), this is now safe
let handle = std::thread::spawn(move || {

// The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader
// object from it
let point_root = point_reader.get().unwrap();

assert_eq!(point_root.get_x(), 12);

assert_eq!(point_root.get_y(), 14);
});

handle.join().unwrap();
}
+

And while we've left Rust to do the dirty work of actually moving the point_reader into the new thread, +we could also use things like mpsc channels to achieve a similar effect.

+

So now we're able to define basic Cap'N Proto messages, and send them all around our programs.

\ No newline at end of file diff --git a/2018/05/hello/index.html b/2018/05/hello/index.html new file mode 100644 index 0000000..6b5e017 --- /dev/null +++ b/2018/05/hello/index.html @@ -0,0 +1,9 @@ +Hello! | The Old Speice Guy
Skip to main content
\ No newline at end of file diff --git a/2018/06/dateutil-parser-to-rust/index.html b/2018/06/dateutil-parser-to-rust/index.html new file mode 100644 index 0000000..8b92328 --- /dev/null +++ b/2018/06/dateutil-parser-to-rust/index.html @@ -0,0 +1,142 @@ +What I learned porting dateutil to Rust | The Old Speice Guy
Skip to main content

What I learned porting dateutil to Rust

· 7 min read
Bradlee Speice

I've mostly been a lurker in Rust for a while, making a couple small contributions here and there. +So launching dtparse feels like nice step towards becoming a +functioning member of society. But not too much, because then you know people start asking you to +pay bills, and ain't nobody got time for that.

+

But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you +what to do with your life (but you should totally keep reading).

+

Slow down, what?

+

OK, fine, I guess I should start with why someone would do this.

+

Dateutil is a Python library for handling dates. The +standard library support for time in Python is kinda dope, but there are a lot of extras that go +into making it useful beyond just the datetime +module. dateutil.parser specifically is code to take all the super-weird time formats people come +up with and turn them into something actually useful.

+

Date/time parsing, it turns out, is just like everything else involving +computers and +time: it +feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people +suck and this is why +we can't we have nice things. But +alas, we'll try and make contemporary art out of the rubble and give it a pretentious name like +Time.

+

A gravel mound

+
+

Time

+
+

What makes dateutil.parser great is that there's single function with a single argument that +drives what programmers interact with: +parse(timestr). +It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can +possibly do to make sense of your input" value. It doesn't expect much of you.

+

And now it's in Rust.

+

Lost in Translation

+

Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm +admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can +actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better +experiences than +this guy +who attempted the same thing for D. These are the actual take-aways:

+

When transcribing code, stay as close to the original library as possible. I'm talking about +using the same variable names, same access patterns, the whole shebang. It's way too easy to make a +couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference +manual for verbatim what your code should be means that you don't spend that long debugging +complicated logic, you're more looking for typos.

+

Also, don't use nice Rust things like enums. While +one time it worked out OK for me, +I also managed to shoot myself in the foot a couple times because dateutil stores AM/PM as a +boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In +general, writing nice code should not be a first-pass priority when you're just trying to recreate +the same functionality.

+

Exceptions are a pain. Make peace with it. Python code is just allowed to skip stack frames. So +when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out +he's not quite right, and I'm OK with that. And while +dateutil is pretty well-behaved about not skipping multiple stack frames, +130-line try-catch blocks +take a while to verify.

+

As another Python quirk, be very careful about +long nested if-elif-else blocks. +I used to think that Python's whitespace was just there to get you to format your code correctly. I +think that no longer. It's way too easy to close a block too early and have incredibly weird issues +in the logic. Make sure you use an editor that displays indentation levels so you can keep things +straight.

+

Rust macros are not free. I originally had the +main test body +wrapped up in a macro using pyo3. It took two minutes to compile. +After +moving things to a function +compile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code +to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually +functions that need to be liberated, man.

+

Finally, I really miss list comprehensions and dictionary comprehensions. As a quick comparison, +see +this dateutil code +and +the implementation in Rust. +I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be +added through macros or syntax extensions. Either way, they're expressive, save typing, and are +super-readable. Let's get more of that.

+

Using a young language

+

Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On +more than one occasion though, I've had issues navigating the Rust ecosystem.

+

What I'll call the "canonical library" is still being built. In Python, if you need datetime +parsing, you use dateutil. If you want decimal types, it's already in the +standard library. While I might've gotten away +with f64, dateutil uses decimals, and I wanted to follow the principle of staying as close to +the original library as possible. Thus began my quest to find a decimal library in Rust. What I +quickly found was summarized in a comment:

+
+

Writing a BigDecimal is easy. Writing a good BigDecimal is hard.

+

-cmr

+
+

In practice, this means that there are at least 4 +different +implementations available. +And that's a lot of decisions to worry about when all I'm thinking is "why can't +calendar reform be a thing" and I'm forced to dig +through a couple +different +threads to figure out if the library I'm look at is dead +or just stable.

+

And even when the "canonical library" exists, there's no guarantees that it will be well-maintained. +Chrono is the de facto date/time library in Rust, and just +released version 0.4.4 like two days ago. Meanwhile, +chrono-tz appears to be dead in the water even though +there are people happy to help maintain it. I +know relatively little about it, but it appears that most of the release process is automated; +keeping that up to date should be a no-brainer.

+

Trial Maintenance Policy

+

Specifically given "maintenance" being an +oft-discussed +issue, I'm going to try out the following policy to keep things moving on dtparse:

+
    +
  1. +

    Issues/PRs needing maintainer feedback will be updated at least weekly. I want to make sure +nobody's blocking on me.

    +
  2. +
  3. +

    To keep issues/PRs needing contributor feedback moving, I'm going to (kindly) ask the +contributor to check in after two weeks, and close the issue without resolution if I hear nothing +back after a month.

    +
  4. +
+

The second point I think has the potential to be a bit controversial, so I'm happy to receive +feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm +running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And +second: I don't mind keeping those requests going indefinitely. I just want to try and balance +keeping things moving with giving people the necessary time they need.

+

I should also note that I'm still getting some best practices in place - CONTRIBUTING and +CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are +perfect.

+

Roadmap and Conclusion

+

So if I've now built a dateutil-compatible parser, we're done, right? Of course not! That's not +nearly ambitious enough.

+

Ultimately, I'd love to have a library that's capable of parsing everything the Linux date command +can do (and not date on OSX, because seriously, BSD coreutils are the worst). I know Rust has a +coreutils rewrite going on, and dtparse would potentially be an interesting candidate since it +doesn't bring in a lot of extra dependencies. humantime +could help pick up some of the (current) slack in dtparse, so maybe we can share and care with each +other?

+

All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month +on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going +to take it hard.

+

And in the mean time, I'm looking forward to building more. Onwards.

\ No newline at end of file diff --git a/2018/09/isomorphic-apps/index.html b/2018/09/isomorphic-apps/index.html new file mode 100644 index 0000000..19cbb89 --- /dev/null +++ b/2018/09/isomorphic-apps/index.html @@ -0,0 +1,184 @@ +Isomorphic desktop apps with Rust | The Old Speice Guy
Skip to main content

Isomorphic desktop apps with Rust

· 10 min read
Bradlee Speice

I both despise Javascript and am stunned by its success doing some really cool things. It's +this duality that's +led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I +bootstrap a simple desktop application.

+

See, as much as +Webassembly isn't trying to replace Javascript, +I want Javascript gone. There are plenty of people who don't share my views, and they are +probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think +it's hilarious that the +language specification +dramatically outpaces anyone's +actual implementation. The answer to this +conundrum is of course to recompile code from newer versions of the language to older versions of +the same language before running. At least Babel is a nice tongue-in-cheek reference.

+

Yet for as much hate as Electron receives, it does a stunningly good job at solving a really hard +problem: how the hell do I put a button on the screen and react when the user clicks it? GUI +programming is hard, straight up. But if browsers are already able to run everywhere, why don't we +take advantage of someone else solving the hard problems for us? I don't like that I have to use +Javascript for it, but I really don't feel inclined to whip out good ol' wxWidgets.

+

Now there are other native solutions (libui-rs, conrod, oh hey wxWdidgets again!), but +those also have their own issues with distribution, styling, etc. With Electron, I can +yarn create electron-app my-app and just get going, knowing that packaging/upgrades/etc. are built +in.

+

My question is: given recent innovations with WASM, are we Electron yet?

+

No, not really.

+

Instead, what would it take to get to a point where we can skip Javascript in Electron apps?

+

Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There +may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to +try and organize what I did manage to discover.

+

I should also mention that the content and things I'm talking about here are not intended to be +prescriptive, but more "if someone else is interested, what do we already know doesn't work?" I +expect everything in this post to be obsolete within two months. Even over the course of writing +this, a separate blog post had +to be modified because upstream changes broke a +Rust tool the post tried to use. The post +ultimately +got updated, but +all this happened within the span of a week. Things are moving quickly.

+

I'll also note that we're going to skip asm.js and emscripten. Truth be told, I couldn't get +either of these to output anything, and so I'm just going to say +here be dragons. Everything I'm discussing here +uses the wasm32-unknown-unknown target.

+

The code that I did get running is available +over here. Feel free to use it as a starting point, +but I'm mostly including the link as a reference for the things that were attempted.

+

An Example Running Application

+

So, I did technically get a running application:

+

Electron app using WASM

+

...which you can also try out if you want:

+
git clone https://github.com/speice-io/isomorphic-rust.git
cd isomorphic_rust/percy
yarn install && yarn start
+

...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly +there to prove this is possible in the first place. And that's something to be proud of! There's a +huge amount of engineering that went into showing a window with the text "It's alive!".

+

There's also a lot of usability issues that prevent me from recommending anyone try Electron and +WASM apps at the moment, and I think that's the more important thing to discuss.

+

Issue the First: Complicated Toolchains

+

I quickly established that wasm-bindgen was necessary to "link" my Rust code to Javascript. At +that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM +blob. To keep things simple, the goal was to package everything using webpack so that I could just +load a bundle.js file on the page. That decision was to be the last thing that kinda worked in +this process.

+

The first issue +I ran into +while attempting to bundle everything via webpack is a detail in the WASM spec:

+
+

This function accepts a Response object, or a promise for one, and ... [if > it] does not match +the application/wasm MIME type, the returned promise will be rejected with a TypeError;

+

WebAssembly - Additional Web Embedding API

+
+

Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the +web this isn't a huge issue, as the server can set MIME types when delivering the blob. With +Electron, you're resolving things with a file:// URL and thus can't control the MIME type:

+

TypeError: Incorrect response MIME type. Expected &#39;application/wasm&#39;.

+

There are a couple of solutions depending on how far into the deep end you care to venture:

+
    +
  • Embed a static file server in your Electron application
  • +
  • Use a custom protocol and custom protocol handler
  • +
  • Host your WASM blob on a website that you resolve at runtime
  • +
+

But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. +Instead, my workaround was to +open a PR with webpack and use regex to remove +calls to instantiateStreaming in the +build script:

+
cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
# Have to use --mode=development so we can patch out the call to instantiateStreaming
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \
sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js"
+

Once that lands, the +build process +becomes much simpler:

+

cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js"
+

But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via +wasm-bindgen and webpack), we still have to make an Electron app. For this purpose I used a +starter app from Electron Forge, and then a +prestart script +to actually handle starting the application.

+

The +final toolchain +looks something like this:

+
    +
  • yarn start triggers the prestart script
  • +
  • prestart checks for missing tools (wasm-bindgen-cli, etc.) and then: +
      +
    • Uses cargo to compile the Rust code into WASM
    • +
    • Uses wasm-bindgen to link the WASM blob into a Javascript file with exported symbols
    • +
    • Uses webpack to bundle the page start script with the Javascript we just generated +
        +
      • Uses babel under the hood to compile the wasm-bindgen code down from ES6 into something +browser-compatible
      • +
      +
    • +
    +
  • +
  • The start script runs an Electron Forge handler to do some sanity checks
  • +
  • Electron actually starts
  • +
+

...which is complicated. I think more work needs to be done to either build a high-quality starter +app that can manage these steps, or another tool that "just handles" the complexity of linking a +compiled WASM file into something the Electron browser can run.

+

Issue the Second: WASM tools in Rust

+

For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only +bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that +leads to a fragmented ecosystem. Here's what I can recommend as a starting point:

+

Don't check in your Cargo.lock files to version control. If there's a disagreement between the +version of wasm-bindgen-cli you have installed and the wasm-bindgen you're compiling with in +Cargo.lock, you get a nasty error:

+
it looks like the Rust project used to create this wasm file was linked against
a different version of wasm-bindgen than this binary:

rust wasm file: 0.2.21
this binary: 0.2.17

Currently the bindgen format is unstable enough that these two version must
exactly match, so it's required that these two version are kept in sync by
either updating the wasm-bindgen dependency or this binary.
+

Not that I ever managed to run into this myself (coughs nervously).

+

There are two projects attempting to be "application frameworks": percy and yew. Between those, +I managed to get two +examples running +using percy, but was unable to get an +example running with yew because +of issues with "missing modules" during the webpack step:

+
ERROR in ./dist/electron_yew_wasm_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist'
@ ./dist/electron_yew_wasm_bg.wasm
@ ./dist/electron_yew_wasm.js
@ ./dist/app.js
@ ./dist/app_loader.js
+

If you want to work with the browser APIs directly, your choices are percy-webapis or stdweb (or +eventually web-sys). See above for my percy examples, but when I tried +an example with stdweb, I was +unable to get it running:

+
ERROR in ./dist/stdweb_electron_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist'
@ ./dist/stdweb_electron_bg.wasm
@ ./dist/stdweb_electron.js
@ ./dist/app_loader.js
+

At this point I'm pretty convinced that stdweb is causing issues for yew as well, but can't +prove it.

+

I did also get a minimal example +running that doesn't depend on any tools besides wasm-bindgen. However, it requires manually +writing "extern C" blocks for everything you need from the browser. Es no bueno.

+

Finally, from a tools and platform view, there are two up-and-coming packages that should be +mentioned: js-sys and web-sys. Their purpose is to be fundamental building blocks that exposes +the browser's APIs to Rust. If you're interested in building an app framework from scratch, these +should give you the most flexibility. I didn't touch either in my research, though I expect them to +be essential long-term.

+

So there's a lot in play from the Rust side of things, and it's just going to take some time to +figure out what works and what doesn't.

+

Issue the Third: Known Unknowns

+

Alright, so after I managed to get an application started, I stopped there. It was a good deal of +effort to chain together even a proof of concept, and at this point I'd rather learn Typescript +than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...

+

The important point I want to make is that there's a lot unknown about how any of this holds up +outside proofs of concept. Things I didn't attempt:

+
    +
  • Testing
  • +
  • Packaging
  • +
  • Updates
  • +
  • Literally anything related to why I wanted to use Electron in the first place
  • +
+

What it Would Take

+

Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and +WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an +application in production a couple months from now. But at the moment, I'm personally going to stay +away.

+

Let's finish with a wishlist then - here are the things that I think need to happen before +Electron/WASM/Rust can become a thing:

+
    +
  • Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet +(#7983)
  • +
  • Browser API libraries (web-sys and stdweb) need to make sure they can support running in +Electron (see module error above)
  • +
  • Projects need to stabilize. There's talk of stdweb being turned into a Rust API +on top of web-sys, and percy +moving to web-sys, both of which are big changes
  • +
  • wasm-bindgen is great, but still in the "move fast and break things" phase
  • +
  • A good "boilerplate" app would dramatically simplify the start-up costs; +electron-react-boilerplate comes to +mind as a good project to imitate
  • +
  • More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm +doing
  • +
\ No newline at end of file diff --git a/2018/09/primitives-in-rust-are-weird/index.html b/2018/09/primitives-in-rust-are-weird/index.html new file mode 100644 index 0000000..0719a3d --- /dev/null +++ b/2018/09/primitives-in-rust-are-weird/index.html @@ -0,0 +1,99 @@ +Primitives in Rust are weird (and cool) | The Old Speice Guy
Skip to main content

Primitives in Rust are weird (and cool)

· 7 min read
Bradlee Speice

I wrote a really small Rust program a while back because I was curious. I was 100% convinced it +couldn't possibly run:

+
fn main() {
println!("{}", 8.to_string())
}
+

And to my complete befuddlement, it compiled, ran, and produced a completely sensible output.

+

The reason I was so surprised has to do with how Rust treats a special category of things I'm going to +call primitives. In the current version of the Rust book, you'll see them referred to as +scalars, and in older versions they'll be called primitives, but +we're going to stick with the name primitive for the time being. Explaining why this program is so +cool requires talking about a number of other programming languages, and keeping a consistent +terminology makes things easier.

+

You've been warned: this is going to be a tedious post about a relatively minor issue that +involves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking +about with assembly.

+

Defining primitives (Java)

+

The reason I'm using the name primitive comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special +name for some specific types of values:

+
+
bool    char    byte
short int long
float double
+
+

They are referred to as primitives. And relative to the other bits of Java, +they have two unique features. First, they don't have to worry about the +billion-dollar mistake; +primitives in Java can never be null. Second: they can't have instance methods. +Remember that Rust program from earlier? Java has no idea what to do with it:

+
class Main {
public static void main(String[] args) {
int x = 8;
System.out.println(x.toString()); // Triggers a compiler error
}
}
+

The error is:

+
Main.java:5: error: int cannot be dereferenced
System.out.println(x.toString());
^
1 error
+

Specifically, Java's Object +and things that inherit from it are pointers under the hood, and we have to dereference them before +the fields and methods they define can be used. In contrast, primitive types are just values - +there's nothing to be dereferenced. In memory, they're just a sequence of bits.

+

If we really want, we can turn the int into an +Integer and then dereference +it, but it's a bit wasteful:

+
class Main {
public static void main(String[] args) {
int x = 8;
Integer y = Integer.valueOf(x);
System.out.println(y.toString());
}
}
+

This creates the variable y of type Integer (which inherits Object), and at run time we +dereference y to locate the toString() function and call it. Rust obviously handles things a bit +differently, but we have to dig into the low-level details to see it in action.

+

Low Level Handling of Primitives (C)

+

We first need to build a foundation for reading and understanding the assembly code the final answer +requires. Let's begin with showing how the C language (and your computer) thinks about "primitive" +values in memory:

+
void my_function(int num) {}

int main() {
int x = 8;
my_function(x);
}
+

The compiler explorer gives us an easy way of showing off the +assembly-level code that's generated: whose output has been lightly +edited

+
main:
push rbp
mov rbp, rsp
sub rsp, 16

; We assign the value `8` to `x` here
mov DWORD PTR [rbp-4], 8

; And copy the bits making up `x` to a location
; `my_function` can access (`edi`)
mov eax, DWORD PTR [rbp-4]
mov edi, eax

; Call `my_function` and give it control
call my_function

mov eax, 0
leave
ret

my_function:
push rbp
mov rbp, rsp

; Copy the bits out of the pre-determined location (`edi`)
; to somewhere we can use
mov DWORD PTR [rbp-4], edi
nop

pop rbp
ret
+

At a really low level of memory, we're copying bits around using the mov instruction; +nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C +to Rust:

+
fn my_function(x: i32) {}

fn main() {
let x = 8;
my_function(x)
}
+

And the assembly generated when we stick it in the +compiler explorer: again, lightly +edited

+
example::main:
push rax

; Look familiar? We're copying bits to a location for `my_function`
; The compiler just optimizes out holding `x` in memory
mov edi, 8

; Call `my_function` and give it control
call example::my_function

pop rax
ret

example::my_function:
sub rsp, 4

; And copying those bits again, just like in C
mov dword ptr [rsp], edi

add rsp, 4
ret
+

The generated Rust assembly is functionally pretty close to the C assembly: When working with +primitives, we're just dealing with bits in memory.

+

In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to +dereference. So what exactly is going on with this .to_string() function call?

+

impl primitive (and Python)

+

Now it's time to reveal my trap card show the revelation that tied all this +together: Rust has implementations for its primitive types. That's right, impl blocks aren't +only for structs and traits, primitives get them too. Don't believe me? Check out +u32, +f64 and +char as examples.

+

But the really interesting bit is how Rust turns those impl blocks into assembly. Let's break out +the compiler explorer once again:

+
pub fn main() {
8.to_string()
}
+

And the interesting bits in the assembly: heavily trimmed down

+
example::main:
sub rsp, 24
mov rdi, rsp
lea rax, [rip + .Lbyte_str.u]
mov rsi, rax

; Cool stuff right here
call <T as alloc::string::ToString>::to_string@PLT

mov rdi, rsp
call core::ptr::drop_in_place
add rsp, 24
ret
+

Now, this assembly is a bit more complicated, but here's the big revelation: we're calling +to_string() as a function that exists all on its own, and giving it the instance of 8. Instead +of thinking of the value 8 as an instance of u32 and then peeking in to find the location of the +function we want to call (like Java), we have a function that exists outside of the instance and +just give that function the value 8.

+

This is an incredibly technical detail, but the interesting idea I had was this: if to_string() +is a static function, can I refer to the unbound function and give it an instance?

+

Better explained in code (and a compiler explorer link because I +seriously love this thing):

+
struct MyVal {
x: u32
}

impl MyVal {
fn to_string(&self) -> String {
self.x.to_string()
}
}

pub fn main() {
let my_val = MyVal { x: 8 };

// THESE ARE THE SAME
my_val.to_string();
MyVal::to_string(&my_val);
}
+

Rust is totally fine "binding" the function call to the instance, and also as a static.

+

MIND == BLOWN.

+

Python does the same thing where I can both call functions bound to their instances and also call as +an unbound function where I give it the instance:

+
class MyClass():
x = 24

def my_function(self):
print(self.x)

m = MyClass()

m.my_function()
MyClass.my_function(m)
+

And Python tries to make you think that primitives can have instance methods...

+
>>> dir(8)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__',
...
'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__',
...]

>>> # Theoretically `8.__str__()` should exist, but:

>>> 8.__str__()
File "<stdin>", line 1
8.__str__()
^
SyntaxError: invalid syntax

>>> # It will run if we assign it first though:
>>> x = 8
>>> x.__str__()
'8'
+

...but in practice it's a bit complicated.

+

So while Python handles binding instance methods in a way similar to Rust, it's still not able to +run the example we started with.

+

Conclusion

+

This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor +details like primitives leads to really cool effects. Primitives are optimized like C in how they +have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python +(like both instance and late binding).

+

And when you put it together, there are areas where Rust does cool things nobody else can; as a +quirky feature of Rust's type system, 8.to_string() is actually valid code.

+

Now go forth and fool your friends into thinking you know assembly. This is all I've got.

\ No newline at end of file diff --git a/2018/10/case-study-optimization/index.html b/2018/10/case-study-optimization/index.html new file mode 100644 index 0000000..37f4615 --- /dev/null +++ b/2018/10/case-study-optimization/index.html @@ -0,0 +1,92 @@ +A case study in heaptrack | The Old Speice Guy
Skip to main content

A case study in heaptrack

· 5 min read
Bradlee Speice

I remember early in my career someone joking that:

+
+

Programmers have it too easy these days. They should learn to develop in low memory environments +and be more efficient.

+
+

...though it's not like the first code I wrote was for a +graphing calculator +packing a whole 24KB of RAM.

+

But the principle remains: be efficient with the resources you have, because +what Intel giveth, Microsoft taketh away.

+

My professional work is focused on this kind of efficiency; low-latency financial markets demand +that you understand at a deep level exactly what your code is doing. As I continue experimenting +with Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's +flexibility for the times I pretend to have a garbage collector, and flexibility for the times that +I really care about how memory is used.

+

This post is a (small) case study in how I went from the former to the latter. And ultimately, it's +intended to be a starting toolkit to empower analysis of your own code.

+

Curiosity

+

When I first started building the dtparse crate, my intention was to mirror as closely as possible +the equivalent Python library. Python, as you may know, is garbage collected. Very +rarely is memory usage considered in Python, and I likewise wasn't paying too much attention when +dtparse was first being built.

+

This lackadaisical approach to memory works well enough, and I'm not planning on making dtparse +hyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the +advent of Rust 1.28 and the +Global Allocator trait, I had a really +great idea: build a custom allocator that allows you to track your own allocations. That way, you +can do things like writing tests for both correct results and correct memory usage. I gave it a +shot, but learned very quickly: never write your own allocator. It went from "fun +weekend project" to "I have literally no idea what my computer is doing" at breakneck speed.

+

Instead, I'll highlight a separate path I took to make sense of my memory usage: heaptrack.

+

Turning on the System Allocator

+

This is the hardest part of the post. Because Rust uses +its own allocator by default, +heaptrack is unable to properly record unmodified Rust code. To remedy this, we'll make use of the +#[global_allocator] attribute.

+

Specifically, in lib.rs or main.rs, add this:

+
use std::alloc::System;

#[global_allocator]
static GLOBAL: System = System;
+

...and that's it. Everything else comes essentially for free.

+

Running heaptrack

+

Assuming you've installed heaptrack (Homebrew in Mac, package manager +in Linux, ??? in Windows), all that's left is to fire up your application:

+
heaptrack my_application
+

It's that easy. After the program finishes, you'll see a file in your local directory with a name +like heaptrack.my_appplication.XXXX.gz. If you load that up in heaptrack_gui, you'll see +something like this:

+

heaptrack

+
+

And even these pretty colors:

+

pretty colors

+

Reading Flamegraphs

+

To make sense of our memory usage, we're going to focus on that last picture - it's called a +"flamegraph". These charts are typically used to +show how much time your program spends executing each function, but they're used here to show how +much memory was allocated during those functions instead.

+

For example, we can see that all executions happened during the main function:

+

allocations in main

+

...and within that, all allocations happened during dtparse::parse:

+

allocations in dtparse

+

...and within that, allocations happened in two different places:

+

allocations in parseinfo

+

Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue: +what the heck is the Default thing doing?

+

pretty colors

+

Optimizing dtparse

+

See, I knew that there were some allocations during calls to dtparse::parse, but I was totally +wrong about where the bulk of allocations occurred in my program. Let me post the code and see if +you can spot the mistake:

+
/// Main entry point for using `dtparse`.
pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> {
let res = Parser::default().parse(
timestr, None, None, false, false,
None, false,
&HashMap::new(),
)?;

Ok((res.0, res.1))
}
+
+

dtparse

+
+
+

Because Parser::parse requires a mutable reference to itself, I have to create a new +Parser::default every time it receives a string. This is excessive! We'd rather have an immutable +parser that can be re-used, and avoid allocating memory in the first place.

+

Armed with that information, I put some time in to +make the parser immutable. +Now that I can re-use the same parser over and over, the allocations disappear:

+

allocations cleaned up

+

In total, we went from requiring 2 MB of memory in +version 1.0.2:

+

memory before

+

All the way down to 300KB in version 1.0.3:

+

memory after

+

Conclusion

+

In the end, you don't need to write a custom allocator to be efficient with memory, great tools +already exist to help you understand what your program is doing.

+

Use them.

+

Given that Moore's Law is +dead, we've all got to do +our part to take back what Microsoft stole.

\ No newline at end of file diff --git a/2018/12/allocation-safety/index.html b/2018/12/allocation-safety/index.html new file mode 100644 index 0000000..ee8d889 --- /dev/null +++ b/2018/12/allocation-safety/index.html @@ -0,0 +1,77 @@ +QADAPT - debug_assert! for allocations | The Old Speice Guy
Skip to main content

QADAPT - debug_assert! for allocations

· 5 min read
Bradlee Speice

I think it's part of the human condition to ignore perfectly good advice when it comes our way. A +bit over a month ago, I was dispensing sage wisdom for the ages:

+
+

I had a really great idea: build a custom allocator that allows you to track your own allocations. +I gave it a shot, but learned very quickly: never write your own allocator.

+

-- me

+
+

I proceeded to ignore it, because we never really learn from our mistakes.

+

There's another part of the human condition that derives joy from seeing things explode.

+

Explosions

+

And that's the part I'm going to focus on.

+

Why an Allocator?

+

So why, after complaining about allocators, would I still want to write one? There are three reasons +for that:

+
    +
  1. Allocation/dropping is slow
  2. +
  3. It's difficult to know exactly when Rust will allocate or drop, especially when using code that +you did not write
  4. +
  5. I want automated tools to verify behavior, instead of inspecting by hand
  6. +
+

When I say "slow," it's important to define the terms. If you're writing web applications, you'll +spend orders of magnitude more time waiting for the database than you will the allocator. However, +there's still plenty of code where micro- or nano-seconds matter; think +finance, +real-time audio, +self-driving cars, and +networking. In these situations it's simply +unacceptable for you to spend time doing things that are not your program, and waiting on the +allocator is not cool.

+

As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. +So, I propose we play a quick trivia game: Does this code invoke the allocator?

+

Example 1

+
fn my_function() {
let v: Vec<u8> = Vec::new();
}
+

No: Rust knows how big the Vec type is, +and reserves a fixed amount of memory on the stack for the v vector. However, if we wanted to +reserve extra space (using Vec::with_capacity) the allocator would get invoked.

+

Example 2

+
fn my_function() {
let v: Box<Vec<u8>> = Box::new(Vec::new());
}
+

Yes: Because Boxes allow us to work with things that are of unknown size, it has to allocate on +the heap. While the Box is unnecessary in this snippet (release builds will optimize out the +allocation), reserving heap space more generally is needed to pass a dynamically sized type to +another function.

+

Example 3

+
fn my_function(v: Vec<u8>) {
v.push(5);
}
+

Maybe: Depending on whether the Vector we were given has space available, we may or may not +allocate. Especially when dealing with code that you did not author, it's difficult to verify that +things behave as you expect them to.

+

Blowing Things Up

+

So, how exactly does QADAPT solve these problems? Whenever an allocation or drop occurs in code +marked allocation-safe, QADAPT triggers a thread panic. We don't want to let the program continue +as if nothing strange happened, we want things to explode.

+

However, you don't want code to panic in production because of circumstances you didn't predict. +Just like debug_assert!, QADAPT will +strip out its own code when building in release mode to guarantee no panics and no performance +impact.

+

Finally, there are three ways to have QADAPT check that your code will not invoke the allocator:

+

Using a procedural macro

+

The easiest method, watch an entire function for allocator invocation:

+
use qadapt::no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

#[no_alloc]
fn push_vec(v: &mut Vec<u8>) {
// This triggers a panic if v.len() == v.capacity()
v.push(5);
}

fn main() {
let v = Vec::with_capacity(1);

// This will *not* trigger a panic
push_vec(&v);

// This *will* trigger a panic
push_vec(&v);
}
+

Using a regular macro

+

For times when you need more precision:

+
use qadapt::assert_no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
let v = Vec::with_capacity(1);

// No allocations here, we already have space reserved
assert_no_alloc!(v.push(5));

// Even though we remove an item, it doesn't trigger a drop
// because it's a scalar. If it were a `Box<_>` type,
// a drop would trigger.
assert_no_alloc!({
v.pop().unwrap();
});
}
+

Using function calls

+

Both the most precise and most tedious:

+
use qadapt::enter_protected;
use qadapt::exit_protected;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
// This triggers an allocation (on non-release builds)
let v = Vec::with_capacity(1);

enter_protected();
// This does not trigger an allocation because we've reserved size
v.push(0);
exit_protected();

// This triggers an allocation because we ran out of size,
// but doesn't panic because we're no longer protected.
v.push(1);
}
+

Caveats

+

It's important to point out that QADAPT code is synchronous, so please be careful when mixing in +asynchronous functions:

+
use futures::future::Future;
use futures::future::ok;

#[no_alloc]
fn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> {
ok(12).and_then(|e| Ok(Vec::with_capacity(e)))
}

fn main() {
// This doesn't trigger a panic because the `and_then` closure
// wasn't run during the function call.
async_capacity();

// Still no panic
assert_no_alloc!(async_capacity());

// This will panic because the allocation happens during `unwrap`
// in the `assert_no_alloc!` macro
assert_no_alloc!(async_capacity().poll().unwrap());
}
+

Conclusion

+

While there's a lot more to writing high-performance code than managing your usage of the allocator, +it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing +what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for +most allocators. Version 1.0 was released today, and you can check it out over at +crates.io or on github.

+

I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will +help guide that. If there are topics you're interested in, let me know in the comments below!

\ No newline at end of file diff --git a/2018/12/what-small-business-really-means/index.html b/2018/12/what-small-business-really-means/index.html new file mode 100644 index 0000000..7985c4a --- /dev/null +++ b/2018/12/what-small-business-really-means/index.html @@ -0,0 +1,19 @@ +More "what companies really mean" | The Old Speice Guy
Skip to main content

More "what companies really mean"

· 2 min read
Bradlee Speice

I recently stumbled across a phenomenal small article entitled +What Startups Really Mean By "Why Should We Hire You?". +Having been interviewed by smaller companies (though not exactly startups), the questions and +subtexts are the same. There's often a question behind the question that you're actually trying to +answer, and I wish I spotted the nuance earlier in my career.

+

Let me also make note of one more question/euphemism I've come across:

+

How do you feel about production support?

+

Translation: We're a fairly small team, and when things break on an evening/weekend/Christmas +Day, can we call on you to be there?

+

I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're +incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning +that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make +it out the door before the zombie apocalypse.

+

Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people +who either enjoy that, or play along nicely enough that our systems keep working.

+

Small teams have no such luck. If you're interviewing at a small company, especially as a "data +scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the +most inopportune moments.

+

Terrible-but-popular answers include: It's a part of the job, and I'm happy to contribute.

\ No newline at end of file diff --git a/2019/02/08/compiler-optimizations/index.html b/2019/02/08/compiler-optimizations/index.html new file mode 100644 index 0000000..fbdc863 --- /dev/null +++ b/2019/02/08/compiler-optimizations/index.html @@ -0,0 +1,46 @@ +Allocations in Rust: Compiler optimizations | The Old Speice Guy
Skip to main content

Allocations in Rust: Compiler optimizations

· 4 min read

Up to this point, we've been discussing memory usage in the Rust language by focusing on simple +rules that are mostly right for small chunks of code. We've spent time showing how those rules work +themselves out in practice, and become familiar with reading the assembly code needed to see each +memory type (global, stack, heap) in action.

+

Throughout the series so far, we've put a handicap on the code. In the name of consistent and +understandable results, we've asked the compiler to pretty please leave the training wheels on. Now +is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the +Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them +do their job.

+

Similar to +"What Has My Compiler Done For Me Lately?", we're +focusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll +still be looking at assembly code to understand what's going on, but it's important to mention +again: please use automated tools like alloc-counter to +double-check memory behavior if it's something you care about. It's far too easy to mis-read +assembly in large code sections, you should always verify behavior if you care about memory usage.

+

The guiding principal as we move forward is this: optimizing compilers won't produce worse programs +than we started with. There won't be any situations where stack allocations get moved to heap +allocations. There will, however, be an opera of optimization.

+

Update 2019-02-10: When debugging a +related issue, it was discovered that the +original code worked because LLVM optimized out the entire function, rather than just the allocation +segments. The code has been updated with proper use of +read_volatile, and a previous section +on vector capacity has been removed.

+

The Case of the Disappearing Box

+

Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently +short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the +stack instead! The way this interacts with #[inline] attributes is a bit opaque, but the important +part is that LLVM can sometimes do better than the baseline Rust language:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

pub fn cmp(x: u32) {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// The compiler is able to see through the constant `Box`
// and directly compare `x` to 24 - assembly line 73
let y = Box::new(24);
let equals = x == *y;

// This call to drop is eliminated
drop(y);

// Need to mark the comparison result as volatile so that
// LLVM doesn't strip out all the code. If `y` is marked
// volatile instead, allocation will be forced.
unsafe { std::ptr::read_volatile(&equals) };

// Turn off panicking, as there are some deallocations
// when we exit main.
DO_PANIC.store(false, Ordering::SeqCst);
}

fn main() {
cmp(12)
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- Compiler Explorer

+

-- Rust Playground

+

Dr. Array or: how I learned to love the optimizer

+

Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping +out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if +you're not careful, they can make your benchmarks look +impossibly good. In Rust, the +black_box function (implemented in both +libtest and +criterion) will tell the compiler +to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up +running programs that previously caused errors:

+
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

pub fn main() {
// Normally this blows up because we can't reserve size on stack
// for the `EightM` struct. But because the compiler notices we
// never do anything with `_x`, it optimizes out the stack storage
// and the program completes successfully.
let _x = EightM::default();
}
+

-- Compiler Explorer

+

-- Rust Playground

\ No newline at end of file diff --git a/2019/02/a-heaping-helping/index.html b/2019/02/a-heaping-helping/index.html new file mode 100644 index 0000000..d1ea26f --- /dev/null +++ b/2019/02/a-heaping-helping/index.html @@ -0,0 +1,122 @@ +Allocations in Rust: Dynamic memory | The Old Speice Guy
Skip to main content

Allocations in Rust: Dynamic memory

· 6 min read
Bradlee Speice

Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and +some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how +the language uses dynamic memory (also referred to as the heap) is a system called ownership. +And as the docs mention, ownership +is Rust's most unique feature.

+

The heap is used in two situations; when the compiler is unable to predict either the total size of +memory needed, or how long the memory is needed for, it allocates space in the heap.

+

This happens +pretty frequently; if you want to download the Google home page, you won't know how large it is +until your program runs. And when you're finished with Google, we deallocate the memory so it can be +used to store other webpages. If you're interested in a slightly longer explanation of the heap, +check out +The Stack and the Heap +in Rust's documentation.

+

We won't go into detail on how the heap is managed; the +ownership documentation does a +phenomenal job explaining both the "why" and "how" of memory management. Instead, we're going to +focus on understanding "when" heap allocations occur in Rust.

+

To start off, take a guess for how many allocations happen in the program below:

+
fn main() {}
+

It's obviously a trick question; while no heap allocations occur as a result of that code, the setup +needed to call main does allocate on the heap. Here's a way to show it:

+
#![feature(integer_atomics)]
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicU64, Ordering};

static ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);

struct CountingAllocator;

unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout);
}
}

#[global_allocator]
static A: CountingAllocator = CountingAllocator;

fn main() {
let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst);
println!("There were {} allocations before calling main!", x);
}
+

-- +Rust Playground

+

As of the time of writing, there are five allocations that happen before main is ever called.

+

But when we want to understand more practically where heap allocation happens, we'll follow this +guide:

+
    +
  • Smart pointers hold their contents in the heap
  • +
  • Collections are smart pointers for many objects at a time, and reallocate when they need to grow
  • +
+

Finally, there are two "addendum" issues that are important to address when discussing Rust and the +heap:

+
    +
  • Non-heap alternatives to many standard library types are available.
  • +
  • Special allocators to track memory behavior should be used to benchmark code.
  • +
+

Smart pointers

+

The first thing to note are the "smart pointer" types. When you have data that must outlive the +scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these +types.

+

The term smart pointer comes from C++, and while it's +closely linked to a general design pattern of +"Resource Acquisition Is Initialization", we'll +use it here specifically to describe objects that are responsible for managing ownership of data +allocated on the heap. The smart pointers available in the alloc crate should look mostly +familiar:

+ +

The standard library also defines some smart pointers to manage +heap objects, though more than can be covered here. Some examples are:

+ +

Finally, there is one "gotcha": cell types +(like RefCell) look and behave +similarly, but don't involve heap allocation. The +core::cell docs have more information.

+

When a smart pointer is created, the data it is given is placed in heap memory and the location of +that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to +deallocate that memory (when a Box has +gone out of scope or a reference count +goes to zero), the heap space is reclaimed. We can +prove these types use heap memory by looking at code:

+
use std::rc::Rc;
use std::sync::Arc;
use std::borrow::Cow;

pub fn my_box() {
// Drop at assembly line 1640
Box::new(0);
}

pub fn my_rc() {
// Drop at assembly line 1650
Rc::new(0);
}

pub fn my_arc() {
// Drop at assembly line 1660
Arc::new(0);
}

pub fn my_cow() {
// Drop at assembly line 1672
Cow::from("drop");
}
+

-- Compiler Explorer

+

Collections

+

Collection types use heap memory because their contents have dynamic size; they will request more +memory when needed, and can +release memory when it's +no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In +a way, collections are smart pointers for many objects at a time. Common types that fall under +this umbrella are Vec, +HashMap, and +String (not +str).

+

While collections store the objects they own in heap memory, creating new collections will not +allocate on the heap. This is a bit weird; if we call Vec::new(), the assembly shows a +corresponding call to real_drop_in_place:

+
pub fn my_vec() {
// Drop in place at line 481
Vec::<u8>::new();
}
+

-- Compiler Explorer

+

But because the vector has no elements to manage, no calls to the allocator will ever be dispatched:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// Interesting bit happens here
let x: Vec<u8> = Vec::new();
drop(x);

// Turn panicking back off, some deallocations occur
// after main as well.
DO_PANIC.store(false, Ordering::SeqCst);
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- +Rust Playground

+

Other standard library types follow the same behavior; make sure to check out +HashMap::new(), +and String::new().

+

Heap Alternatives

+

While it is a bit strange to speak of the stack after spending time with the heap, it's worth +pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by +other crates. If you have need of the functionality, but want to avoid allocating, there are +typically alternatives available.

+

When it comes to some standard library smart pointers +(RwLock and +Mutex), stack-based alternatives are +provided in crates like parking_lot and +spin. You can check out +lock_api::RwLock, +lock_api::Mutex, and +spin::Once if you're in need +of synchronization primitives.

+

thread_id may be necessary if you're implementing an allocator +because thread::current().id() uses a +thread_local! structure +that needs heap allocation.

+

Tracing Allocators

+

When writing performance-sensitive code, there's no alternative to measuring your code. If you +didn't write a benchmark, +you don't care about it's performance +You should never rely on your instincts when +a microsecond is an eternity.

+

Similarly, there's great work going on in Rust with allocators that keep track of what they're doing +(like alloc_counter). When it comes to tracking heap +behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard +against future issues.

\ No newline at end of file diff --git a/2019/02/stacking-up/index.html b/2019/02/stacking-up/index.html new file mode 100644 index 0000000..78e113a --- /dev/null +++ b/2019/02/stacking-up/index.html @@ -0,0 +1,210 @@ +Allocations in Rust: Fixed memory | The Old Speice Guy
Skip to main content

Allocations in Rust: Fixed memory

· 16 min read
Bradlee Speice

const and static are perfectly fine, but it's relatively rare that we know at compile-time about +either values or references that will be the same for the duration of our program. Put another way, +it's not often the case that either you or your compiler knows how much memory your entire program +will ever need.

+

However, there are still some optimizations the compiler can do if it knows how much memory +individual functions will need. Specifically, the compiler can make use of "stack" memory (as +opposed to "heap" memory) which can be managed far faster in both the short- and long-term.

+

When requesting memory, the push instruction +can typically complete in 1 or 2 cycles (<1ns +on modern CPUs). Contrast that to heap memory which requires an allocator (specialized +software to track what memory is in use) to reserve space. When you're finished with stack memory, +the pop instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory +fragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have +been used to design allocators:

+ +

But no matter how fast your allocator is, the principle remains: the fastest allocator is the one +you never use. As such, we're not going to discuss how exactly the +push and pop instructions work, but +we'll focus instead on the conditions that enable the Rust compiler to use faster stack-based +allocation for variables.

+

So, how do we know when Rust will or will not use stack allocation for objects we create? +Looking at other languages, it's often easy to delineate between stack and heap. Managed memory +languages (Python, Java, +C#) place +everything on the heap. JIT compilers (PyPy, +HotSpot) may optimize +some heap allocations away, but you should never assume it will happen. C makes things clear with +calls to special functions (like malloc(3)) needed to access +heap memory. Old C++ has the new keyword, though +modern C++/C++11 is more complicated with RAII.

+

For Rust, we can summarize as follows: stack allocation will be used for everything that doesn't +involve "smart pointers" and collections. We'll skip over a precise definition of the term "smart +pointer" for now, and instead discuss what we should watch for to understand when stack and heap +memory regions are used:

+
    +
  1. +

    Stack manipulation instructions (push, pop, and add/sub of the rsp register) indicate +allocation of stack memory:

    +
    pub fn stack_alloc(x: u32) -> u32 {
    // Space for `y` is allocated by subtracting from `rsp`,
    // and then populated
    let y = [1u8, 2, 3, 4];
    // Space for `y` is deallocated by adding back to `rsp`
    x
    }
    +

    -- Compiler Explorer

    +
  2. +
  3. +

    Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch +for call core::ptr::real_drop_in_place, and infer that a heap allocation happened in the recent +past:

    +
    pub fn heap_alloc(x: usize) -> usize {
    // Space for elements in a vector has to be allocated
    // on the heap, and is then de-allocated once the
    // vector goes out of scope
    let y: Vec<u8> = Vec::with_capacity(x);
    x
    }
    +

    -- Compiler Explorer (real_drop_in_place happens on line 1317) +Note: While the +Drop trait is +called for stack-allocated objects, +the Rust standard library only defines Drop implementations for types that involve heap +allocation.

    +
  4. +
  5. +

    If you don't want to inspect the assembly, use a custom allocator that's able to track and alert +when heap allocations occur. Crates like +alloc_counter are designed for exactly this purpose.

    +
  6. +
+

With all that in mind, let's talk about situations in which we're guaranteed to use stack memory:

+
    +
  • Structs are created on the stack.
  • +
  • Function arguments are passed on the stack, meaning the +#[inline] attribute will +not change the memory region used.
  • +
  • Enums and unions are stack-allocated.
  • +
  • Arrays are always stack-allocated.
  • +
  • Closures capture their arguments on the stack.
  • +
  • Generics will use stack allocation, even with dynamic dispatch.
  • +
  • Copy types are guaranteed to be +stack-allocated, and copying them will be done in stack memory.
  • +
  • Iterators in the standard library are +stack-allocated even when iterating over heap-based collections.
  • +
+

Structs

+

The simplest case comes first. When creating vanilla struct objects, we use stack memory to hold +their contents:

+
struct Point {
x: u64,
y: u64,
}

struct Line {
a: Point,
b: Point,
}

pub fn make_line() {
// `origin` is stored in the first 16 bytes of memory
// starting at location `rsp`
let origin = Point { x: 0, y: 0 };
// `point` makes up the next 16 bytes of memory
let point = Point { x: 1, y: 2 };

// When creating `ray`, we just move the content out of
// `origin` and `point` into the next 32 bytes of memory
let ray = Line { a: origin, b: point };
}
+

-- Compiler Explorer

+

Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the +sub rsp, 64 instruction indicates we're still working with the stack.

+

Function arguments

+

Have you ever wondered how functions communicate with each other? Like, once the variables are given +to you, everything's fine. But how do you "give" those variables to another function? How do you get +the results back afterward? The answer: the compiler arranges memory and assembly instructions using +a pre-determined calling convention. This +convention governs the rules around where arguments needed by a function will be located (either in +memory offsets relative to the stack pointer rsp, or in other registers), and where the results +can be found once the function has finished. And when multiple languages agree on what the calling +conventions are, you can do things like having Go call Rust code!

+

Put simply: it's the compiler's job to figure out how to call other functions, and you can assume +that the compiler is good at its job.

+

We can see this in action using a simple example:

+
struct Point {
x: i64,
y: i64,
}

// We use integer division operations to keep
// the assembly clean, understanding the result
// isn't accurate.
fn distance(a: &Point, b: &Point) -> i64 {
// Immediately subtract from `rsp` the bytes needed
// to hold all the intermediate results - this is
// the stack allocation step

// The compiler used the `rdi` and `rsi` registers
// to pass our arguments, so read them in
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

// Do the actual math work
let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared

// Our final result will be stored in the `rax` register
// so that our caller knows where to retrieve it.
// Finally, add back to `rsp` the stack memory that is
// now ready to be used by other functions.
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

As a consequence of function arguments never using heap memory, we can also infer that functions +using the #[inline] attributes also do not heap allocate. But better than inferring, we can look +at the assembly to prove it:

+
struct Point {
x: i64,
y: i64,
}

// Note that there is no `distance` function in the assembly output,
// and the total line count goes from 229 with inlining off
// to 306 with inline on. Even still, no heap allocations occur.
#[inline(always)]
fn distance(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (a.x - b.x) * (a.x - b.x);
let y_pow = (a.y - b.y) * (a.y - b.y);
let squared = x_pow + y_pow;
squared / squared
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

Finally, passing by value (arguments with type +Copy) and passing by reference (either +moving ownership or passing a pointer) may have slightly different layouts in assembly, but will +still use either stack memory or CPU registers:

+
pub struct Point {
x: i64,
y: i64,
}

// Moving values
pub fn distance_moved(a: Point, b: Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}

// Borrowing values has two extra `mov` instructions on lines 21 and 22
pub fn distance_borrowed(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}
+

-- Compiler Explorer

+

Enums

+

If you've ever worried that wrapping your types in +Option or +Result would finally make them +large enough that Rust decides to use heap allocation instead, fear no longer: enum and union +types don't use heap allocation:

+
enum MyEnum {
Small(u8),
Large(u64)
}

struct MyStruct {
x: MyEnum,
y: MyEnum,
}

pub fn enum_compare() {
let x = MyEnum::Small(0);
let y = MyEnum::Large(0);

let z = MyStruct { x, y };

let opt = Option::Some(z);
}
+

-- Compiler Explorer

+

Because the size of an enum is the size of its largest element plus a flag, the compiler can +predict how much memory is used no matter which variant of an enum is currently stored in a +variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great +way to show this in assembly, so I'll instead point you to the +core::mem::size_of +documentation.

+

Arrays

+

The array type is guaranteed to be stack allocated, which is why the array size must be declared. +Interestingly enough, this can be used to cause safe Rust programs to crash:

+
// 256 bytes
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

// 8 kilobytes
#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

// 256 kilobytes
#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

// 8 megabytes - exceeds space typically provided for the stack,
// though the kernel can be instructed to allocate more.
// On Linux, you can check stack size using `ulimit -s`
#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

fn main() {
// Because we already have things in stack memory
// (like the current function call stack), allocating another
// eight megabytes of stack memory crashes the program
let _x = EightM::default();
}
+

-- +Rust Playground

+

There aren't any security implications of this (no memory corruption occurs), but it's good to note +that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to +overflow the stack.

+

Closures

+

Rules for how anonymous functions capture their arguments are typically language-specific. In Java, +Lambda Expressions are +actually objects created on the heap that capture local primitives by copying, and capture local +non-primitives as (final) references. +Python and +JavaScript +both bind everything by reference normally, but Python can also +capture values and JavaScript has +Arrow functions.

+

In Rust, arguments to closures are the same as arguments to other functions; closures are simply +functions that don't have a declared name. Some weird ordering of the stack may be required to +handle them, but it's the compiler's responsiblity to figure that out.

+

Each example below has the same effect, but a different assembly implementation. In the simplest +case, we immediately run a closure returned by another function. Because we don't store a reference +to the closure, the stack memory needed to store the captured values is contiguous:

+
fn my_func() -> impl FnOnce() {
let x = 24;
// Note that this closure in assembly looks exactly like
// any other function; you even use the `call` instruction
// to start running it.
move || { x; }
}

pub fn immediate() {
my_func()();
my_func()();
}
+

-- Compiler Explorer, 25 total assembly instructions

+

If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory +of the original function. Getting the details right is a bit harder, so the instruction count goes +up even though this code is functionally equivalent to our original example:

+
pub fn simple_reference() {
let x = my_func();
let y = my_func();
y();
x();
}
+

-- Compiler Explorer, 55 total assembly instructions

+

Even things like variable order can make a difference in instruction count:

+
pub fn complex() {
let x = my_func();
let y = my_func();
x();
y();
}
+

-- Compiler Explorer, 70 total assembly instructions

+

In every circumstance though, the compiler ensured that no heap allocations were necessary.

+

Generics

+

Traits in Rust come in two broad forms: static dispatch (monomorphization, impl Trait) and dynamic +dispatch (trait objects, dyn Trait). While dynamic dispatch is often associated with trait +objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:

+
trait GetInt {
fn get_int(&self) -> u64;
}

// vtable stored at section L__unnamed_1
struct WhyNotU8 {
x: u8
}
impl GetInt for WhyNotU8 {
fn get_int(&self) -> u64 {
self.x as u64
}
}

// vtable stored at section L__unnamed_2
struct ActualU64 {
x: u64
}
impl GetInt for ActualU64 {
fn get_int(&self) -> u64 {
self.x
}
}

// `&dyn` declares that we want to use dynamic dispatch
// rather than monomorphization, so there is only one
// `retrieve_int` function that shows up in the final assembly.
// If we used generics, there would be one implementation of
// `retrieve_int` for each type that implements `GetInt`.
pub fn retrieve_int(u: &dyn GetInt) {
// In the assembly, we just call an address given to us
// in the `rsi` register and hope that it was set up
// correctly when this function was invoked.
let x = u.get_int();
}

pub fn do_call() {
// Note that even though the vtable for `WhyNotU8` and
// `ActualU64` includes a pointer to
// `core::ptr::real_drop_in_place`, it is never invoked.
let a = WhyNotU8 { x: 0 };
let b = ActualU64 { x: 0 };

retrieve_int(&a);
retrieve_int(&b);
}
+

-- Compiler Explorer

+

It's hard to imagine practical situations where dynamic dispatch would be used for objects that +aren't heap allocated, but it technically can be done.

+

Copy types

+

Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs +go into detail far better than can +be addressed here, so I'll leave them to do the job. From a memory perspective though, their +guideline is reasonable: +if your type can implemement Copy, it should. +While there are potential speed tradeoffs to benchmark when discussing Copy (move semantics for +stack objects vs. copying stack pointers vs. copying stack structs), it's impossible for Copy +to introduce a heap allocation.

+

But why is this the case? Fundamentally, it's because the language controls what Copy means - +"the behavior of Copy is not overloadable" +because it's a marker trait. From there we'll note that a type +can implement Copy +if (and only if) its components implement Copy, and that +no heap-allocated types implement Copy. +Thus, assignments involving heap types are always move semantics, and new heap allocations won't +occur because of implicit operator behavior.

+
#[derive(Clone)]
struct Cloneable {
x: Box<u64>
}

// error[E0204]: the trait `Copy` may not be implemented for this type
#[derive(Copy, Clone)]
struct NotCopyable {
x: Box<u64>
}
+

-- Compiler Explorer

+

Iterators

+

In managed memory languages (like +Java), there's a subtle +difference between these two code samples:

+
public static int sum_for(List<Long> vals) {
long sum = 0;
// Regular for loop
for (int i = 0; i < vals.length; i++) {
sum += vals[i];
}
return sum;
}

public static int sum_foreach(List<Long> vals) {
long sum = 0;
// "Foreach" loop - uses iteration
for (Long l : vals) {
sum += l;
}
return sum;
}
+

In the sum_for function, nothing terribly interesting happens. In sum_foreach, an object of type +Iterator +is allocated on the heap, and will eventually be garbage-collected. This isn't a great design; +iterators are often transient objects that you need during a function and can discard once the +function ends. Sounds exactly like the issue stack-allocated objects address, no?

+

In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in +heap memory, but the iterator itself +(Iter) doesn't need to use the heap. In +each of the examples below we iterate over a collection, but never use heap allocation:

+
use std::collections::HashMap;
// There's a lot of assembly generated, but if you search in the text,
// there are no references to `real_drop_in_place` anywhere.

pub fn sum_vec(x: &Vec<u32>) {
let mut s = 0;
// Basic iteration over vectors doesn't need allocation
for y in x {
s += y;
}
}

pub fn sum_enumerate(x: &Vec<u32>) {
let mut s = 0;
// More complex iterators are just fine too
for (_i, y) in x.iter().enumerate() {
s += y;
}
}

pub fn sum_hm(x: &HashMap<u32, u32>) {
let mut s = 0;
// And it's not just Vec, all types will allocate the iterator
// on stack memory
for y in x.values() {
s += y;
}
}
+

-- Compiler Explorer

\ No newline at end of file diff --git a/2019/02/summary/index.html b/2019/02/summary/index.html new file mode 100644 index 0000000..e5f2bac --- /dev/null +++ b/2019/02/summary/index.html @@ -0,0 +1,26 @@ +Allocations in Rust: Summary | The Old Speice Guy
Skip to main content

Allocations in Rust: Summary

· 2 min read
Bradlee Speice

While there's a lot of interesting detail captured in this series, it's often helpful to have a +document that answers some "yes/no" questions. You may not care about what an Iterator looks like +in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust +will prioritize the fastest behavior it can, here are the rules for each memory type:

+

Global Allocation:

+
    +
  • const is a fixed value; the compiler is allowed to copy it wherever useful.
  • +
  • static is a fixed reference; the compiler will guarantee it is unique.
  • +
+

Stack Allocation:

+
    +
  • Everything not using a smart pointer will be allocated on the stack.
  • +
  • Structs, enums, iterators, arrays, and closures are all stack allocated.
  • +
  • Cell types (RefCell) behave like smart pointers, but are stack-allocated.
  • +
  • Inlining (#[inline]) will not affect allocation behavior for better or worse.
  • +
  • Types that are marked Copy are guaranteed to have their contents stack-allocated.
  • +
+

Heap Allocation:

+
    +
  • Smart pointers (Box, Rc, Mutex, etc.) allocate their contents in heap memory.
  • +
  • Collections (HashMap, Vec, String, etc.) allocate their contents in heap memory.
  • +
  • Some smart pointers in the standard library have counterparts in other crates that don't need heap +memory. If possible, use those.
  • +
+

Container Sizes in Rust

+

-- Raph Levien

\ No newline at end of file diff --git a/2019/02/the-whole-world/index.html b/2019/02/the-whole-world/index.html new file mode 100644 index 0000000..1ae6ba1 --- /dev/null +++ b/2019/02/the-whole-world/index.html @@ -0,0 +1,133 @@ +Allocations in Rust: Global memory | The Old Speice Guy
Skip to main content

Allocations in Rust: Global memory

· 8 min read
Bradlee Speice

The first memory type we'll look at is pretty special: when Rust can prove that a value is fixed +for the life of a program (const), and when a reference is unique for the life of a program +(static as a declaration, not +'static as a +lifetime), we can make use of global memory. This special section of data is embedded directly in +the program binary so that variables are ready to go once the program loads; no additional +computation is necessary.

+

Understanding the value/reference distinction is important for reasons we'll go into below, and +while the +full specification for +these two keywords is available, we'll take a hands-on approach to the topic.

+

const values

+

When a value is guaranteed to be unchanging in your program (where "value" may be scalars, +structs, etc.), you can declare it const. This tells the compiler that it's safe to treat the +value as never changing, and enables some interesting optimizations; not only is there no +initialization cost to creating the value (it is loaded at the same time as the executable parts of +your program), but the compiler can also copy the value around if it speeds up the code.

+

The points we need to address when talking about const are:

+
    +
  • Const values are stored in read-only memory - it's impossible to modify.
  • +
  • Values resulting from calling a const fn are materialized at compile-time.
  • +
  • The compiler may (or may not) copy const values wherever it chooses.
  • +
+

Read-Only

+

The first point is a bit strange - "read-only memory." +The Rust book +mentions in a couple places that using mut with constants is illegal, but it's also important to +demonstrate just how immutable they are. Typically in Rust you can use +interior mutability to modify +things that aren't declared mut. +RefCell provides an example of this +pattern in action:

+
use std::cell::RefCell;

fn my_mutator(cell: &RefCell<u8>) {
// Even though we're given an immutable reference,
// the `replace` method allows us to modify the inner value.
cell.replace(14);
}

fn main() {
let cell = RefCell::new(25);
// Prints out 25
println!("Cell: {:?}", cell);
my_mutator(&cell);
// Prints out 14
println!("Cell: {:?}", cell);
}
+

-- +Rust Playground

+

When const is involved though, interior mutability is impossible:

+
use std::cell::RefCell;

const CELL: RefCell<u8> = RefCell::new(25);

fn my_mutator(cell: &RefCell<u8>) {
cell.replace(14);
}

fn main() {
// First line prints 25 as expected
println!("Cell: {:?}", &CELL);
my_mutator(&CELL);
// Second line *still* prints 25
println!("Cell: {:?}", &CELL);
}
+

-- +Rust Playground

+

And a second example using Once:

+
use std::sync::Once;

const SURPRISE: Once = Once::new();

fn main() {
// This is how `Once` is supposed to be used
SURPRISE.call_once(|| println!("Initializing..."));
// Because `Once` is a `const` value, we never record it
// having been initialized the first time, and this closure
// will also execute.
SURPRISE.call_once(|| println!("Initializing again???"));
}
+

-- +Rust Playground

+

When the +const specification +refers to "rvalues", this +behavior is what they refer to. Clippy will treat this +as an error, but it's still something to be aware of.

+

Initialization

+

The next thing to mention is that const values are loaded into memory as part of your program +binary. Because of this, any const values declared in your program will be "realized" at +compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may +be able to prefetch the value), but that's it.

+
use std::cell::RefCell;

const CELL: RefCell<u32> = RefCell::new(24);

pub fn multiply(value: u32) -> u32 {
// CELL is stored at `.L__unnamed_1`
value * (*CELL.get_mut())
}
+

-- Compiler Explorer

+

The compiler creates one RefCell, uses it everywhere, and never needs to call the RefCell::new +function.

+

Copying

+

If it's helpful though, the compiler can choose to copy const values.

+
const FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// See assembly line 4 for the `mov edi, 1000` instruction
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// See assembly lines 22 and 29 for `mov edi, 1000` instructions
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

In this example, the FACTOR value is turned into the mov edi, 1000 instruction in both the +multiply and multiply_twice functions; the "1000" value is never "stored" anywhere, as it's +small enough to inline into the assembly instructions.

+

Finally, getting the address of a const value is possible, but not guaranteed to be unique +(because the compiler can choose to copy values). I was unable to get non-unique pointers in my +testing (even using different crates), but the specifications are clear enough: don't rely on +pointers to const values being consistent. To be frank, caring about locations for const values +is almost certainly a code smell.

+

static values

+

Static variables are related to const variables, but take a slightly different approach. When we +declare that a reference is unique for the life of a program, you have a static variable +(unrelated to the 'static lifetime). Because of the reference/value distinction with +const/static, static variables behave much more like typical "global" variables.

+

But to understand static, here's what we'll look at:

+
    +
  • static variables are globally unique locations in memory.
  • +
  • Like const, static variables are loaded at the same time as your program being read into +memory.
  • +
  • All static variables must implement the +Sync marker trait.
  • +
  • Interior mutability is safe and acceptable when using static variables.
  • +
+

Memory Uniqueness

+

The single biggest difference between const and static is the guarantees provided about +uniqueness. Where const variables may or may not be copied in code, static variables are +guarantee to be unique. If we take a previous const example and change it to static, the +difference should be clear:

+
static FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

Where previously there were plenty of references to multiplying by 1000, the new +assembly refers to FACTOR as a named memory location instead. No initialization work needs to be +done, but the compiler can no longer prove the value never changes during execution.

+

Initialization

+

Next, let's talk about initialization. The simplest case is initializing static variables with +either scalar or struct notation:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

static MY_STRUCT: MyStruct = MyStruct {
// You can even reference other statics
// declared later
x: MY_VAL
};

static MY_VAL: u32 = 24;

fn main() {
println!("Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

Things can get a bit weirder when using const fn though. In most cases, it just works:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

impl MyStruct {
const fn new() -> MyStruct {
MyStruct { x: 24 }
}
}

static MY_STRUCT: MyStruct = MyStruct::new();

fn main() {
println!("const fn Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

However, there's a caveat: you're currently not allowed to use const fn to initialize static +variables of types that aren't marked Sync. For example, +RefCell::new() is a +const fn, but because +RefCell isn't Sync, you'll +get an error at compile time:

+
use std::cell::RefCell;

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_LOCK: RefCell<u8> = RefCell::new(0);
+

-- +Rust Playground

+

It's likely that this will +change in the future though.

+

The Sync marker

+

Which leads well to the next point: static variable types must implement the +Sync marker. Because they're globally +unique, it must be safe for you to access static variables from any thread at any time. Most +struct definitions automatically implement the Sync trait because they contain only elements +which themselves implement Sync (read more in the +Nomicon). This is why earlier examples could +get away with initializing statics, even though we never included an impl Sync for MyStruct in the +code. To demonstrate this property, Rust refuses to compile our earlier example if we add a +non-Sync element to the struct definition:

+
use std::cell::RefCell;

struct MyStruct {
x: u32,
y: RefCell<u8>,
}

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_STRUCT: MyStruct = MyStruct {
x: 8,
y: RefCell::new(8)
};
+

-- +Rust Playground

+

Interior mutability

+

Finally, while static mut variables are allowed, mutating them is an unsafe operation. If we +want to stay in safe Rust, we can use interior mutability to accomplish similar goals:

+
use std::sync::Once;

// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once
static INIT: Once = Once::new();

fn main() {
// Note that while `INIT` is declared immutable, we're still allowed
// to mutate its interior
INIT.call_once(|| println!("Initializing..."));
// This code won't panic, as the interior of INIT was modified
// as part of the previous `call_once`
INIT.call_once(|| panic!("INIT was called twice!"));
}
+

-- +Rust Playground

\ No newline at end of file diff --git a/2019/02/understanding-allocations-in-rust/index.html b/2019/02/understanding-allocations-in-rust/index.html new file mode 100644 index 0000000..6aee6af --- /dev/null +++ b/2019/02/understanding-allocations-in-rust/index.html @@ -0,0 +1,83 @@ +Allocations in Rust: Foreword | The Old Speice Guy
Skip to main content

Allocations in Rust: Foreword

· 4 min read
Bradlee Speice

There's an alchemy of distilling complex technical topics into articles and videos that change the +way programmers see the tools they interact with on a regular basis. I knew what a linker was, but +there's a staggering amount of complexity in between +the OS and main(). Rust programmers use the +Box type all the time, but there's a +rich history of the Rust language itself wrapped up in +how special it is.

+

In a similar vein, this series attempts to look at code and understand how memory is used; the +complex choreography of operating system, compiler, and program that frees you to focus on +functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the +cognitive burden associated with memory management, but we're going to step into its world for a +while.

+

Let's learn a bit about memory in Rust.

+
+

Rust's three defining features of +Performance, Reliability, and Productivity are all driven to a great +degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, +Python), Rust +doesn't really +garbage collect; instead, it uses an +ownership system to reason about +how long objects will last in your program. In some cases, if the life of an object is fairly +transient, Rust can make use of a very fast region called the "stack." When that's not possible, +Rust uses +dynamic (heap) memory +and the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it +is important to have available.

+

That said, there are specific situations in Rust where you'd never need to worry about the +stack/heap distinction! If you:

+
    +
  1. Never use unsafe
  2. +
  3. Never use #![feature(alloc)] or the alloc crate
  4. +
+

...then it's not possible for you to use dynamic memory!

+

For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited +memory, and the program binary size itself may significantly affect what's available! There's no +operating system able to manage this +"virtual memory" thing, but that's not an issue +because there's only one running application. The +embedonomicon is ever in mind, and +interacting with the "real world" through extra peripherals is accomplished by reading and writing +to specific memory addresses.

+

Most Rust programs find these requirements overly burdensome though. C++ developers would struggle +without access to std::vector (except those +hardcore no-STL people), and Rust developers would struggle without +std::vec. But with the constraints above, +std::vec is actually a part of the +alloc crate, and thus off-limits. Box, +Rc, etc., are also unusable for the same reason.

+

Whether writing code for embedded devices or not, the important thing in both situations is how much +you know before your application starts about what its memory usage will look like. In embedded +devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large +google.com's home page is until you start trying to download it. The +compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code +runs faster when the compiler can guarantee exactly how much memory your program needs while it's +running. This series is all about understanding how the compiler reasons about your program, with an +emphasis on the implications for performance.

+

Now let's address some conditions and caveats before going much further:

+
    +
  • We'll focus on "safe" Rust only; unsafe lets you use platform-specific allocation API's +(malloc) that we'll +ignore.
  • +
  • We'll assume a "debug" build of Rust code (what you get with cargo run and cargo test) and +address (pun intended) release mode at the end (cargo run --release and cargo test --release).
  • +
  • All content will be run using Rust 1.32, as that's the highest currently supported in the +Compiler Exporer. As such, we'll avoid upcoming innovations like +compile-time evaluation of static +that are available in nightly.
  • +
  • Because of the nature of the content, being able to read assembly is helpful. We'll keep it +simple, but I found a +refresher on the push and pop +instructions was helpful while writing +this.
  • +
  • I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are +available, but if there's something said in error it will be corrected expeditiously. Please let +me know at bradlee@speice.io
  • +
+

Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth +repeating:

+
+

Rust does not currently have a rigorously and formally defined memory model.

+

-- the docs

+
\ No newline at end of file diff --git a/2019/05/making-bread/index.html b/2019/05/making-bread/index.html new file mode 100644 index 0000000..1e47171 --- /dev/null +++ b/2019/05/making-bread/index.html @@ -0,0 +1,29 @@ +Making bread | The Old Speice Guy
Skip to main content

Making bread

· 2 min read
Bradlee Speice

Having recently started my "gardening leave" between positions, I have some more personal time +available. I'm planning to stay productive, contributing to some open-source projects, but it also +occurred to me that despite talking about bread pics, this +blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites +and Bytes"?

+

Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on +some lighter material. I recently learned two critically important lessons: first, the temperature +of the dough when you put the yeast in makes a huge difference.

+

Previously, when I wasn't paying attention to dough temperature:

+

Whole weat dough

+

Compared with what happens when I put the dough in the microwave for a defrost cycle because the +water I used wasn't warm enough:

+

White dough

+

I mean, just look at the bubbles!

+

White dough with bubbles

+

After shaping the dough, I've got two loaves ready:

+

Shaped loaves

+

Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from +drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the +bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot +to add the water and learned my second lesson: never add room-temperature water to a glass dish +that's currently at 500 degrees.

+

Shattered glass dish

+

Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected +to be doing during my garden leave.

+

In the end, the bread crust wasn't great, but the bread itself turned out pretty alright:

+

Baked bread

+

I've been writing a lot more during this break, so I'm looking forward to sharing that in the +future. In the mean-time, I'm planning on making a sandwich.

\ No newline at end of file diff --git a/2019/06/high-performance-systems/index.html b/2019/06/high-performance-systems/index.html new file mode 100644 index 0000000..f918fc1 --- /dev/null +++ b/2019/06/high-performance-systems/index.html @@ -0,0 +1,267 @@ +On building high performance systems | The Old Speice Guy
Skip to main content

On building high performance systems

· 13 min read
Bradlee Speice

Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is +made up of people who have access to secret techniques mortal developers could only dream of. There +had to be some secret art that could only be learned if one had an appropriately tragic backstory.

+

Kung Fu fight

+
+

How I assumed HFT people learn their secret techniques

+
+

How else do you explain people working on systems that complete the round trip of market data in to +orders out (a.k.a. tick-to-trade) consistently within +750-800 nanoseconds? In roughly the time it takes a +computer to access +main memory 8 times, +trading systems are capable of reading the market data packets, deciding what orders to send, doing +risk checks, creating new packets for exchange-specific protocols, and putting those packets on the +wire.

+

Having now worked in the trading industry, I can confirm the developers aren't super-human; I've +made some simple mistakes at the very least. Instead, what shows up in public discussions is that +philosophy, not technique, separates high-performance systems from everything else. +Performance-critical systems don't rely on "this one cool C++ optimization trick" to make code fast +(though micro-optimizations have their place); there's a lot more to worry about than just the code +written for the project.

+

The framework I'd propose is this: If you want to build high-performance systems, focus first on +reducing performance variance (reducing the gap between the fastest and slowest runs of the same +code), and only look at average latency once variance is at an acceptable level.

+

Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20 +seconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes +a full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a +week is the same in each situation, but you're painfully aware of that minute when it happens. When +it comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds +doesn't mean much if there's a 100ms difference between your fastest and slowest runs. When +performance matters, you need to respond quickly every time, not just in aggregate. +High-performance systems should first optimize for time variance. Once you're consistent at the time +scale you care about, then focus on improving average time.

+

This focus on variance shows up all the time in industry too (emphasis added in all quotes below):

+
    +
  • +

    In marketing materials for +NASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability +is highlighted in addition to instantaneous metrics:

    +
    +

    Able to consistently sustain an order rate of over 100,000 orders per second at sub-40 +microsecond average latency

    +
    +
  • +
  • +

    The Aeron message bus has this to say about performance:

    +
    +

    Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and +most predictable latency possible of any messaging system

    +
    +
  • +
  • +

    The company PolySync, which is working on autonomous vehicles, +mentions why they picked their +specific messaging format:

    +
    +

    In general, high performance is almost always desirable for serialization. But in the world of +autonomous vehicles, steady timing performance is even more important than peak throughput. +This is because safe operation is sensitive to timing outliers. Nobody wants the system that +decides when to slam on the brakes to occasionally take 100 times longer than usual to encode +its commands.

    +
    +
  • +
  • +

    Solarflare, which makes highly-specialized network hardware, points out +variance (jitter) as a big concern for +electronic trading:

    +
    +

    The high stakes world of electronic trading, investment banks, market makers, hedge funds and +exchanges demand the lowest possible latency and jitter while utilizing the highest +bandwidth and return on their investment.

    +
    +
  • +
+

And to further clarify: we're not discussing total run-time, but variance of total run-time. There +are situations where it's not reasonably possible to make things faster, and you'd much rather be +consistent. For example, trading firms use +wireless networks because +the speed of light through air is faster than through fiber-optic cables. There's still at absolute +minimum a ~33.76 millisecond delay required to send data between, +say, +Chicago and Tokyo. +If a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a +trade occurs, there's a physical limit to how long that will take. In this situation, the focus is +on keeping variance of additional processing to a minimum, since speed of light is the limiting +factor.

+

So how does one go about looking for and eliminating performance variance? To tell the truth, I +don't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep +understanding of the entire technology stack, and (B) actually measuring system performance (though +(C) watching a lot of CppCon videos for +inspiration never hurt). Even then, every project cares about performance to a different degree; you +may need to build an entire +replica production system to +accurately benchmark at nanosecond precision, or you may be content to simply +avoid garbage collection in +your Java code.

+

Even though everyone has different needs, there are still common things to look for when trying to +isolate and eliminate variance. In no particular order, these are my focus areas when thinking about +high-performance systems:

+

Update 2019-09-21: Added notes on isolcpus and systemd affinity.

+

Language-specific

+

Garbage Collection: How often does garbage collection happen? When is it triggered? What are the +impacts?

+
    +
  • In Python, individual objects are collected +if the reference count reaches 0, and each generation is collected if +num_alloc - num_dealloc > gc_threshold whenever an allocation happens. The GIL is acquired for +the duration of generational collection.
  • +
  • Java has +many +different +collection +algorithms +to choose from, each with different characteristics. The default algorithms (Parallel GC in Java +8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms +(ZGC and +Shenandoah) are designed to keep "stop the +world" to a minimum by doing collection work in parallel.
  • +
+

Allocation: Every language has a different way of interacting with "heap" memory, but the +principle is the same: running the allocator to allocate/deallocate memory takes time that can often +be put to better use. Understanding when your language interacts with the allocator is crucial, and +not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java +does (meaning potential GC pauses). Take time to understand heap behavior (I made a +a guide for Rust), and look into alternative +allocators (jemalloc, +tcmalloc) that might run faster than the +operating system default.

+

Data Layout: How your data is arranged in memory matters; +data-oriented design and +cache locality can have huge +impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have +guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't +make. Cachegrind and kernel +perf counters are both great for understanding +how performance relates to memory layout.

+

Just-In-Time Compilation: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are +great because they optimize your program for how it's actually being used, rather than how a +compiler expects it to be used. However, there's a variance problem if the program stops executing +while waiting for translation from VM bytecode to native code. As a remedy, many languages support +ahead-of-time compilation in addition to the JIT versions +(CoreRT in C# and GraalVM in Java). +On the other hand, LLVM supports +Profile Guided Optimization, +which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing +apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT +compiler kicked in.

+

Programming Tricks: These won't make or break performance, but can be useful in specific +circumstances. For example, C++ can use +templates instead of branches +in critical sections.

+

Kernel

+

Code you wrote is almost certainly not the only code running on your hardware. There are many ways +the operating system interacts with your program, from interrupts to system calls, that are +important to watch for. These are written from a Linux perspective, but Windows does typically have +equivalent functionality.

+

Scheduling: The kernel is normally free to schedule any process on any core, so it's important +to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, +limit the CPU cores that non-critical processes are allowed to run on by excluding cores from +scheduling +(isolcpus +kernel command-line option), or by setting the init process CPU affinity +(systemd example). Second, set critical processes +to run on the isolated cores by setting the +processor affinity using +taskset. Finally, use +NO_HZ or +chrt to disable scheduling interrupts. Turning off +hyper-threading is also likely beneficial.

+

System calls: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long +the I/O operation takes, these all trigger expensive +system calls (syscalls). To handle these, the CPU must +context switch to the kernel, let the kernel +operation complete, then context switch back to your program. We'd rather keep these +to a minimum (see +timestamp 18:20). Strace is your friend for understanding when +and where syscalls happen.

+

Signal Handling: Far less likely to be an issue, but signals do trigger a context switch if your +code has a handler registered. This will be highly dependent on the application, but you can +block signals +if it's an issue.

+

Interrupts: System interrupts are how devices connected to your computer notify the CPU that +something has happened. The CPU will then choose a processor core to pause and context switch to the +OS to handle the interrupt. Make sure that +SMP affinity is +set so that interrupts are handled on a CPU core not running the program you care about.

+

NUMA: While NUMA is good at making +multi-cell systems transparent, there are variance implications; if the kernel moves a process +across nodes, future memory accesses must wait for the controller on the original node. Use +numactl to handle memory-/cpu-cell pinning so this doesn't +happen.

+

Hardware

+

CPU Pipelining/Speculation: Speculative execution in modern processors gave us vulnerabilities +like Spectre, but it also gave us performance improvements like +branch prediction. And if the CPU mis-speculates +your code, there's variance associated with rewind and replay. While the compiler knows a lot about +how your CPU pipelines instructions, code can be +structured to help the branch +predictor.

+

Paging: For most systems, virtual memory is incredible. Applications live in their own worlds, +and the CPU/MMU figures out the details. +However, there's a variance penalty associated with memory paging and caching; if you access more +memory pages than the TLB can store, +you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an +issue, but using huge pages can +reduce TLB burdens. Alternately, running applications in a hypervisor like +Jailhouse allows one to skip virtual memory entirely, but +this is probably more work than the benefits are worth.

+

Network Interfaces: When more than one computer is involved, variance can go up dramatically. +Tuning kernel +network parameters may be +helpful, but modern systems more frequently opt to skip the kernel altogether with a technique +called kernel bypass. This typically requires +specialized hardware and drivers, but even industries like +telecom are +finding the benefits.

+

Networks

+

Routing: There's a reason financial firms are willing to pay +millions of euros +for rights to a small plot of land - having a straight-line connection from point A to point B means +the path their data takes is the shortest possible. In contrast, there are currently 6 computers in +between me and Google, but that may change at any moment if my ISP realizes a +more efficient route is available. Whether +it's using +research-quality equipment +for shortwave radio, or just making sure there's no data inadvertently going between data centers, +routing matters.

+

Protocol: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, +and congestion control all built in. But these attributes make the most sense when networking +infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the +setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may +make sense in these contexts as it avoids the chatter needed to track connection state, and +gap-fill +strategies +can handle the rest.

+

Switching: Many routers/switches handle packets using "store-and-forward" behavior: wait for the +whole packet, validate checksums, and then send to the next device. In variance terms, the time +needed to move data between two nodes is proportional to the size of that data; the switch must +"store" all data before it can calculate checksums and "forward" to the next node. With +"cut-through" +designs, switches will begin forwarding data as soon as they know where the destination is, +checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter +the size.

+

Final Thoughts

+

High-performance systems, regardless of industry, are not magical. They do require extreme precision +and attention to detail, but they're designed, built, and operated by regular people, using a lot of +tools that are publicly available. Interested in seeing how context switching affects performance of +your benchmarks? taskset should be installed in all modern Linux distributions, and can be used to +make sure the OS never migrates your process. Curious how often garbage collection triggers during a +crucial operation? Your language of choice will typically expose details of its operations +(Python, +Java). +Want to know how hard your program is stressing the TLB? Use perf record and look for +dtlb_load_misses.miss_causes_a_walk.

+

Two final guiding questions, then: first, before attempting to apply some of the technology above to +your own systems, can you first identify +where/when you care about "high-performance"? As an +example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable +effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are +they being designed in a way that's actually helpful? Tools like +Criterion (also in +Rust) and Google's +Benchmark output not only average run time, but variance as +well; your benchmarking environment is subject to the same concerns your production environment is.

+

Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. +Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate +it; once that's at an acceptable level, then optimize for speed.

\ No newline at end of file diff --git a/2019/09/binary-format-shootout/index.html b/2019/09/binary-format-shootout/index.html new file mode 100644 index 0000000..cca57ab --- /dev/null +++ b/2019/09/binary-format-shootout/index.html @@ -0,0 +1,151 @@ +Binary format shootout | The Old Speice Guy
Skip to main content

Binary format shootout

· 9 min read
Bradlee Speice

I've found that in many personal projects, +analysis paralysis is particularly deadly. +Making good decisions in the beginning avoids pain and suffering later; if extra research prevents +future problems, I'm happy to continue procrastinating researching indefinitely.

+

So let's say you're in need of a binary serialization format. Data will be going over the network, +not just in memory, so having a schema document and code generation is a must. Performance is +crucial, so formats that support zero-copy de/serialization are given priority. And the more +languages supported, the better; I use Rust, but can't predict what other languages this could +interact with.

+

Given these requirements, the candidates I could find were:

+
    +
  1. Cap'n Proto has been around the longest, and is the most established
  2. +
  3. Flatbuffers is the newest, and claims to have a simpler +encoding
  4. +
  5. Simple Binary Encoding has the simplest +encoding, but the Rust implementation is unmaintained
  6. +
+

Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably +fast, and polyglot support. But how do you actually pick one? It's impossible to know what issues +will follow that choice, so I tend to avoid commitment until the last possible moment.

+

Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a +small proof-of-concept system in each format and pit them against each other. All code can be found +in the repository for this post.

+

We'll discuss more in detail, but a quick preview of the results:

+
    +
  • Cap'n Proto: Theoretically performs incredibly well, the implementation had issues
  • +
  • Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises
  • +
  • SBE: Best median and worst-case performance, but the message structure has a limited feature set
  • +
+

Prologue: Binary Parsing with Nom

+

Our benchmark system will be a simple data processor; given depth-of-book market data from +IEX, serialize each message into the schema +format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. +This test isn't complex, but is representative of the project I need a binary format for.

+

But before we make it to that point, we have to actually read in the market data. To do so, I'm +using a library called nom. Version 5.0 was recently released and +brought some big changes, so this was an opportunity to build a non-trivial program and get +familiar.

+

If you don't already know about nom, it's a "parser generator". By combining different smaller +parsers, you can assemble a parser to handle complex structures without writing tedious code by +hand. For example, when parsing +PCAP files:

+
   0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
0 | Block Type = 0x00000006 |
+---------------------------------------------------------------+
4 | Block Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Interface ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 | Timestamp (High) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 | Timestamp (Low) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 | Captured Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 | Packet Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet Data |
| ... |
+

...you can build a parser in nom that looks like +this:

+
const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];
pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> {
let (
remaining,
(
block_type,
block_len,
interface_id,
timestamp_high,
timestamp_low,
captured_len,
packet_len,
),
) = tuple((
tag(ENHANCED_PACKET),
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
))(input)?;

let (remaining, packet_data) = take(captured_len)(remaining)?;
Ok((remaining, packet_data))
}
+

While this example isn't too interesting, more complex formats (like IEX market data) are where +nom really shines.

+

Ultimately, because the nom code in this shootout was the same for all formats, we're not too +interested in its performance. Still, it's worth mentioning that building the market data parser was +actually fun; I didn't have to write tons of boring code by hand.

+

Cap'n Proto

+

Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried +because of how long it has supported Rust (thanks to dwrensha for +maintaining the Rust port since +2014!). However, I had a ton +of performance concerns once I started using it.

+

To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the +heap to hold the message content, but because builders +can't be re-used, we have to allocate a +new buffer for every single message. I was able to work around this with a +special builder +that could re-use the buffer, but it required reading through Cap'n Proto's +benchmarks +to find an example, and used +std::mem::transmute to bypass Rust's borrow +checker.

+

The process of reading messages was better, but still had issues. Cap'n Proto has two message +encodings: a "packed" representation, and an +"unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into +before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't +able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n +Proto shines; its main selling point is that there's no decoding step. +However, accomplishing zero-copy deserialization required code in the private API +(since fixed), and we allocate a vector on +every read for the segment table.

+

In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too +many issues for me to feel comfortable using it long-term.

+

Flatbuffers

+

This is the new kid on the block. After a +first attempt didn't pan out, official support +was recently launched. Flatbuffers intends to +address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The +difference is that Flatbuffers claims to have a simpler wire format and +more flexibility.

+

On the whole, I enjoyed using Flatbuffers; the tooling is +nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, +there were still some issues.

+

First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats +like the following:

+
table Message {
symbol: string;
}
table MultiMessage {
messages:[Message];
}
+

We want to create a MultiMessage which contains a vector of Message, and each Message itself +contains a vector (the string type). I was able to work around this by +caching Message elements +in a SmallVec before building the final MultiMessage, but it was a painful process that I +believe contributed to poor serialization performance.

+

Second, streaming support in Flatbuffers seems to be something of an +afterthought. Where Cap'n Proto in Rust handles +reading messages from a stream as part of the API, Flatbuffers just sticks a u32 at the front of +each message to indicate the size. Not specifically a problem, but calculating message size without +that tag is nigh on impossible.

+

Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform +well.

+

Simple Binary Encoding

+

Support for SBE was added by the author of one of my favorite +Rust blog posts. +I've talked previously about how important +variance is in high-performance systems, so it was encouraging to read about a format that +directly addressed my +concerns. SBE has by far the simplest binary format, but it does make some tradeoffs.

+

Both Cap'n Proto and Flatbuffers use message offsets +to handle variable-length data, unions, and various +other features. In contrast, messages in SBE are essentially +just structs; +variable-length data is supported, but there's no union type.

+

As mentioned in the beginning, the Rust port of SBE works well, but is +essentially unmaintained. +However, if you don't need union types, and can accept that schemas are XML documents, it's still +worth using. SBE's implementation had the best streaming support of all formats I tested, and +doesn't trigger allocation during de/serialization.

+

Results

+

After building a test harness +for +each +format, it was +time to actually take them for a spin. I used +this script to run +the benchmarks, and the raw results are +here. All data reported +below is the average of 10 runs on a single day of IEX data. Results were validated to make sure +that each format parsed the data correctly.

+

Serialization

+

This test measures, on a +per-message basis, +how long it takes to serialize the IEX message into the desired format and write to a pre-allocated +buffer.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed413ns1751ns2943ns14.80s
Cap'n Proto Unpacked273ns1828ns2836ns10.65s
Flatbuffers355ns2185ns3497ns14.31s
SBE91ns1535ns2423ns3.91s
+

Deserialization

+

This test measures, on a +per-message basis, +how long it takes to read the previously-serialized message and perform some basic aggregation. The +aggregation code is the same for each format, so any performance differences are due solely to the +format implementation.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed539ns1216ns2599ns18.92s
Cap'n Proto Unpacked366ns737ns1583ns12.32s
Flatbuffers173ns421ns1007ns6.00s
SBE116ns286ns659ns4.05s
+

Conclusion

+

Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" +type isn't important to me, I can be confident that SBE best addresses my needs.

+

While SBE was the fastest in terms of both median and worst-case performance, its worst case +performance was proportionately far higher than any other format. It seems to be that +de/serialization time scales with message size, but I'll need to do some more research to understand +what exactly is going on.

\ No newline at end of file diff --git a/2019/12/release-the-gil/index.html b/2019/12/release-the-gil/index.html new file mode 100644 index 0000000..5a05540 --- /dev/null +++ b/2019/12/release-the-gil/index.html @@ -0,0 +1,151 @@ +Release the GIL | The Old Speice Guy
Skip to main content

Release the GIL

· 9 min read
Bradlee Speice

Complaining about the Global Interpreter Lock +(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision +made before multi-core CPU's were widely available, but the fact that it's still around indicates +that it generally works Good +Enough. Besides, there are simple and effective +workarounds; it's not hard to start a +new process and use message passing to +synchronize code running in parallel.

+

Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of +asynchronicity and M:N threading, Python seems lacking. The ideal scenario is to take advantage of +both Python's productivity and the modern CPU's parallel capabilities.

+

Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes +Python a nice language to start with. Bear in mind: these are just the tools, no claim is made about +whether it's a good idea to use them. Very often, unlocking the GIL is an +XY problem; you want application performance, and the +GIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at +the expense of project complexity; messing with the GIL is ultimately messing with Python's memory +model.

+
%load_ext Cython
from numba import jit

N = 1_000_000_000
+

Cython

+

Put simply, Cython is a programming language that looks a lot like Python, +gets transpiled to C/C++, and integrates +well with the CPython API. It's great for building Python +wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And +when it comes to managing the GIL, there are two special features:

+
    +
  • The nogil +function annotation +asserts that a Cython function is safe to use without the GIL, and compilation will fail if it +interacts with Python in an unsafe manner
  • +
  • The with nogil +context manager +explicitly unlocks the CPython GIL while active
  • +
+

Whenever Cython code runs inside a with nogil block on a separate thread, the Python interpreter +is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that +demonstrates this principle in action:

+
%%cython

# Annotating a function with `nogil` indicates only that it is safe
# to call in a `with nogil` block. It *does not* release the GIL.
cdef unsigned long fibonacci(unsigned long n) nogil:
if n <= 1:
return n

cdef unsigned long a = 0, b = 1, c = 0

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


def cython_nogil(unsigned long n):
# Explicitly release the GIL while running `fibonacci`
with nogil:
value = fibonacci(n)

return value


def cython_gil(unsigned long n):
# Because the GIL is not explicitly released, it implicitly
# remains acquired when running the `fibonacci` function
return fibonacci(n)
+

First, let's time how long it takes Cython to calculate the billionth Fibonacci number:

+
%%time
_ = cython_gil(N);
+
+

CPU times: user 365 ms, sys: 0 ns, total: 365 ms +Wall time: 372 ms

+
+
%%time
_ = cython_nogil(N);
+
+

CPU times: user 381 ms, sys: 0 ns, total: 381 ms +Wall time: 388 ms

+
+

Both versions (with and without GIL) take effectively the same amount of time to run. Even when +running this calculation in parallel on separate threads, it is expected that the run time will +double because only one thread can be active at a time:

+
%%time
from threading import Thread

# Create the two threads to run on
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
# Start the threads
t1.start(); t2.start()
# Wait for the threads to finish
t1.join(); t2.join()
+
+

CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms +Wall time: 645 ms

+
+

However, if the first thread releases the GIL, the second thread is free to acquire it and run in +parallel:

+
%%time

t1 = Thread(target=cython_nogil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 717 ms, sys: 372 µs, total: 718 ms +Wall time: 358 ms

+
+

Because user time represents the sum of processing time on all threads, it doesn't change much. +The "wall time" has been cut roughly in half +because each function is running simultaneously.

+

Keep in mind that the order in which threads are started makes a difference!

+
%%time

# Note that the GIL-locked version is started first
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 667 ms, sys: 0 ns, total: 667 ms +Wall time: 672 ms

+
+

Even though the second thread releases the GIL while running, it can't start until the first has +completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads.

+

Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the +interpreter, not just the thread attempting the unlock:

+
%%cython

cdef int cython_recurse(int n) nogil:
if n <= 0:
return 0

with nogil:
return cython_recurse(n - 1)

cython_recurse(2)
+
+

Fatal Python error: PyEval_SaveThread: NULL tstate

Thread 0x00007f499effd700 (most recent call first): +File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run +File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner +File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap

+
+

In practice, avoiding this issue is simple. First, nogil functions probably shouldn't contain +with nogil blocks. Second, Cython can +conditionally acquire/release +the GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for +external C code +contains more detail on how to safely manage the GIL.

+

To conclude: use Cython's nogil annotation to assert that functions are safe for calling when the +GIL is unlocked, and with nogil to actually unlock the GIL and run those functions.

+

Numba

+

Like Cython, Numba is a "compiled Python." Where Cython works by +compiling a Python-like language to C/C++, Numba compiles Python bytecode directly to machine code +at runtime. Behavior is controlled with a special @jit decorator; calling a decorated function +first compiles it to machine code before running. Calling the function a second time re-uses that +machine code unless the argument types have changed.

+

Numba works best when a nopython=True argument is added to the @jit decorator; functions +compiled in nopython mode +avoid the CPython API and have performance comparable to C. Further, adding nogil=True to the +@jit decorator unlocks the GIL while that function is running. Note that nogil and nopython +are separate arguments; while it is necessary for code to be compiled in nopython mode in order to +release the lock, the GIL will remain locked if nogil=False (the default).

+

Let's repeat the same experiment, this time using Numba instead of Cython:

+
# The `int` type annotation is only for humans and is ignored
# by Numba.
@jit(nopython=True, nogil=True)
def numba_nogil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Run using `nopython` mode to receive a performance boost,
# but GIL remains locked due to `nogil=False` by default.
@jit(nopython=True)
def numba_gil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Call each function once to force compilation; we don't want
# the timing statistics to include how long it takes to compile.
numba_nogil(N)
numba_gil(N);
+

We'll perform the same tests as above; first, figure out how long it takes the function to run:

+
%%time
_ = numba_gil(N)
+
+

CPU times: user 253 ms, sys: 258 µs, total: 253 ms +Wall time: 251 ms

+
+

Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be +effectively identical after compilation. +

When running two GIL-locked threads, the result (as expected) takes around twice as long to compute:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms +Wall time: 541 ms

+
+

But if the GIL-unlocking thread starts first, both threads run in parallel:

+
%%time
t1 = Thread(target=numba_nogil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms +Wall time: 279 ms

+
+

Just like Cython, starting the GIL-locked thread first leads to poor performance:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 524 ms, sys: 0 ns, total: 524 ms +Wall time: 522 ms

+
+

Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; +recursively calling @jit(nogil=True) functions is perfectly safe:

+
from numba import jit

@jit(nopython=True, nogil=True)
def numba_recurse(n: int) -> int:
if n <= 0:
return 0

return numba_recurse(n - 1)

numba_recurse(2);
+

Conclusion

+

Before finishing, it's important to address pain points that will show up if these techniques are +used in a more realistic project:

+

First, code running in a GIL-free context will likely also need non-trivial data structures; +GIL-free functions aren't useful if they're constantly interacting with Python objects whose access +requires the GIL. Cython provides +extension types and Numba +provides a @jitclass decorator to +address this need.

+

Second, building and distributing applications that make use of Cython/Numba can be complicated. +Cython packages require running the compiler, (potentially) linking/packaging external dependencies, +and distributing a binary wheel. Numba is generally simpler because the code being distributed is +pure Python, but can be tricky since errors aren't detected until runtime.

+

Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba +provide tools to directly manage the GIL when appropriate. This enables true parallelism (not just +concurrency) that is impossible in vanilla Python.

\ No newline at end of file diff --git a/404.html b/404.html index 3969180..899a525 100644 --- a/404.html +++ b/404.html @@ -1,24 +1 @@ ---- -layout: page ---- - - - -
-

404

- -

Page not found :(

-

The requested page could not be found.

-
+Page Not Found | The Old Speice Guy
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

\ No newline at end of file diff --git a/CNAME b/CNAME index 8875e7a..13be74a 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -speice.io +speice.io \ No newline at end of file diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 3031ef3..0000000 --- a/Gemfile +++ /dev/null @@ -1,29 +0,0 @@ -source "https://rubygems.org" - -# Hello! This is where you manage which Jekyll version is used to run. -# When you want to use a different version, change it below, save the -# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: -# -# bundle exec jekyll serve -# -# This will help ensure the proper Jekyll version is running. -# Happy Jekylling! -gem "jekyll", "~> 3.8.3" - -gem "texture" - -# If you want to use GitHub Pages, remove the "gem "jekyll"" above and -# uncomment the line below. To upgrade, run `bundle update github-pages`. -# gem "github-pages", group: :jekyll_plugins - -# If you have any plugins, put them here! -group :jekyll_plugins do - gem "jekyll-feed", "~> 0.6" - gem "jekyll-remote-theme" -end - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] - -# Performance-booster for watching directories on Windows -gem "wdm", "~> 0.1.0" if Gem.win_platform? diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 310c738..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,78 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - colorator (1.1.0) - concurrent-ruby (1.1.6) - em-websocket (0.5.1) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) - eventmachine (1.2.7) - ffi (1.12.2) - forwardable-extended (2.6.0) - http_parser.rb (0.6.0) - i18n (0.9.5) - concurrent-ruby (~> 1.0) - jekyll (3.8.6) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (~> 0.7) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 2.0) - kramdown (~> 1.14) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (>= 1.7, < 4) - safe_yaml (~> 1.0) - jekyll-feed (0.13.0) - jekyll (>= 3.7, < 5.0) - jekyll-remote-theme (0.4.2) - addressable (~> 2.0) - jekyll (>= 3.5, < 5.0) - jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) - rubyzip (>= 1.3.0, < 3.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-seo-tag (2.6.1) - jekyll (>= 3.3, < 5.0) - jekyll-watch (2.2.1) - listen (~> 3.0) - kramdown (1.17.0) - liquid (4.0.3) - listen (3.2.1) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.3.6) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (4.0.4) - rb-fsevent (0.10.3) - rb-inotify (0.10.1) - ffi (~> 1.0) - rouge (3.17.0) - rubyzip (2.3.0) - safe_yaml (1.0.5) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - texture (0.3) - jekyll (~> 3.7) - jekyll-seo-tag (~> 2.1) - -PLATFORMS - ruby - -DEPENDENCIES - jekyll (~> 3.8.3) - jekyll-feed (~> 0.6) - jekyll-remote-theme - texture - tzinfo-data - -BUNDLED WITH - 2.1.4 diff --git a/_config.yml b/_config.yml deleted file mode 100644 index 9f9c8cd..0000000 --- a/_config.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Welcome to Jekyll! -# -# This config file is meant for settings that affect your whole blog, values -# which you are expected to set up once and rarely edit after that. If you find -# yourself editing this file very often, consider using Jekyll's data files -# feature for the data you need to update frequently. -# -# For technical reasons, this file is *NOT* reloaded automatically when you use -# 'bundle exec jekyll serve'. If you change this file, please restart the server process. - -# Site settings -# These are used to personalize your new site. If you look in the HTML files, -# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. -# You can create any custom variable you would like, and they will be accessible -# in the templates via {{ site.myvariable }}. -title: speice.io -description: The Old Speice Guy -email: bradlee@speice.io -baseurl: "" # the subpath of your site, e.g. /blog -url: "https://speice.io/" # the base hostname & protocol for your site, e.g. http://example.com -github_username: bspeice - -# Build settings -markdown: kramdown -# theme: texture -remote_theme: thelehhman/texture -plugins: - - jekyll-feed - - jekyll-remote-theme - -include: [_pages] -permalink: /:year/:month/:title.html - -# Exclude from processing. -# The following items will not be processed, by default. Create a custom list -# to override the default setting. -# exclude: -# - Gemfile -# - Gemfile.lock -# - node_modules -# - vendor/bundle/ -# - vendor/cache/ -# - vendor/gems/ -# - vendor/ruby/ diff --git a/_includes/footer.html b/_includes/footer.html deleted file mode 100644 index 4d3c143..0000000 --- a/_includes/footer.html +++ /dev/null @@ -1,23 +0,0 @@ -{% if page.layout == 'post' %} -{% comment %}Thanks to https://www.bytedude.com/jekyll-previous-and-next-posts/{% endcomment %} -
-
-
-
- {% if page.previous.url %} - « {{page.previous.title}} - {% endif %} -
-
- {% if page.next.url %} - {{page.next.title}} » - {% endif %} -
-
-
- - - -{% endif %} \ No newline at end of file diff --git a/_includes/head.html b/_includes/head.html deleted file mode 100644 index ec0f85d..0000000 --- a/_includes/head.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - -{{ page.title | default: site.title }} -{% seo %} \ No newline at end of file diff --git a/_includes/nav.html b/_includes/nav.html deleted file mode 100644 index 14ca138..0000000 --- a/_includes/nav.html +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/_includes/page_header.html b/_includes/page_header.html deleted file mode 100644 index e486090..0000000 --- a/_includes/page_header.html +++ /dev/null @@ -1,15 +0,0 @@ -
-

{{ site.title }}

-

{{ site.description }}

- -
\ No newline at end of file diff --git a/_pages/about.md b/_pages/about.md deleted file mode 100644 index 3f45159..0000000 --- a/_pages/about.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: page -title: About -permalink: /about/ ---- - -Developer currently living in New York City. - -Best ways to get in contact: - -- Email: [bradlee@speice.io](mailto:bradlee@speice.io) -- Github: [bspeice](https://github.com/bspeice) -- LinkedIn: [bradleespeice](https://www.linkedin.com/in/bradleespeice/) diff --git a/_posts/2018-05-28-hello.md b/_posts/2018-05-28-hello.md deleted file mode 100644 index f7c76c7..0000000 --- a/_posts/2018-05-28-hello.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -layout: post -title: "Hello!" -description: "" -category: -tags: [] ---- - -I'll do what I can to keep this short, there's plenty of other things we both should be doing right -now. - -If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you -covered: - -![Saturday Bread]({{ "/assets/images/2018-05-28-bread.jpg" | absolute_url }}) - -And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven. - -Okay, just one: - -![Bread as rock]({{ "/assets/images/2018-05-28-rocks.jpg" | absolute_url }}) - -If you're here for keeping up with the man Bradlee Speice, got plenty of that too. Plus some -up-coming super-nerdy posts about how I'm changing the world. - -And if you're not here for those things: don't have a lot for you, sorry. But you're welcome to let -me know what needs to change. - -I'm looking forward to making this a place to talk about what's going on in life, I hope you'll -stick it out with me. The best way to follow what's going on is on my [About](/about/) page, but if -you want the joy of clicking links, here's a few good ones: - -- Email (people still use this?): [bradlee@speice.io](mailto:bradlee@speice.io) -- Mastodon (nerd Twitter): [@bradlee](https://mastodon.social/@bradlee) -- Chat (RiotIM): [@bspeice:matrix.com](https://matrix.to/#/@bspeice:matrix.com) -- The comments section (not for people with sanity intact): ↓↓↓ - -Thanks, and keep it amazing. diff --git a/_posts/2018-06-25-dateutil-parser-to-rust.md b/_posts/2018-06-25-dateutil-parser-to-rust.md deleted file mode 100644 index 7646f28..0000000 --- a/_posts/2018-06-25-dateutil-parser-to-rust.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -layout: post -title: "What I Learned: Porting Dateutil Parser to Rust" -description: "" -category: -tags: [dtparse, rust] ---- - -Hi. I'm Bradlee. - -I've mostly been a lurker in Rust for a while, making a couple small contributions here and there. -So launching [dtparse](https://github.com/bspeice/dtparse) feels like nice step towards becoming a -functioning member of society. But not too much, because then you know people start asking you to -pay bills, and ain't nobody got time for that. - -But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you -what to do with your life (but you should totally keep reading). - -# Slow down, what? - -OK, fine, I guess I should start with _why_ someone would do this. - -[Dateutil](https://github.com/dateutil/dateutil) is a Python library for handling dates. The -standard library support for time in Python is kinda dope, but there are a lot of extras that go -into making it useful beyond just the [datetime](https://docs.python.org/3.6/library/datetime.html) -module. `dateutil.parser` specifically is code to take all the super-weird time formats people come -up with and turn them into something actually useful. - -Date/time parsing, it turns out, is just like everything else involving -[computers](https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time) and -[time](https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time): it -feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people -suck and this is why -[we can't we have nice things](https://zachholman.com/talk/utc-is-enough-for-everyone-right). But -alas, we'll try and make contemporary art out of the rubble and give it a pretentious name like -_Time_. - -![A gravel mound](/assets/images/2018-06-25-gravel-mound.jpg) - -> [Time](https://www.goodfreephotos.com/united-states/montana/elkhorn/remains-of-the-mining-operation-elkhorn.jpg.php) - -What makes `dateutil.parser` great is that there's single function with a single argument that -drives what programmers interact with: -[`parse(timestr)`](https://github.com/dateutil/dateutil/blob/6dde5d6298cfb81a4c594a38439462799ed2aef2/dateutil/parser/_parser.py#L1258). -It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can -possibly do to make sense of your input" value. It doesn't expect much of you. - -[And now it's in Rust.](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L1332) - -# Lost in Translation - -Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm -admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can -actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better -experiences than -[this guy](https://webcache.googleusercontent.com/search?q=cache:wkYMpktJtnUJ:https://jackstouffer.com/blog/porting_dateutil.html+&cd=3&hl=en&ct=clnk&gl=us) -who attempted the same thing for D. These are the actual take-aways: - -When transcribing code, **stay as close to the original library as possible**. I'm talking about -using the same variable names, same access patterns, the whole shebang. It's way too easy to make a -couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference -manual for verbatim what your code should be means that you don't spend that long debugging -complicated logic, you're more looking for typos. - -Also, **don't use nice Rust things like enums**. While -[one time it worked out OK for me](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L88-L94), -I also managed to shoot myself in the foot a couple times because `dateutil` stores AM/PM as a -boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In -general, writing nice code _should not be a first-pass priority_ when you're just trying to recreate -the same functionality. - -**Exceptions are a pain.** Make peace with it. Python code is just allowed to skip stack frames. So -when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out -[he's not quite right](https://github.com/rust-lang/rfcs/pull/243), and I'm OK with that. And while -`dateutil` is pretty well-behaved about not skipping multiple stack frames, -[130-line try-catch blocks](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L730-L865) -take a while to verify. - -As another Python quirk, **be very careful about -[long nested if-elif-else blocks](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L494-L568)**. -I used to think that Python's whitespace was just there to get you to format your code correctly. I -think that no longer. It's way too easy to close a block too early and have incredibly weird issues -in the logic. Make sure you use an editor that displays indentation levels so you can keep things -straight. - -**Rust macros are not free.** I originally had the -[main test body](https://github.com/bspeice/dtparse/blob/b0e737f088eca8e83ab4244c6621a2797d247697/tests/compat.rs#L63-L217) -wrapped up in a macro using [pyo3](https://github.com/PyO3/PyO3). It took two minutes to compile. -After -[moving things to a function](https://github.com/bspeice/dtparse/blob/e017018295c670e4b6c6ee1cfff00dbb233db47d/tests/compat.rs#L76-L205) -compile times dropped down to ~5 seconds. Turns out 150 lines \* 100 tests = a lot of redundant code -to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually -functions that need to be liberated, man. - -Finally, **I really miss list comprehensions and dictionary comprehensions.** As a quick comparison, -see -[this dateutil code](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L476) -and -[the implementation in Rust](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L619-L629). -I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be -added through macros or syntax extensions. Either way, they're expressive, save typing, and are -super-readable. Let's get more of that. - -# Using a young language - -Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On -more than one occasion though, I've had issues navigating the Rust ecosystem. - -What I'll call the "canonical library" is still being built. In Python, if you need datetime -parsing, you use `dateutil`. If you want `decimal` types, it's already in the -[standard library](https://docs.python.org/3.6/library/decimal.html). While I might've gotten away -with `f64`, `dateutil` uses decimals, and I wanted to follow the principle of **staying as close to -the original library as possible**. Thus began my quest to find a decimal library in Rust. What I -quickly found was summarized in a comment: - -> Writing a BigDecimal is easy. Writing a _good_ BigDecimal is hard. -> -> [-cmr](https://github.com/rust-lang/rust/issues/8937#issuecomment-34582794) - -In practice, this means that there are at least [4](https://crates.io/crates/bigdecimal) -[different](https://crates.io/crates/rust_decimal) -[implementations](https://crates.io/crates/decimal) [available](https://crates.io/crates/decimate). -And that's a lot of decisions to worry about when all I'm thinking is "why can't -[calendar reform](https://en.wikipedia.org/wiki/Calendar_reform) be a thing" and I'm forced to dig -through a [couple](https://github.com/rust-lang/rust/issues/8937#issuecomment-31661916) -[different](https://github.com/rust-lang/rfcs/issues/334) -[threads](https://github.com/rust-num/num/issues/8) to figure out if the library I'm look at is dead -or just stable. - -And even when the "canonical library" exists, there's no guarantees that it will be well-maintained. -[Chrono](https://github.com/chronotope/chrono) is the _de facto_ date/time library in Rust, and just -released version 0.4.4 like two days ago. Meanwhile, -[chrono-tz](https://github.com/chronotope/chrono-tz) appears to be dead in the water even though -[there are people happy to help maintain it](https://github.com/chronotope/chrono-tz/issues/19). I -know relatively little about it, but it appears that most of the release process is automated; -keeping that up to date should be a no-brainer. - -## Trial Maintenance Policy - -Specifically given "maintenance" being an -[oft-discussed](https://www.reddit.com/r/rust/comments/48540g/thoughts_on_initiators_vs_maintainers/) -issue, I'm going to try out the following policy to keep things moving on `dtparse`: - -1. Issues/PRs needing _maintainer_ feedback will be updated at least weekly. I want to make sure - nobody's blocking on me. - -2. To keep issues/PRs needing _contributor_ feedback moving, I'm going to (kindly) ask the - contributor to check in after two weeks, and close the issue without resolution if I hear nothing - back after a month. - -The second point I think has the potential to be a bit controversial, so I'm happy to receive -feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm -running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And -second: I don't mind keeping those requests going indefinitely. I just want to try and balance -keeping things moving with giving people the necessary time they need. - -I should also note that I'm still getting some best practices in place - CONTRIBUTING and -CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are -perfect. - -# Roadmap and Conclusion - -So if I've now built a `dateutil`-compatible parser, we're done, right? Of course not! That's not -nearly ambitious enough. - -Ultimately, I'd love to have a library that's capable of parsing everything the Linux `date` command -can do (and not `date` on OSX, because seriously, BSD coreutils are the worst). I know Rust has a -coreutils rewrite going on, and `dtparse` would potentially be an interesting candidate since it -doesn't bring in a lot of extra dependencies. [`humantime`](https://crates.io/crates/humantime) -could help pick up some of the (current) slack in dtparse, so maybe we can share and care with each -other? - -All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month -on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going -to take it hard. - -And in the mean time, I'm looking forward to building more. Onwards. diff --git a/_posts/2018-09-01-primitives-in-rust-are-weird.md b/_posts/2018-09-01-primitives-in-rust-are-weird.md deleted file mode 100644 index bcc8ae8..0000000 --- a/_posts/2018-09-01-primitives-in-rust-are-weird.md +++ /dev/null @@ -1,323 +0,0 @@ ---- -layout: post -title: "Primitives in Rust are Weird (and Cool)" -description: "but mostly weird." -category: -tags: [rust, c, java, python, x86] ---- - -I wrote a really small Rust program a while back because I was curious. I was 100% convinced it -couldn't possibly run: - -```rust -fn main() { - println!("{}", 8.to_string()) -} -``` - -And to my complete befuddlement, it compiled, ran, and produced a completely sensible output. The -reason I was so surprised has to do with how Rust treats a special category of things I'm going to -call _primitives_. In the current version of the Rust book, you'll see them referred to as -[scalars][rust_scalar], and in older versions they'll be called [primitives][rust_primitive], but -we're going to stick with the name _primitive_ for the time being. Explaining why this program is so -cool requires talking about a number of other programming languages, and keeping a consistent -terminology makes things easier. - -**You've been warned:** this is going to be a tedious post about a relatively minor issue that -involves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking -about with assembly. - -# Defining primitives (Java) - -The reason I'm using the name _primitive_ comes from how much of my life is Java right now. Spoiler -alert: a lot of it. And for the most part I like Java, but I digress. In Java, there's a special -name for some specific types of values: - -> ``` -> bool char byte -> short int long -> float double -> ``` - -```` - -They are referred to as [primitives][java_primitive]. And relative to the other bits of Java, -they have two unique features. First, they don't have to worry about the -[billion-dollar mistake](https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions); -primitives in Java can never be `null`. Second: *they can't have instance methods*. -Remember that Rust program from earlier? Java has no idea what to do with it: - -```java -class Main { - public static void main(String[] args) { - int x = 8; - System.out.println(x.toString()); // Triggers a compiler error - } -} -```` - -The error is: - -``` -Main.java:5: error: int cannot be dereferenced - System.out.println(x.toString()); - ^ -1 error -``` - -Specifically, Java's [`Object`](https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html) -and things that inherit from it are pointers under the hood, and we have to dereference them before -the fields and methods they define can be used. In contrast, _primitive types are just values_ - -there's nothing to be dereferenced. In memory, they're just a sequence of bits. - -If we really want, we can turn the `int` into an -[`Integer`](https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html) and then dereference -it, but it's a bit wasteful: - -```java -class Main { - public static void main(String[] args) { - int x = 8; - Integer y = Integer.valueOf(x); - System.out.println(y.toString()); - } -} -``` - -This creates the variable `y` of type `Integer` (which inherits `Object`), and at run time we -dereference `y` to locate the `toString()` function and call it. Rust obviously handles things a bit -differently, but we have to dig into the low-level details to see it in action. - -# Low Level Handling of Primitives (C) - -We first need to build a foundation for reading and understanding the assembly code the final answer -requires. Let's begin with showing how the `C` language (and your computer) thinks about "primitive" -values in memory: - -```c -void my_function(int num) {} - -int main() { - int x = 8; - my_function(x); -} -``` - -The [compiler explorer](https://godbolt.org/z/lgNYcc) gives us an easy way of showing off the -assembly-level code that's generated: whose output has been lightly -edited - -```nasm -main: - push rbp - mov rbp, rsp - sub rsp, 16 - - ; We assign the value `8` to `x` here - mov DWORD PTR [rbp-4], 8 - - ; And copy the bits making up `x` to a location - ; `my_function` can access (`edi`) - mov eax, DWORD PTR [rbp-4] - mov edi, eax - - ; Call `my_function` and give it control - call my_function - - mov eax, 0 - leave - ret - -my_function: - push rbp - mov rbp, rsp - - ; Copy the bits out of the pre-determined location (`edi`) - ; to somewhere we can use - mov DWORD PTR [rbp-4], edi - nop - - pop rbp - ret -``` - -At a really low level of memory, we're copying bits around using the [`mov`][x86_guide] instruction; -nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C -to Rust: - -```rust -fn my_function(x: i32) {} - -fn main() { - let x = 8; - my_function(x) -} -``` - -And the assembly generated when we stick it in the -[compiler explorer](https://godbolt.org/z/cAlmk0): again, lightly -edited - -```nasm -example::main: - push rax - - ; Look familiar? We're copying bits to a location for `my_function` - ; The compiler just optimizes out holding `x` in memory - mov edi, 8 - - ; Call `my_function` and give it control - call example::my_function - - pop rax - ret - -example::my_function: - sub rsp, 4 - - ; And copying those bits again, just like in C - mov dword ptr [rsp], edi - - add rsp, 4 - ret -``` - -The generated Rust assembly is functionally pretty close to the C assembly: _When working with -primitives, we're just dealing with bits in memory_. - -In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to -dereference. So what exactly is going on with this `.to_string()` function call? - -# impl primitive (and Python) - -Now it's time to reveal my trap card show the revelation that tied all this -together: _Rust has implementations for its primitive types._ That's right, `impl` blocks aren't -only for `structs` and `traits`, primitives get them too. Don't believe me? Check out -[u32](https://doc.rust-lang.org/std/primitive.u32.html), -[f64](https://doc.rust-lang.org/std/primitive.f64.html) and -[char](https://doc.rust-lang.org/std/primitive.char.html) as examples. - -But the really interesting bit is how Rust turns those `impl` blocks into assembly. Let's break out -the [compiler explorer](https://godbolt.org/z/6LBEwq) once again: - -```rust -pub fn main() { - 8.to_string() -} -``` - -And the interesting bits in the assembly: heavily trimmed down - -```nasm -example::main: - sub rsp, 24 - mov rdi, rsp - lea rax, [rip + .Lbyte_str.u] - mov rsi, rax - - ; Cool stuff right here - call ::to_string@PLT - - mov rdi, rsp - call core::ptr::drop_in_place - add rsp, 24 - ret -``` - -Now, this assembly is a bit more complicated, but here's the big revelation: **we're calling -`to_string()` as a function that exists all on its own, and giving it the instance of `8`**. Instead -of thinking of the value 8 as an instance of `u32` and then peeking in to find the location of the -function we want to call (like Java), we have a function that exists outside of the instance and -just give that function the value `8`. - -This is an incredibly technical detail, but the interesting idea I had was this: _if `to_string()` -is a static function, can I refer to the unbound function and give it an instance?_ - -Better explained in code (and a [compiler explorer](https://godbolt.org/z/fJY-gA) link because I -seriously love this thing): - -```rust -struct MyVal { - x: u32 -} - -impl MyVal { - fn to_string(&self) -> String { - self.x.to_string() - } -} - -pub fn main() { - let my_val = MyVal { x: 8 }; - - // THESE ARE THE SAME - my_val.to_string(); - MyVal::to_string(&my_val); -} -``` - -Rust is totally fine "binding" the function call to the instance, and also as a static. - -MIND == BLOWN. - -Python does the same thing where I can both call functions bound to their instances and also call as -an unbound function where I give it the instance: - -```python -class MyClass(): - x = 24 - - def my_function(self): - print(self.x) - -m = MyClass() - -m.my_function() -MyClass.my_function(m) -``` - -And Python tries to make you _think_ that primitives can have instance methods... - -```python ->>> dir(8) -['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', -'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', -... -'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', -...] - ->>> # Theoretically `8.__str__()` should exist, but: - ->>> 8.__str__() - File "", line 1 - 8.__str__() - ^ -SyntaxError: invalid syntax - ->>> # It will run if we assign it first though: ->>> x = 8 ->>> x.__str__() -'8' -``` - -...but in practice it's a bit complicated. - -So while Python handles binding instance methods in a way similar to Rust, it's still not able to -run the example we started with. - -# Conclusion - -This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor -details like primitives leads to really cool effects. Primitives are optimized like C in how they -have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python -(like both instance and late binding). - -And when you put it together, there are areas where Rust does cool things nobody else can; as a -quirky feature of Rust's type system, `8.to_string()` is actually valid code. - -Now go forth and fool your friends into thinking you know assembly. This is all I've got. - -[x86_guide]: http://www.cs.virginia.edu/~evans/cs216/guides/x86.html -[java_primitive]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html -[rust_scalar]: https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html#scalar-types -[rust_primitive]: https://doc.rust-lang.org/book/first-edition/primitive-types.html diff --git a/_posts/2018-09-15-isomorphic-apps.md b/_posts/2018-09-15-isomorphic-apps.md deleted file mode 100644 index abc0dcb..0000000 --- a/_posts/2018-09-15-isomorphic-apps.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -layout: post -title: "Isomorphic Desktop Apps with Rust" -description: "Electron + WASM = ☣" -category: -tags: [rust, javascript, webassembly] ---- - -Forgive me, but this is going to be a bit of a schizophrenic post. I both despise Javascript and the -modern ECMAScript ecosystem, and I'm stunned by its success doing some really cool things. It's -[this duality](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript) that's -led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I -bootstrap a simple desktop application. - -See, as much as -[Webassembly isn't trying to replace Javascript](https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript), -**I want Javascript gone**. There are plenty of people who don't share my views, and they are -probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think -it's hilarious that the -[language specification](https://ecma-international.org/publications/standards/Ecma-402.htm) -dramatically outpaces anyone's -[actual implementation](https://kangax.github.io/compat-table/es2016plus/). The answer to this -conundrum is of course to recompile code from newer versions of the language to older versions _of -the same language_ before running. At least [Babel] is a nice tongue-in-cheek reference. - -Yet for as much hate as [Electron] receives, it does a stunningly good job at solving a really hard -problem: _how the hell do I put a button on the screen and react when the user clicks it_? GUI -programming is hard, straight up. But if browsers are already able to run everywhere, why don't we -take advantage of someone else solving the hard problems for us? I don't like that I have to use -Javascript for it, but I really don't feel inclined to whip out good ol' [wxWidgets]. - -Now there are other native solutions ([libui-rs], [conrod], [oh hey wxWdidgets again!][wxrust]), but -those also have their own issues with distribution, styling, etc. With Electron, I can -`yarn create electron-app my-app` and just get going, knowing that packaging/upgrades/etc. are built -in. - -My question is: given recent innovations with WASM, _are we Electron yet_? - -No, not really. - -Instead, **what would it take to get to a point where we can skip Javascript in Electron apps?** - -# Setting the Stage - -Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There -may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to -try and organize what I did manage to discover. - -I should also mention that the content and things I'm talking about here are not intended to be -prescriptive, but more "if someone else is interested, what do we already know doesn't work?" _I -expect everything in this post to be obsolete within two months._ Even over the course of writing -this, [a separate blog post](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/) had -to be modified because [upstream changes](https://github.com/WebAssembly/binaryen/pull/1642) broke a -[Rust tool](https://github.com/rustwasm/wasm-bindgen/pull/787) the post tried to use. The post -ultimately -[got updated](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477), **but -all this happened within the span of a week.** Things are moving quickly. - -I'll also note that we're going to skip [asm.js] and [emscripten]. Truth be told, I couldn't get -either of these to output anything, and so I'm just going to say -[here be dragons.](https://en.wikipedia.org/wiki/Here_be_dragons) Everything I'm discussing here -uses the `wasm32-unknown-unknown` target. - -The code that I _did_ get running is available -[over here](https://github.com/speice-io/isomorphic-rust). Feel free to use it as a starting point, -but I'm mostly including the link as a reference for the things that were attempted. - -# An Example Running Application - -So, I did _technically_ get a running application: - -![Electron app using WASM](/assets/images/2018-09-15-electron-percy-wasm.png) - -...which you can also try out if you want: - -```sh -git clone https://github.com/speice-io/isomorphic-rust.git -cd isomorphic_rust/percy -yarn install && yarn start -``` - -...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly -there to prove this is possible in the first place. And that's something to be proud of! There's a -huge amount of engineering that went into showing a window with the text "It's alive!". - -There's also a lot of usability issues that prevent me from recommending anyone try Electron and -WASM apps at the moment, and I think that's the more important thing to discuss. - -# Issue the First: Complicated Toolchains - -I quickly established that [wasm-bindgen] was necessary to "link" my Rust code to Javascript. At -that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM -blob. To keep things simple, the goal was to package everything using [webpack] so that I could just -load a `bundle.js` file on the page. That decision was to be the last thing that kinda worked in -this process. - -The first issue -[I ran into](https://www.reddit.com/r/rust/comments/98lpun/unable_to_load_wasm_for_electron_application/) -while attempting to bundle everything via `webpack` is a detail in the WASM spec: - -> This function accepts a Response object, or a promise for one, and ... **[if > it] does not match -> the `application/wasm` MIME type**, the returned promise will be rejected with a TypeError; -> -> [WebAssembly - Additional Web Embedding API](https://webassembly.org/docs/web/#additional-web-embedding-api) - -Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the -web this isn't a huge issue, as the server can set MIME types when delivering the blob. With -Electron, you're resolving things with a `file://` URL and thus can't control the MIME type: - -![TypeError: Incorrect response MIME type. Expected 'application/wasm'.](/assets/images/2018-09-15-incorrect-MIME-type.png) - -There are a couple of solutions depending on how far into the deep end you care to venture: - -- Embed a static file server in your Electron application -- Use a [custom protocol](https://electronjs.org/docs/api/protocol) and custom protocol handler -- Host your WASM blob on a website that you resolve at runtime - -But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. -Instead, my workaround was to -[open a PR with `webpack`](https://github.com/webpack/webpack/issues/7918) and use regex to remove -calls to `instantiateStreaming` in the -[build script](https://github.com/speice-io/isomorphic-rust/blob/master/percy/build.sh#L21-L25): - -```sh -cargo +nightly build --target=wasm32-unknown-unknown && \ - wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \ - # Have to use --mode=development so we can patch out the call to instantiateStreaming - "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \ - sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js" -``` - -Once that lands, the -[build process](https://github.com/speice-io/isomorphic-rust/blob/master/percy_patched_webpack/build.sh#L24-L27) -becomes much simpler: - -```sh - -cargo +nightly build --target=wasm32-unknown-unknown && \ - wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \ - "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" -``` - -But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via -`wasm-bindgen` and `webpack`), we still have to make an Electron app. For this purpose I used a -starter app from [Electron Forge], and then a -[`prestart` script](https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8) -to actually handle starting the application. - -The -[final toolchain](https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8) -looks something like this: - -- `yarn start` triggers the `prestart` script -- `prestart` checks for missing tools (`wasm-bindgen-cli`, etc.) and then: - - Uses `cargo` to compile the Rust code into WASM - - Uses `wasm-bindgen` to link the WASM blob into a Javascript file with exported symbols - - Uses `webpack` to bundle the page start script with the Javascript we just generated - - Uses `babel` under the hood to compile the `wasm-bindgen` code down from ES6 into something - browser-compatible -- The `start` script runs an Electron Forge handler to do some sanity checks -- Electron actually starts - -...which is complicated. I think more work needs to be done to either build a high-quality starter -app that can manage these steps, or another tool that "just handles" the complexity of linking a -compiled WASM file into something the Electron browser can run. - -# Issue the Second: WASM tools in Rust - -For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only -bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that -leads to a fragmented ecosystem. Here's what I can recommend as a starting point: - -Don't check in your `Cargo.lock` files to version control. If there's a disagreement between the -version of `wasm-bindgen-cli` you have installed and the `wasm-bindgen` you're compiling with in -`Cargo.lock`, you get a nasty error: - -``` -it looks like the Rust project used to create this wasm file was linked against -a different version of wasm-bindgen than this binary: - -rust wasm file: 0.2.21 - this binary: 0.2.17 - -Currently the bindgen format is unstable enough that these two version must -exactly match, so it's required that these two version are kept in sync by -either updating the wasm-bindgen dependency or this binary. -``` - -Not that I ever managed to run into this myself (_coughs nervously_). - -There are two projects attempting to be "application frameworks": [percy] and [yew]. Between those, -I managed to get [two](https://github.com/speice-io/isomorphic-rust/tree/master/percy) -[examples](https://github.com/speice-io/isomorphic-rust/tree/master/percy_patched_webpack) running -using `percy`, but was unable to get an -[example](https://github.com/speice-io/isomorphic-rust/tree/master/yew) running with `yew` because -of issues with "missing modules" during the `webpack` step: - -```sh -ERROR in ./dist/electron_yew_wasm_bg.wasm -Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist' - @ ./dist/electron_yew_wasm_bg.wasm - @ ./dist/electron_yew_wasm.js - @ ./dist/app.js - @ ./dist/app_loader.js -``` - -If you want to work with the browser APIs directly, your choices are [percy-webapis] or [stdweb] (or -eventually [web-sys]). See above for my `percy` examples, but when I tried -[an example with `stdweb`](https://github.com/speice-io/isomorphic-rust/tree/master/stdweb), I was -unable to get it running: - -```sh -ERROR in ./dist/stdweb_electron_bg.wasm -Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist' - @ ./dist/stdweb_electron_bg.wasm - @ ./dist/stdweb_electron.js - @ ./dist/app_loader.js -``` - -At this point I'm pretty convinced that `stdweb` is causing issues for `yew` as well, but can't -prove it. - -I did also get a [minimal example](https://github.com/speice-io/isomorphic-rust/tree/master/minimal) -running that doesn't depend on any tools besides `wasm-bindgen`. However, it requires manually -writing "`extern C`" blocks for everything you need from the browser. Es no bueno. - -Finally, from a tools and platform view, there are two up-and-coming packages that should be -mentioned: [js-sys] and [web-sys]. Their purpose is to be fundamental building blocks that exposes -the browser's APIs to Rust. If you're interested in building an app framework from scratch, these -should give you the most flexibility. I didn't touch either in my research, though I expect them to -be essential long-term. - -So there's a lot in play from the Rust side of things, and it's just going to take some time to -figure out what works and what doesn't. - -# Issue the Third: Known Unknowns - -Alright, so after I managed to get an application started, I stopped there. It was a good deal of -effort to chain together even a proof of concept, and at this point I'd rather learn [Typescript] -than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know... - -The important point I want to make is that there's a lot unknown about how any of this holds up -outside proofs of concept. Things I didn't attempt: - -- Testing -- Packaging -- Updates -- Literally anything related to why I wanted to use Electron in the first place - -# What it Would Take - -Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and -WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an -application in production a couple months from now. But at the moment, I'm personally going to stay -away. - -Let's finish with a wishlist then - here are the things that I think need to happen before -Electron/WASM/Rust can become a thing: - -- Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet - ([#7983](https://github.com/webpack/webpack/pull/7983)) -- Browser API libraries (`web-sys` and `stdweb`) need to make sure they can support running in - Electron (see module error above) -- Projects need to stabilize. There's talk of `stdweb` being turned into a Rust API - [on top of web-sys](https://github.com/rustwasm/team/issues/226#issuecomment-418475778), and percy - [moving to web-sys](https://github.com/chinedufn/percy/issues/24), both of which are big changes -- `wasm-bindgen` is great, but still in the "move fast and break things" phase -- A good "boilerplate" app would dramatically simplify the start-up costs; - [electron-react-boilerplate](https://github.com/chentsulin/electron-react-boilerplate) comes to - mind as a good project to imitate -- More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm - doing - -[wxwidgets]: https://wxwidgets.org/ -[libui-rs]: https://github.com/LeoTindall/libui-rs/ -[electron]: https://electronjs.org/ -[babel]: https://babeljs.io/ -[wxrust]: https://github.com/kenz-gelsoft/wxRust -[wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen -[js-sys]: https://crates.io/crates/js-sys -[percy-webapis]: https://crates.io/crates/percy-webapis -[stdweb]: https://crates.io/crates/stdweb -[web-sys]: https://crates.io/crates/web-sys -[percy]: https://chinedufn.github.io/percy/ -[virtual-dom-rs]: https://crates.io/crates/virtual-dom-rs -[yew]: https://github.com/DenisKolodin/yew -[react]: https://reactjs.org/ -[elm]: http://elm-lang.org/ -[asm.js]: http://asmjs.org/ -[emscripten]: https://kripken.github.io/emscripten-site/ -[typescript]: https://www.typescriptlang.org/ -[electron forge]: https://electronforge.io/ -[conrod]: https://github.com/PistonDevelopers/conrod -[webpack]: https://webpack.js.org/ diff --git a/_posts/2018-10-08-case-study-optimization.md b/_posts/2018-10-08-case-study-optimization.md deleted file mode 100644 index 00f24ae..0000000 --- a/_posts/2018-10-08-case-study-optimization.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -layout: post -title: "A Case Study in Heaptrack" -description: "...because you don't need no garbage collection" -category: -tags: [] ---- - -One of my earliest conversations about programming went like this: - -> Programmers have it too easy these days. They should learn to develop in low memory environments -> and be more efficient. -> -> -- My Father (paraphrased) - -...though it's not like the first code I wrote was for a -[graphing calculator](https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-se) -packing a whole 24KB of RAM. By the way, _what are you doing on my lawn?_ - -The principle remains though: be efficient with the resources you have, because -[what Intel giveth, Microsoft taketh away](http://exo-blog.blogspot.com/2007/09/what-intel-giveth-microsoft-taketh-away.html). -My professional work is focused on this kind of efficiency; low-latency financial markets demand -that you understand at a deep level _exactly_ what your code is doing. As I continue experimenting -with Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's -flexibility for the times I pretend to have a garbage collector, and flexibility for the times that -I really care about how memory is used. - -This post is a (small) case study in how I went from the former to the latter. And ultimately, it's -intended to be a starting toolkit to empower analysis of your own code. - -# Curiosity - -When I first started building the [dtparse] crate, my intention was to mirror as closely as possible -the equivalent [Python library][dateutil]. Python, as you may know, is garbage collected. Very -rarely is memory usage considered in Python, and I likewise wasn't paying too much attention when -`dtparse` was first being built. - -This lackadaisical approach to memory works well enough, and I'm not planning on making `dtparse` -hyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the -advent of Rust 1.28 and the -[Global Allocator trait](https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html), I had a really -great idea: _build a custom allocator that allows you to track your own allocations._ That way, you -can do things like writing tests for both correct results and correct memory usage. I gave it a -[shot][qadapt], but learned very quickly: **never write your own allocator**. It went from "fun -weekend project" to "I have literally no idea what my computer is doing" at breakneck speed. - -Instead, I'll highlight a separate path I took to make sense of my memory usage: [heaptrack]. - -# Turning on the System Allocator - -This is the hardest part of the post. Because Rust uses -[its own allocator](https://github.com/rust-lang/rust/pull/27400#issue-41256384) by default, -`heaptrack` is unable to properly record unmodified Rust code. To remedy this, we'll make use of the -`#[global_allocator]` attribute. - -Specifically, in `lib.rs` or `main.rs`, add this: - -```rust -use std::alloc::System; - -#[global_allocator] -static GLOBAL: System = System; -``` - -...and that's it. Everything else comes essentially for free. - -# Running heaptrack - -Assuming you've installed heaptrack (Homebrew in Mac, package manager -in Linux, ??? in Windows), all that's left is to fire up your application: - -``` -heaptrack my_application -``` - -It's that easy. After the program finishes, you'll see a file in your local directory with a name -like `heaptrack.my_appplication.XXXX.gz`. If you load that up in `heaptrack_gui`, you'll see -something like this: - -![heaptrack](/assets/images/2018-10-heaptrack/heaptrack-before.png) - ---- - -And even these pretty colors: - -![pretty colors](/assets/images/2018-10-heaptrack/heaptrack-flamegraph.png) - -# Reading Flamegraphs - -To make sense of our memory usage, we're going to focus on that last picture - it's called a -["flamegraph"](http://www.brendangregg.com/flamegraphs.html). These charts are typically used to -show how much time your program spends executing each function, but they're used here to show how -much memory was allocated during those functions instead. - -For example, we can see that all executions happened during the `main` function: - -![allocations in main](/assets/images/2018-10-heaptrack/heaptrack-main-colorized.png) - -...and within that, all allocations happened during `dtparse::parse`: - -![allocations in dtparse](/assets/images/2018-10-heaptrack/heaptrack-dtparse-colorized.png) - -...and within _that_, allocations happened in two different places: - -![allocations in parseinfo](/assets/images/2018-10-heaptrack/heaptrack-parseinfo-colorized.png) - -Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue: -**what the heck is the `Default` thing doing?** - -![pretty colors](/assets/images/2018-10-heaptrack/heaptrack-flamegraph-default.png) - -# Optimizing dtparse - -See, I knew that there were some allocations during calls to `dtparse::parse`, but I was totally -wrong about where the bulk of allocations occurred in my program. Let me post the code and see if -you can spot the mistake: - -```rust -/// Main entry point for using `dtparse`. -pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option)> { - let res = Parser::default().parse( - timestr, None, None, false, false, - None, false, - &HashMap::new(), - )?; - - Ok((res.0, res.1)) -} -``` - -> [dtparse](https://github.com/bspeice/dtparse/blob/4d7c5dd99572823fa4a390b483c38ab020a2172f/src/lib.rs#L1286) - ---- - -Because `Parser::parse` requires a mutable reference to itself, I have to create a new -`Parser::default` every time it receives a string. This is excessive! We'd rather have an immutable -parser that can be re-used, and avoid allocating memory in the first place. - -Armed with that information, I put some time in to -[make the parser immutable](https://github.com/bspeice/dtparse/commit/741afa34517d6bc1155713bbc5d66905fea13fad#diff-b4aea3e418ccdb71239b96952d9cddb6). -Now that I can re-use the same parser over and over, the allocations disappear: - -![allocations cleaned up](/assets/images/2018-10-heaptrack/heaptrack-flamegraph-after.png) - -In total, we went from requiring 2 MB of memory in -[version 1.0.2](https://crates.io/crates/dtparse/1.0.2): - -![memory before](/assets/images/2018-10-heaptrack/heaptrack-closeup.png) - -All the way down to 300KB in [version 1.0.3](https://crates.io/crates/dtparse/1.0.3): - -![memory after](/assets/images/2018-10-heaptrack/heaptrack-closeup-after.png) - -# Conclusion - -In the end, you don't need to write a custom allocator to be efficient with memory, great tools -already exist to help you understand what your program is doing. - -**Use them.** - -Given that [Moore's Law](https://en.wikipedia.org/wiki/Moore%27s_law) is -[dead](https://www.technologyreview.com/s/601441/moores-law-is-dead-now-what/), we've all got to do -our part to take back what Microsoft stole. - -[dtparse]: https://crates.io/crates/dtparse -[dateutil]: https://github.com/dateutil/dateutil -[heaptrack]: https://github.com/KDE/heaptrack -[qadapt]: https://crates.io/crates/qadapt diff --git a/_posts/2018-12-04-what-small-business-really-means.md b/_posts/2018-12-04-what-small-business-really-means.md deleted file mode 100644 index dce374d..0000000 --- a/_posts/2018-12-04-what-small-business-really-means.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: post -title: 'More "What Companies Really Mean"' -description: 'when they ask "Why should we hire you?"' -category: -tags: [] ---- - -I recently stumbled across a phenomenal small article entitled -[What Startups Really Mean By "Why Should We Hire You?"](https://angel.co/blog/what-startups-really-mean-by-why-should-we-hire-you). -Having been interviewed by smaller companies (though not exactly startups), the questions and -subtexts are the same. There's often a question behind the question that you're actually trying to -answer, and I wish I spotted the nuance earlier in my career. - -Let me also make note of one more question/euphemism I've come across: - -# How do you feel about Production Support? - -**Translation**: _We're a fairly small team, and when things break on an evening/weekend/Christmas -Day, can we call on you to be there?_ - -I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're -incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning -that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make -it out the door before the zombie apocalypse. - -Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people -who either enjoy that, or play along nicely enough that our systems keep working. - -Small teams have no such luck. If you're interviewing at a small company, especially as a "data -scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the -most inopportune moments. - -**Terrible-but-popular answers include**: _It's a part of the job, and I'm happy to contribute._ diff --git a/_posts/2018-12-15-allocation-safety.md b/_posts/2018-12-15-allocation-safety.md deleted file mode 100644 index 7892856..0000000 --- a/_posts/2018-12-15-allocation-safety.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -layout: post -title: "QADAPT - debug_assert! for your memory usage" -description: "...and why you want an allocator that goes 💥." -category: -tags: [] ---- - -I think it's part of the human condition to ignore perfectly good advice when it comes our way. A -bit over a month ago, I was dispensing sage wisdom for the ages: - -> I had a really great idea: build a custom allocator that allows you to track your own allocations. -> I gave it a shot, but learned very quickly: **never write your own allocator.** -> -> -- [me](/2018/10/case-study-optimization.html) - -I proceeded to ignore it, because we never really learn from our mistakes. - -There's another part of the human condition that derives joy from seeing things explode. - - - -And _that's_ the part I'm going to focus on. - -# Why an Allocator? - -So why, after complaining about allocators, would I still want to write one? There are three reasons -for that: - -1. Allocation/dropping is slow -2. It's difficult to know exactly when Rust will allocate or drop, especially when using code that - you did not write -3. I want automated tools to verify behavior, instead of inspecting by hand - -When I say "slow," it's important to define the terms. If you're writing web applications, you'll -spend orders of magnitude more time waiting for the database than you will the allocator. However, -there's still plenty of code where micro- or nano-seconds matter; think -[finance](https://www.youtube.com/watch?v=NH1Tta7purM), -[real-time audio](https://www.reddit.com/r/rust/comments/9hg7yj/synthesizer_progress_update/e6c291f), -[self-driving cars](https://polysync.io/blog/session-types-for-hearty-codecs/), and -[networking](https://carllerche.github.io/bytes/bytes/index.html). In these situations it's simply -unacceptable for you to spend time doing things that are not your program, and waiting on the -allocator is not cool. - -As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. -So, I propose we play a quick trivia game: **Does this code invoke the allocator?** - -## Example 1 - -```rust -fn my_function() { - let v: Vec = Vec::new(); -} -``` - -**No**: Rust [knows how big](https://doc.rust-lang.org/std/mem/fn.size_of.html) the `Vec` type is, -and reserves a fixed amount of memory on the stack for the `v` vector. However, if we wanted to -reserve extra space (using `Vec::with_capacity`) the allocator would get invoked. - -## Example 2 - -```rust -fn my_function() { - let v: Box> = Box::new(Vec::new()); -} -``` - -**Yes**: Because Boxes allow us to work with things that are of unknown size, it has to allocate on -the heap. While the `Box` is unnecessary in this snippet (release builds will optimize out the -allocation), reserving heap space more generally is needed to pass a dynamically sized type to -another function. - -## Example 3 - -```rust -fn my_function(v: Vec) { - v.push(5); -} -``` - -**Maybe**: Depending on whether the Vector we were given has space available, we may or may not -allocate. Especially when dealing with code that you did not author, it's difficult to verify that -things behave as you expect them to. - -# Blowing Things Up - -So, how exactly does QADAPT solve these problems? **Whenever an allocation or drop occurs in code -marked allocation-safe, QADAPT triggers a thread panic.** We don't want to let the program continue -as if nothing strange happened, _we want things to explode_. - -However, you don't want code to panic in production because of circumstances you didn't predict. -Just like [`debug_assert!`](https://doc.rust-lang.org/std/macro.debug_assert.html), **QADAPT will -strip out its own code when building in release mode to guarantee no panics and no performance -impact.** - -Finally, there are three ways to have QADAPT check that your code will not invoke the allocator: - -## Using a procedural macro - -The easiest method, watch an entire function for allocator invocation: - -```rust -use qadapt::no_alloc; -use qadapt::QADAPT; - -#[global_allocator] -static Q: QADAPT = QADAPT; - -#[no_alloc] -fn push_vec(v: &mut Vec) { - // This triggers a panic if v.len() == v.capacity() - v.push(5); -} - -fn main() { - let v = Vec::with_capacity(1); - - // This will *not* trigger a panic - push_vec(&v); - - // This *will* trigger a panic - push_vec(&v); -} -``` - -## Using a regular macro - -For times when you need more precision: - -```rust -use qadapt::assert_no_alloc; -use qadapt::QADAPT; - -#[global_allocator] -static Q: QADAPT = QADAPT; - -fn main() { - let v = Vec::with_capacity(1); - - // No allocations here, we already have space reserved - assert_no_alloc!(v.push(5)); - - // Even though we remove an item, it doesn't trigger a drop - // because it's a scalar. If it were a `Box<_>` type, - // a drop would trigger. - assert_no_alloc!({ - v.pop().unwrap(); - }); -} -``` - -## Using function calls - -Both the most precise and most tedious: - -```rust -use qadapt::enter_protected; -use qadapt::exit_protected; -use qadapt::QADAPT; - -#[global_allocator] -static Q: QADAPT = QADAPT; - -fn main() { - // This triggers an allocation (on non-release builds) - let v = Vec::with_capacity(1); - - enter_protected(); - // This does not trigger an allocation because we've reserved size - v.push(0); - exit_protected(); - - // This triggers an allocation because we ran out of size, - // but doesn't panic because we're no longer protected. - v.push(1); -} -``` - -## Caveats - -It's important to point out that QADAPT code is synchronous, so please be careful when mixing in -asynchronous functions: - -```rust -use futures::future::Future; -use futures::future::ok; - -#[no_alloc] -fn async_capacity() -> impl Future, Error=()> { - ok(12).and_then(|e| Ok(Vec::with_capacity(e))) -} - -fn main() { - // This doesn't trigger a panic because the `and_then` closure - // wasn't run during the function call. - async_capacity(); - - // Still no panic - assert_no_alloc!(async_capacity()); - - // This will panic because the allocation happens during `unwrap` - // in the `assert_no_alloc!` macro - assert_no_alloc!(async_capacity().poll().unwrap()); -} -``` - -# Conclusion - -While there's a lot more to writing high-performance code than managing your usage of the allocator, -it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing -what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for -most allocators. Version 1.0 was released today, and you can check it out over at -[crates.io](https://crates.io/crates/qadapt) or on [github](https://github.com/bspeice/qadapt). - -I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will -help guide that. If there are topics you're interested in, let me know in the comments below! - -[qadapt]: https://crates.io/crates/qadapt diff --git a/_posts/2019-02-04-understanding-allocations-in-rust.md b/_posts/2019-02-04-understanding-allocations-in-rust.md deleted file mode 100644 index 48b9df6..0000000 --- a/_posts/2019-02-04-understanding-allocations-in-rust.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -layout: post -title: "Allocations in Rust" -description: "An introduction to the memory model." -category: -tags: [rust, understanding-allocations] ---- - -There's an alchemy of distilling complex technical topics into articles and videos that change the -way programmers see the tools they interact with on a regular basis. I knew what a linker was, but -there's a staggering amount of complexity in between -[the OS and `main()`](https://www.youtube.com/watch?v=dOfucXtyEsU). Rust programmers use the -[`Box`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html) type all the time, but there's a -rich history of the Rust language itself wrapped up in -[how special it is](https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/). - -In a similar vein, this series attempts to look at code and understand how memory is used; the -complex choreography of operating system, compiler, and program that frees you to focus on -functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the -cognitive burden associated with memory management, but we're going to step into its world for a -while. - -Let's learn a bit about memory in Rust. - -# Table of Contents - -This series is intended as both learning and reference material; we'll work through the different -memory types Rust uses, and explain the implications of each. Ultimately, a summary will be provided -as a cheat sheet for easy future reference. To that end, a table of contents is in order: - -- Foreword -- [Global Memory Usage: The Whole World](/2019/02/the-whole-world.html) -- [Fixed Memory: Stacking Up](/2019/02/stacking-up.html) -- [Dynamic Memory: A Heaping Helping](/2019/02/a-heaping-helping.html) -- [Compiler Optimizations: What It's Done For You Lately](/2019/02/compiler-optimizations.html) -- [Summary: What Are the Rules?](/2019/02/summary.html) - -# Foreword - -Rust's three defining features of -[Performance, Reliability, and Productivity](https://www.rust-lang.org/) are all driven to a great -degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, -Python), Rust -[doesn't really](https://words.steveklabnik.com/borrow-checking-escape-analysis-and-the-generational-hypothesis) -garbage collect; instead, it uses an -[ownership](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) system to reason about -how long objects will last in your program. In some cases, if the life of an object is fairly -transient, Rust can make use of a very fast region called the "stack." When that's not possible, -Rust uses -[dynamic (heap) memory](https://en.wikipedia.org/wiki/Memory_management#Dynamic_memory_allocation) -and the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it -is important to have available. - -That said, there are specific situations in Rust where you'd never need to worry about the -stack/heap distinction! If you: - -1. Never use `unsafe` -2. Never use `#![feature(alloc)]` or the [`alloc` crate](https://doc.rust-lang.org/alloc/index.html) - -...then it's not possible for you to use dynamic memory! - -For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited -memory, and the program binary size itself may significantly affect what's available! There's no -operating system able to manage this -["virtual memory"](https://en.wikipedia.org/wiki/Virtual_memory) thing, but that's not an issue -because there's only one running application. The -[embedonomicon](https://docs.rust-embedded.org/embedonomicon/preface.html) is ever in mind, and -interacting with the "real world" through extra peripherals is accomplished by reading and writing -to [specific memory addresses](https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-gpio-mem.html). - -Most Rust programs find these requirements overly burdensome though. C++ developers would struggle -without access to [`std::vector`](https://en.cppreference.com/w/cpp/container/vector) (except those -hardcore no-STL people), and Rust developers would struggle without -[`std::vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). But with the constraints above, -`std::vec` is actually a part of the -[`alloc` crate](https://doc.rust-lang.org/alloc/vec/struct.Vec.html), and thus off-limits. `Box`, -`Rc`, etc., are also unusable for the same reason. - -Whether writing code for embedded devices or not, the important thing in both situations is how much -you know _before your application starts_ about what its memory usage will look like. In embedded -devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large -[google.com](https://www.google.com)'s home page is until you start trying to download it. The -compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code -runs faster when the compiler can guarantee exactly how much memory your program needs while it's -running. This series is all about understanding how the compiler reasons about your program, with an -emphasis on the implications for performance. - -Now let's address some conditions and caveats before going much further: - -- We'll focus on "safe" Rust only; `unsafe` lets you use platform-specific allocation API's - ([`malloc`](https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm)) that we'll - ignore. -- We'll assume a "debug" build of Rust code (what you get with `cargo run` and `cargo test`) and - address (pun intended) release mode at the end (`cargo run --release` and `cargo test --release`). -- All content will be run using Rust 1.32, as that's the highest currently supported in the - [Compiler Exporer](https://godbolt.org/). As such, we'll avoid upcoming innovations like - [compile-time evaluation of `static`](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md) - that are available in nightly. -- Because of the nature of the content, being able to read assembly is helpful. We'll keep it - simple, but I [found](https://stackoverflow.com/a/4584131/1454178) a - [refresher](https://stackoverflow.com/a/26026278/1454178) on the `push` and `pop` - [instructions](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html) was helpful while writing - this. -- I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are - available, but if there's something said in error it will be corrected expeditiously. Please let - me know at [bradlee@speice.io](mailto:bradlee@speice.io) - -Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth -repeating: - -> Rust does not currently have a rigorously and formally defined memory model. -> -> -- [the docs](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html) diff --git a/_posts/2019-02-05-the-whole-world.md b/_posts/2019-02-05-the-whole-world.md deleted file mode 100644 index ef3bc47..0000000 --- a/_posts/2019-02-05-the-whole-world.md +++ /dev/null @@ -1,337 +0,0 @@ ---- -layout: post -title: "Global Memory Usage: The Whole World" -description: "Static considered slightly less harmful." -category: -tags: [rust, understanding-allocations] ---- - -The first memory type we'll look at is pretty special: when Rust can prove that a _value_ is fixed -for the life of a program (`const`), and when a _reference_ is unique for the life of a program -(`static` as a declaration, not -[`'static`](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#the-static-lifetime) as a -lifetime), we can make use of global memory. This special section of data is embedded directly in -the program binary so that variables are ready to go once the program loads; no additional -computation is necessary. - -Understanding the value/reference distinction is important for reasons we'll go into below, and -while the -[full specification](https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md) for -these two keywords is available, we'll take a hands-on approach to the topic. - -# **const** - -When a _value_ is guaranteed to be unchanging in your program (where "value" may be scalars, -`struct`s, etc.), you can declare it `const`. This tells the compiler that it's safe to treat the -value as never changing, and enables some interesting optimizations; not only is there no -initialization cost to creating the value (it is loaded at the same time as the executable parts of -your program), but the compiler can also copy the value around if it speeds up the code. - -The points we need to address when talking about `const` are: - -- `Const` values are stored in read-only memory - it's impossible to modify. -- Values resulting from calling a `const fn` are materialized at compile-time. -- The compiler may (or may not) copy `const` values wherever it chooses. - -## Read-Only - -The first point is a bit strange - "read-only memory." -[The Rust book](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants) -mentions in a couple places that using `mut` with constants is illegal, but it's also important to -demonstrate just how immutable they are. _Typically_ in Rust you can use -[interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html) to modify -things that aren't declared `mut`. -[`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) provides an example of this -pattern in action: - -```rust -use std::cell::RefCell; - -fn my_mutator(cell: &RefCell) { - // Even though we're given an immutable reference, - // the `replace` method allows us to modify the inner value. - cell.replace(14); -} - -fn main() { - let cell = RefCell::new(25); - // Prints out 25 - println!("Cell: {:?}", cell); - my_mutator(&cell); - // Prints out 14 - println!("Cell: {:?}", cell); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8e4bea1a718edaff4507944e825a54b2) - -When `const` is involved though, interior mutability is impossible: - -```rust -use std::cell::RefCell; - -const CELL: RefCell = RefCell::new(25); - -fn my_mutator(cell: &RefCell) { - cell.replace(14); -} - -fn main() { - // First line prints 25 as expected - println!("Cell: {:?}", &CELL); - my_mutator(&CELL); - // Second line *still* prints 25 - println!("Cell: {:?}", &CELL); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88fe98110c33c1b3a51e341f48b8ae00) - -And a second example using [`Once`](https://doc.rust-lang.org/std/sync/struct.Once.html): - -```rust -use std::sync::Once; - -const SURPRISE: Once = Once::new(); - -fn main() { - // This is how `Once` is supposed to be used - SURPRISE.call_once(|| println!("Initializing...")); - // Because `Once` is a `const` value, we never record it - // having been initialized the first time, and this closure - // will also execute. - SURPRISE.call_once(|| println!("Initializing again???")); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c3cc5979b5e5434eca0f9ec4a06ee0ed) - -When the -[`const` specification](https://github.com/rust-lang/rfcs/blob/26197104b7bb9a5a35db243d639aee6e46d35d75/text/0246-const-vs-static.md) -refers to ["rvalues"](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf), this -behavior is what they refer to. [Clippy](https://github.com/rust-lang/rust-clippy) will treat this -as an error, but it's still something to be aware of. - -## Initialization == Compilation - -The next thing to mention is that `const` values are loaded into memory _as part of your program -binary_. Because of this, any `const` values declared in your program will be "realized" at -compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may -be able to prefetch the value), but that's it. - -```rust -use std::cell::RefCell; - -const CELL: RefCell = RefCell::new(24); - -pub fn multiply(value: u32) -> u32 { - // CELL is stored at `.L__unnamed_1` - value * (*CELL.get_mut()) -} -``` - --- [Compiler Explorer](https://godbolt.org/z/Th8boO) - -The compiler creates one `RefCell`, uses it everywhere, and never needs to call the `RefCell::new` -function. - -## Copying - -If it's helpful though, the compiler can choose to copy `const` values. - -```rust -const FACTOR: u32 = 1000; - -pub fn multiply(value: u32) -> u32 { - // See assembly line 4 for the `mov edi, 1000` instruction - value * FACTOR -} - -pub fn multiply_twice(value: u32) -> u32 { - // See assembly lines 22 and 29 for `mov edi, 1000` instructions - value * FACTOR * FACTOR -} -``` - --- [Compiler Explorer](https://godbolt.org/z/ZtS54X) - -In this example, the `FACTOR` value is turned into the `mov edi, 1000` instruction in both the -`multiply` and `multiply_twice` functions; the "1000" value is never "stored" anywhere, as it's -small enough to inline into the assembly instructions. - -Finally, getting the address of a `const` value is possible, but not guaranteed to be unique -(because the compiler can choose to copy values). I was unable to get non-unique pointers in my -testing (even using different crates), but the specifications are clear enough: _don't rely on -pointers to `const` values being consistent_. To be frank, caring about locations for `const` values -is almost certainly a code smell. - -# **static** - -Static variables are related to `const` variables, but take a slightly different approach. When we -declare that a _reference_ is unique for the life of a program, you have a `static` variable -(unrelated to the `'static` lifetime). Because of the reference/value distinction with -`const`/`static`, static variables behave much more like typical "global" variables. - -But to understand `static`, here's what we'll look at: - -- `static` variables are globally unique locations in memory. -- Like `const`, `static` variables are loaded at the same time as your program being read into - memory. -- All `static` variables must implement the - [`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html) marker trait. -- Interior mutability is safe and acceptable when using `static` variables. - -## Memory Uniqueness - -The single biggest difference between `const` and `static` is the guarantees provided about -uniqueness. Where `const` variables may or may not be copied in code, `static` variables are -guarantee to be unique. If we take a previous `const` example and change it to `static`, the -difference should be clear: - -```rust -static FACTOR: u32 = 1000; - -pub fn multiply(value: u32) -> u32 { - // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used - value * FACTOR -} - -pub fn multiply_twice(value: u32) -> u32 { - // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used - value * FACTOR * FACTOR -} -``` - --- [Compiler Explorer](https://godbolt.org/z/uxmiRQ) - -Where [previously](#copying) there were plenty of references to multiplying by 1000, the new -assembly refers to `FACTOR` as a named memory location instead. No initialization work needs to be -done, but the compiler can no longer prove the value never changes during execution. - -## Initialization == Compilation - -Next, let's talk about initialization. The simplest case is initializing static variables with -either scalar or struct notation: - -```rust -#[derive(Debug)] -struct MyStruct { - x: u32 -} - -static MY_STRUCT: MyStruct = MyStruct { - // You can even reference other statics - // declared later - x: MY_VAL -}; - -static MY_VAL: u32 = 24; - -fn main() { - println!("Static MyStruct: {:?}", MY_STRUCT); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b538dbc46076f12db047af4f4403ee6e) - -Things can get a bit weirder when using `const fn` though. In most cases, it just works: - -```rust -#[derive(Debug)] -struct MyStruct { - x: u32 -} - -impl MyStruct { - const fn new() -> MyStruct { - MyStruct { x: 24 } - } -} - -static MY_STRUCT: MyStruct = MyStruct::new(); - -fn main() { - println!("const fn Static MyStruct: {:?}", MY_STRUCT); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8c796a6e7fc273c12115091b707b0255) - -However, there's a caveat: you're currently not allowed to use `const fn` to initialize static -variables of types that aren't marked `Sync`. For example, -[`RefCell::new()`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.new) is a -`const fn`, but because -[`RefCell` isn't `Sync`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#impl-Sync), you'll -get an error at compile time: - -```rust -use std::cell::RefCell; - -// error[E0277]: `std::cell::RefCell` cannot be shared between threads safely -static MY_LOCK: RefCell = RefCell::new(0); -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c76ef86e473d07117a1700e21fd45560) - -It's likely that this will -[change in the future](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md) though. - -## **Sync** - -Which leads well to the next point: static variable types must implement the -[`Sync` marker](https://doc.rust-lang.org/std/marker/trait.Sync.html). Because they're globally -unique, it must be safe for you to access static variables from any thread at any time. Most -`struct` definitions automatically implement the `Sync` trait because they contain only elements -which themselves implement `Sync` (read more in the -[Nomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html)). This is why earlier examples could -get away with initializing statics, even though we never included an `impl Sync for MyStruct` in the -code. To demonstrate this property, Rust refuses to compile our earlier example if we add a -non-`Sync` element to the `struct` definition: - -```rust -use std::cell::RefCell; - -struct MyStruct { - x: u32, - y: RefCell, -} - -// error[E0277]: `std::cell::RefCell` cannot be shared between threads safely -static MY_STRUCT: MyStruct = MyStruct { - x: 8, - y: RefCell::new(8) -}; -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=40074d0248f056c296b662dbbff97cfc) - -## Interior Mutability - -Finally, while `static mut` variables are allowed, mutating them is an `unsafe` operation. If we -want to stay in `safe` Rust, we can use interior mutability to accomplish similar goals: - -```rust -use std::sync::Once; - -// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once -static INIT: Once = Once::new(); - -fn main() { - // Note that while `INIT` is declared immutable, we're still allowed - // to mutate its interior - INIT.call_once(|| println!("Initializing...")); - // This code won't panic, as the interior of INIT was modified - // as part of the previous `call_once` - INIT.call_once(|| panic!("INIT was called twice!")); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3ba003a981a7ed7400240caadd384d59) diff --git a/_posts/2019-02-06-stacking-up.md b/_posts/2019-02-06-stacking-up.md deleted file mode 100644 index b060ea1..0000000 --- a/_posts/2019-02-06-stacking-up.md +++ /dev/null @@ -1,601 +0,0 @@ ---- -layout: post -title: "Fixed Memory: Stacking Up" -description: "We don't need no allocator." -category: -tags: [rust, understanding-allocations] ---- - -`const` and `static` are perfectly fine, but it's relatively rare that we know at compile-time about -either values or references that will be the same for the duration of our program. Put another way, -it's not often the case that either you or your compiler knows how much memory your entire program -will ever need. - -However, there are still some optimizations the compiler can do if it knows how much memory -individual functions will need. Specifically, the compiler can make use of "stack" memory (as -opposed to "heap" memory) which can be managed far faster in both the short- and long-term. When -requesting memory, the [`push` instruction](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html) -can typically complete in [1 or 2 cycles](https://agner.org/optimize/instruction_tables.ods) (<1 -nanosecond on modern CPUs). Contrast that to heap memory which requires an allocator (specialized -software to track what memory is in use) to reserve space. When you're finished with stack memory, -the `pop` instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory -fragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have -been used to design allocators: - -- [Garbage Collection]() - strategies like [Tracing](https://en.wikipedia.org/wiki/Tracing_garbage_collection) (used in - [Java](https://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html)) and - [Reference counting](https://en.wikipedia.org/wiki/Reference_counting) (used in - [Python](https://docs.python.org/3/extending/extending.html#reference-counts)) -- Thread-local structures to prevent locking the allocator in - [tcmalloc](https://jamesgolick.com/2013/5/19/how-tcmalloc-works.html) -- Arena structures used in [jemalloc](http://jemalloc.net/), which - [until recently](https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#jemalloc-is-removed-by-default) - was the primary allocator for Rust programs! - -But no matter how fast your allocator is, the principle remains: the fastest allocator is the one -you never use. As such, we're not going to discuss how exactly the -[`push` and `pop` instructions work](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html), but -we'll focus instead on the conditions that enable the Rust compiler to use faster stack-based -allocation for variables. - -So, **how do we know when Rust will or will not use stack allocation for objects we create?** -Looking at other languages, it's often easy to delineate between stack and heap. Managed memory -languages (Python, Java, -[C#](https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/)) place -everything on the heap. JIT compilers ([PyPy](https://www.pypy.org/), -[HotSpot](https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html)) may optimize -some heap allocations away, but you should never assume it will happen. C makes things clear with -calls to special functions (like [malloc(3)](https://linux.die.net/man/3/malloc)) needed to access -heap memory. Old C++ has the [`new`](https://stackoverflow.com/a/655086/1454178) keyword, though -modern C++/C++11 is more complicated with [RAII](https://en.cppreference.com/w/cpp/language/raii). - -For Rust, we can summarize as follows: **stack allocation will be used for everything that doesn't -involve "smart pointers" and collections**. We'll skip over a precise definition of the term "smart -pointer" for now, and instead discuss what we should watch for to understand when stack and heap -memory regions are used: - -1. Stack manipulation instructions (`push`, `pop`, and `add`/`sub` of the `rsp` register) indicate - allocation of stack memory: - - ```rust - pub fn stack_alloc(x: u32) -> u32 { - // Space for `y` is allocated by subtracting from `rsp`, - // and then populated - let y = [1u8, 2, 3, 4]; - // Space for `y` is deallocated by adding back to `rsp` - x - } - ``` - - -- [Compiler Explorer](https://godbolt.org/z/5WSgc9) - -2. Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch - for `call core::ptr::real_drop_in_place`, and infer that a heap allocation happened in the recent - past: - - ```rust - pub fn heap_alloc(x: usize) -> usize { - // Space for elements in a vector has to be allocated - // on the heap, and is then de-allocated once the - // vector goes out of scope - let y: Vec = Vec::with_capacity(x); - x - } - ``` - - -- [Compiler Explorer](https://godbolt.org/z/epfgoQ) (`real_drop_in_place` happens on line 1317) - Note: While the - [`Drop` trait](https://doc.rust-lang.org/std/ops/trait.Drop.html) is - [called for stack-allocated objects](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87edf374d8983816eb3d8cfeac657b46), - the Rust standard library only defines `Drop` implementations for types that involve heap - allocation. - -3. If you don't want to inspect the assembly, use a custom allocator that's able to track and alert - when heap allocations occur. Crates like - [`alloc_counter`](https://crates.io/crates/alloc_counter) are designed for exactly this purpose. - -With all that in mind, let's talk about situations in which we're guaranteed to use stack memory: - -- Structs are created on the stack. -- Function arguments are passed on the stack, meaning the - [`#[inline]` attribute](https://doc.rust-lang.org/reference/attributes.html#inline-attribute) will - not change the memory region used. -- Enums and unions are stack-allocated. -- [Arrays](https://doc.rust-lang.org/std/primitive.array.html) are always stack-allocated. -- Closures capture their arguments on the stack. -- Generics will use stack allocation, even with dynamic dispatch. -- [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html) types are guaranteed to be - stack-allocated, and copying them will be done in stack memory. -- [`Iterator`s](https://doc.rust-lang.org/std/iter/trait.Iterator.html) in the standard library are - stack-allocated even when iterating over heap-based collections. - -# Structs - -The simplest case comes first. When creating vanilla `struct` objects, we use stack memory to hold -their contents: - -```rust -struct Point { - x: u64, - y: u64, -} - -struct Line { - a: Point, - b: Point, -} - -pub fn make_line() { - // `origin` is stored in the first 16 bytes of memory - // starting at location `rsp` - let origin = Point { x: 0, y: 0 }; - // `point` makes up the next 16 bytes of memory - let point = Point { x: 1, y: 2 }; - - // When creating `ray`, we just move the content out of - // `origin` and `point` into the next 32 bytes of memory - let ray = Line { a: origin, b: point }; -} -``` - --- [Compiler Explorer](https://godbolt.org/z/vri9BE) - -Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the -`sub rsp, 64` instruction indicates we're still working with the stack. - -# Function arguments - -Have you ever wondered how functions communicate with each other? Like, once the variables are given -to you, everything's fine. But how do you "give" those variables to another function? How do you get -the results back afterward? The answer: the compiler arranges memory and assembly instructions using -a pre-determined [calling convention](http://llvm.org/docs/LangRef.html#calling-conventions). This -convention governs the rules around where arguments needed by a function will be located (either in -memory offsets relative to the stack pointer `rsp`, or in other registers), and where the results -can be found once the function has finished. And when multiple languages agree on what the calling -conventions are, you can do things like having [Go call Rust code](https://blog.filippo.io/rustgo/)! - -Put simply: it's the compiler's job to figure out how to call other functions, and you can assume -that the compiler is good at its job. - -We can see this in action using a simple example: - -```rust -struct Point { - x: i64, - y: i64, -} - -// We use integer division operations to keep -// the assembly clean, understanding the result -// isn't accurate. -fn distance(a: &Point, b: &Point) -> i64 { - // Immediately subtract from `rsp` the bytes needed - // to hold all the intermediate results - this is - // the stack allocation step - - // The compiler used the `rdi` and `rsi` registers - // to pass our arguments, so read them in - let x1 = a.x; - let x2 = b.x; - let y1 = a.y; - let y2 = b.y; - - // Do the actual math work - let x_pow = (x1 - x2) * (x1 - x2); - let y_pow = (y1 - y2) * (y1 - y2); - let squared = x_pow + y_pow; - squared / squared - - // Our final result will be stored in the `rax` register - // so that our caller knows where to retrieve it. - // Finally, add back to `rsp` the stack memory that is - // now ready to be used by other functions. -} - -pub fn total_distance() { - let start = Point { x: 1, y: 2 }; - let middle = Point { x: 3, y: 4 }; - let end = Point { x: 5, y: 6 }; - - let _dist_1 = distance(&start, &middle); - let _dist_2 = distance(&middle, &end); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/Qmx4ST) - -As a consequence of function arguments never using heap memory, we can also infer that functions -using the `#[inline]` attributes also do not heap allocate. But better than inferring, we can look -at the assembly to prove it: - -```rust -struct Point { - x: i64, - y: i64, -} - -// Note that there is no `distance` function in the assembly output, -// and the total line count goes from 229 with inlining off -// to 306 with inline on. Even still, no heap allocations occur. -#[inline(always)] -fn distance(a: &Point, b: &Point) -> i64 { - let x1 = a.x; - let x2 = b.x; - let y1 = a.y; - let y2 = b.y; - - let x_pow = (a.x - b.x) * (a.x - b.x); - let y_pow = (a.y - b.y) * (a.y - b.y); - let squared = x_pow + y_pow; - squared / squared -} - -pub fn total_distance() { - let start = Point { x: 1, y: 2 }; - let middle = Point { x: 3, y: 4 }; - let end = Point { x: 5, y: 6 }; - - let _dist_1 = distance(&start, &middle); - let _dist_2 = distance(&middle, &end); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/30Sh66) - -Finally, passing by value (arguments with type -[`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)) and passing by reference (either -moving ownership or passing a pointer) may have slightly different layouts in assembly, but will -still use either stack memory or CPU registers: - -```rust -pub struct Point { - x: i64, - y: i64, -} - -// Moving values -pub fn distance_moved(a: Point, b: Point) -> i64 { - let x1 = a.x; - let x2 = b.x; - let y1 = a.y; - let y2 = b.y; - - let x_pow = (x1 - x2) * (x1 - x2); - let y_pow = (y1 - y2) * (y1 - y2); - let squared = x_pow + y_pow; - squared / squared -} - -// Borrowing values has two extra `mov` instructions on lines 21 and 22 -pub fn distance_borrowed(a: &Point, b: &Point) -> i64 { - let x1 = a.x; - let x2 = b.x; - let y1 = a.y; - let y2 = b.y; - - let x_pow = (x1 - x2) * (x1 - x2); - let y_pow = (y1 - y2) * (y1 - y2); - let squared = x_pow + y_pow; - squared / squared -} -``` - --- [Compiler Explorer](https://godbolt.org/z/06hGiv) - -# Enums - -If you've ever worried that wrapping your types in -[`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) or -[`Result`](https://doc.rust-lang.org/stable/core/result/enum.Result.html) would finally make them -large enough that Rust decides to use heap allocation instead, fear no longer: `enum` and union -types don't use heap allocation: - -```rust -enum MyEnum { - Small(u8), - Large(u64) -} - -struct MyStruct { - x: MyEnum, - y: MyEnum, -} - -pub fn enum_compare() { - let x = MyEnum::Small(0); - let y = MyEnum::Large(0); - - let z = MyStruct { x, y }; - - let opt = Option::Some(z); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/HK7zBx) - -Because the size of an `enum` is the size of its largest element plus a flag, the compiler can -predict how much memory is used no matter which variant of an enum is currently stored in a -variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great -way to show this in assembly, so I'll instead point you to the -[`core::mem::size_of`](https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums) -documentation. - -# Arrays - -The array type is guaranteed to be stack allocated, which is why the array size must be declared. -Interestingly enough, this can be used to cause safe Rust programs to crash: - -```rust -// 256 bytes -#[derive(Default)] -struct TwoFiftySix { - _a: [u64; 32] -} - -// 8 kilobytes -#[derive(Default)] -struct EightK { - _a: [TwoFiftySix; 32] -} - -// 256 kilobytes -#[derive(Default)] -struct TwoFiftySixK { - _a: [EightK; 32] -} - -// 8 megabytes - exceeds space typically provided for the stack, -// though the kernel can be instructed to allocate more. -// On Linux, you can check stack size using `ulimit -s` -#[derive(Default)] -struct EightM { - _a: [TwoFiftySixK; 32] -} - -fn main() { - // Because we already have things in stack memory - // (like the current function call stack), allocating another - // eight megabytes of stack memory crashes the program - let _x = EightM::default(); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=587a6380a4914bcbcef4192c90c01dc4) - -There aren't any security implications of this (no memory corruption occurs), but it's good to note -that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to -overflow the stack. - -# Closures - -Rules for how anonymous functions capture their arguments are typically language-specific. In Java, -[Lambda Expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) are -actually objects created on the heap that capture local primitives by copying, and capture local -non-primitives as (`final`) references. -[Python](https://docs.python.org/3.7/reference/expressions.html#lambda) and -[JavaScript](https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) -both bind _everything_ by reference normally, but Python can also -[capture values](https://stackoverflow.com/a/235764/1454178) and JavaScript has -[Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). - -In Rust, arguments to closures are the same as arguments to other functions; closures are simply -functions that don't have a declared name. Some weird ordering of the stack may be required to -handle them, but it's the compiler's responsiblity to figure that out. - -Each example below has the same effect, but a different assembly implementation. In the simplest -case, we immediately run a closure returned by another function. Because we don't store a reference -to the closure, the stack memory needed to store the captured values is contiguous: - -```rust -fn my_func() -> impl FnOnce() { - let x = 24; - // Note that this closure in assembly looks exactly like - // any other function; you even use the `call` instruction - // to start running it. - move || { x; } -} - -pub fn immediate() { - my_func()(); - my_func()(); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/mgJ2zl), 25 total assembly instructions - -If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory -of the original function. Getting the details right is a bit harder, so the instruction count goes -up even though this code is functionally equivalent to our original example: - -```rust -pub fn simple_reference() { - let x = my_func(); - let y = my_func(); - y(); - x(); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/K_dj5n), 55 total assembly instructions - -Even things like variable order can make a difference in instruction count: - -```rust -pub fn complex() { - let x = my_func(); - let y = my_func(); - x(); - y(); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/p37qFl), 70 total assembly instructions - -In every circumstance though, the compiler ensured that no heap allocations were necessary. - -# Generics - -Traits in Rust come in two broad forms: static dispatch (monomorphization, `impl Trait`) and dynamic -dispatch (trait objects, `dyn Trait`). While dynamic dispatch is often _associated_ with trait -objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well: - -```rust -trait GetInt { - fn get_int(&self) -> u64; -} - -// vtable stored at section L__unnamed_1 -struct WhyNotU8 { - x: u8 -} -impl GetInt for WhyNotU8 { - fn get_int(&self) -> u64 { - self.x as u64 - } -} - -// vtable stored at section L__unnamed_2 -struct ActualU64 { - x: u64 -} -impl GetInt for ActualU64 { - fn get_int(&self) -> u64 { - self.x - } -} - -// `&dyn` declares that we want to use dynamic dispatch -// rather than monomorphization, so there is only one -// `retrieve_int` function that shows up in the final assembly. -// If we used generics, there would be one implementation of -// `retrieve_int` for each type that implements `GetInt`. -pub fn retrieve_int(u: &dyn GetInt) { - // In the assembly, we just call an address given to us - // in the `rsi` register and hope that it was set up - // correctly when this function was invoked. - let x = u.get_int(); -} - -pub fn do_call() { - // Note that even though the vtable for `WhyNotU8` and - // `ActualU64` includes a pointer to - // `core::ptr::real_drop_in_place`, it is never invoked. - let a = WhyNotU8 { x: 0 }; - let b = ActualU64 { x: 0 }; - - retrieve_int(&a); - retrieve_int(&b); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/u_yguS) - -It's hard to imagine practical situations where dynamic dispatch would be used for objects that -aren't heap allocated, but it technically can be done. - -# Copy types - -Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs -[go into detail](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html) far better than can -be addressed here, so I'll leave them to do the job. From a memory perspective though, their -guideline is reasonable: -[if your type can implemement `Copy`, it should](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html#when-should-my-type-be-copy). -While there are potential speed tradeoffs to _benchmark_ when discussing `Copy` (move semantics for -stack objects vs. copying stack pointers vs. copying stack `struct`s), _it's impossible for `Copy` -to introduce a heap allocation_. - -But why is this the case? Fundamentally, it's because the language controls what `Copy` means - -["the behavior of `Copy` is not overloadable"](https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone) -because it's a marker trait. From there we'll note that a type -[can implement `Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html#when-can-my-type-be-copy) -if (and only if) its components implement `Copy`, and that -[no heap-allocated types implement `Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html#implementors). -Thus, assignments involving heap types are always move semantics, and new heap allocations won't -occur because of implicit operator behavior. - -```rust -#[derive(Clone)] -struct Cloneable { - x: Box -} - -// error[E0204]: the trait `Copy` may not be implemented for this type -#[derive(Copy, Clone)] -struct NotCopyable { - x: Box -} -``` - --- [Compiler Explorer](https://godbolt.org/z/VToRuK) - -# Iterators - -In managed memory languages (like -[Java](https://www.youtube.com/watch?v=bSkpMdDe4g4&feature=youtu.be&t=357)), there's a subtle -difference between these two code samples: - -```java -public static int sum_for(List vals) { - long sum = 0; - // Regular for loop - for (int i = 0; i < vals.length; i++) { - sum += vals[i]; - } - return sum; -} - -public static int sum_foreach(List vals) { - long sum = 0; - // "Foreach" loop - uses iteration - for (Long l : vals) { - sum += l; - } - return sum; -} -``` - -In the `sum_for` function, nothing terribly interesting happens. In `sum_foreach`, an object of type -[`Iterator`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html) -is allocated on the heap, and will eventually be garbage-collected. This isn't a great design; -iterators are often transient objects that you need during a function and can discard once the -function ends. Sounds exactly like the issue stack-allocated objects address, no? - -In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in -heap memory, but the iterator itself -([`Iter`](https://doc.rust-lang.org/std/slice/struct.Iter.html)) doesn't need to use the heap. In -each of the examples below we iterate over a collection, but never use heap allocation: - -```rust -use std::collections::HashMap; -// There's a lot of assembly generated, but if you search in the text, -// there are no references to `real_drop_in_place` anywhere. - -pub fn sum_vec(x: &Vec) { - let mut s = 0; - // Basic iteration over vectors doesn't need allocation - for y in x { - s += y; - } -} - -pub fn sum_enumerate(x: &Vec) { - let mut s = 0; - // More complex iterators are just fine too - for (_i, y) in x.iter().enumerate() { - s += y; - } -} - -pub fn sum_hm(x: &HashMap) { - let mut s = 0; - // And it's not just Vec, all types will allocate the iterator - // on stack memory - for y in x.values() { - s += y; - } -} -``` - --- [Compiler Explorer](https://godbolt.org/z/FTT3CT) diff --git a/_posts/2019-02-07-a-heaping-helping.md b/_posts/2019-02-07-a-heaping-helping.md deleted file mode 100644 index b68c447..0000000 --- a/_posts/2019-02-07-a-heaping-helping.md +++ /dev/null @@ -1,254 +0,0 @@ ---- -layout: post -title: "Dynamic Memory: A Heaping Helping" -description: "The reason Rust exists." -category: -tags: [rust, understanding-allocations] ---- - -Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and -some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how -the language uses dynamic memory (also referred to as the **heap**) is a system called _ownership_. -And as the docs mention, ownership -[is Rust's most unique feature](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html). - -The heap is used in two situations; when the compiler is unable to predict either the _total size of -memory needed_, or _how long the memory is needed for_, it allocates space in the heap. This happens -pretty frequently; if you want to download the Google home page, you won't know how large it is -until your program runs. And when you're finished with Google, we deallocate the memory so it can be -used to store other webpages. If you're interested in a slightly longer explanation of the heap, -check out -[The Stack and the Heap](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#the-stack-and-the-heap) -in Rust's documentation. - -We won't go into detail on how the heap is managed; the -[ownership documentation](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) does a -phenomenal job explaining both the "why" and "how" of memory management. Instead, we're going to -focus on understanding "when" heap allocations occur in Rust. - -To start off, take a guess for how many allocations happen in the program below: - -```rust -fn main() {} -``` - -It's obviously a trick question; while no heap allocations occur as a result of that code, the setup -needed to call `main` does allocate on the heap. Here's a way to show it: - -```rust -#![feature(integer_atomics)] -use std::alloc::{GlobalAlloc, Layout, System}; -use std::sync::atomic::{AtomicU64, Ordering}; - -static ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0); - -struct CountingAllocator; - -unsafe impl GlobalAlloc for CountingAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst); - System.alloc(layout) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - System.dealloc(ptr, layout); - } -} - -#[global_allocator] -static A: CountingAllocator = CountingAllocator; - -fn main() { - let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst); - println!("There were {} allocations before calling main!", x); -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=fb5060025ba79fc0f906b65a4ef8eb8e) - -As of the time of writing, there are five allocations that happen before `main` is ever called. - -But when we want to understand more practically where heap allocation happens, we'll follow this -guide: - -- Smart pointers hold their contents in the heap -- Collections are smart pointers for many objects at a time, and reallocate when they need to grow - -Finally, there are two "addendum" issues that are important to address when discussing Rust and the -heap: - -- Non-heap alternatives to many standard library types are available. -- Special allocators to track memory behavior should be used to benchmark code. - -# Smart pointers - -The first thing to note are the "smart pointer" types. When you have data that must outlive the -scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these -types. - -The term [smart pointer](https://en.wikipedia.org/wiki/Smart_pointer) comes from C++, and while it's -closely linked to a general design pattern of -["Resource Acquisition Is Initialization"](https://en.cppreference.com/w/cpp/language/raii), we'll -use it here specifically to describe objects that are responsible for managing ownership of data -allocated on the heap. The smart pointers available in the `alloc` crate should look mostly -familiar: - -- [`Box`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html) -- [`Rc`](https://doc.rust-lang.org/alloc/rc/struct.Rc.html) -- [`Arc`](https://doc.rust-lang.org/alloc/sync/struct.Arc.html) -- [`Cow`](https://doc.rust-lang.org/alloc/borrow/enum.Cow.html) - -The [standard library](https://doc.rust-lang.org/std/) also defines some smart pointers to manage -heap objects, though more than can be covered here. Some examples are: - -- [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) -- [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) - -Finally, there is one ["gotcha"](https://www.merriam-webster.com/dictionary/gotcha): **cell types** -(like [`RefCell`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html)) look and behave -similarly, but **don't involve heap allocation**. The -[`core::cell` docs](https://doc.rust-lang.org/stable/core/cell/index.html) have more information. - -When a smart pointer is created, the data it is given is placed in heap memory and the location of -that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to -deallocate that memory (when a `Box` has -[gone out of scope](https://doc.rust-lang.org/stable/std/boxed/index.html) or a reference count -[goes to zero](https://doc.rust-lang.org/alloc/rc/index.html)), the heap space is reclaimed. We can -prove these types use heap memory by looking at code: - -```rust -use std::rc::Rc; -use std::sync::Arc; -use std::borrow::Cow; - -pub fn my_box() { - // Drop at assembly line 1640 - Box::new(0); -} - -pub fn my_rc() { - // Drop at assembly line 1650 - Rc::new(0); -} - -pub fn my_arc() { - // Drop at assembly line 1660 - Arc::new(0); -} - -pub fn my_cow() { - // Drop at assembly line 1672 - Cow::from("drop"); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/4AMQug) - -# Collections - -Collection types use heap memory because their contents have dynamic size; they will request more -memory [when needed](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve), and can -[release memory](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit) when it's -no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In -a way, **collections are smart pointers for many objects at a time**. Common types that fall under -this umbrella are [`Vec`](https://doc.rust-lang.org/stable/alloc/vec/struct.Vec.html), -[`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), and -[`String`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html) (not -[`str`](https://doc.rust-lang.org/std/primitive.str.html)). - -While collections store the objects they own in heap memory, _creating new collections will not -allocate on the heap_. This is a bit weird; if we call `Vec::new()`, the assembly shows a -corresponding call to `real_drop_in_place`: - -```rust -pub fn my_vec() { - // Drop in place at line 481 - Vec::::new(); -} -``` - --- [Compiler Explorer](https://godbolt.org/z/1WkNtC) - -But because the vector has no elements to manage, no calls to the allocator will ever be dispatched: - -```rust -use std::alloc::{GlobalAlloc, Layout, System}; -use std::sync::atomic::{AtomicBool, Ordering}; - -fn main() { - // Turn on panicking if we allocate on the heap - DO_PANIC.store(true, Ordering::SeqCst); - - // Interesting bit happens here - let x: Vec = Vec::new(); - drop(x); - - // Turn panicking back off, some deallocations occur - // after main as well. - DO_PANIC.store(false, Ordering::SeqCst); -} - -#[global_allocator] -static A: PanicAllocator = PanicAllocator; -static DO_PANIC: AtomicBool = AtomicBool::new(false); -struct PanicAllocator; - -unsafe impl GlobalAlloc for PanicAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if DO_PANIC.load(Ordering::SeqCst) { - panic!("Unexpected allocation."); - } - System.alloc(layout) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if DO_PANIC.load(Ordering::SeqCst) { - panic!("Unexpected deallocation."); - } - System.dealloc(ptr, layout); - } -} -``` - --- -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=831a297d176d015b1f9ace01ae416cc6) - -Other standard library types follow the same behavior; make sure to check out -[`HashMap::new()`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.new), -and [`String::new()`](https://doc.rust-lang.org/std/string/struct.String.html#method.new). - -# Heap Alternatives - -While it is a bit strange to speak of the stack after spending time with the heap, it's worth -pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by -other crates. If you have need of the functionality, but want to avoid allocating, there are -typically alternatives available. - -When it comes to some standard library smart pointers -([`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) and -[`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)), stack-based alternatives are -provided in crates like [parking_lot](https://crates.io/crates/parking_lot) and -[spin](https://crates.io/crates/spin). You can check out -[`lock_api::RwLock`](https://docs.rs/lock_api/0.1.5/lock_api/struct.RwLock.html), -[`lock_api::Mutex`](https://docs.rs/lock_api/0.1.5/lock_api/struct.Mutex.html), and -[`spin::Once`](https://mvdnes.github.io/rust-docs/spin-rs/spin/struct.Once.html) if you're in need -of synchronization primitives. - -[thread_id](https://crates.io/crates/thread-id) may be necessary if you're implementing an allocator -because [`thread::current().id()`](https://doc.rust-lang.org/std/thread/struct.ThreadId.html) uses a -[`thread_local!` structure](https://doc.rust-lang.org/stable/src/std/sys_common/thread_info.rs.html#17-36) -that needs heap allocation. - -# Tracing Allocators - -When writing performance-sensitive code, there's no alternative to measuring your code. If you -didn't write a benchmark, -[you don't care about it's performance](https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=263) -You should never rely on your instincts when -[a microsecond is an eternity](https://www.youtube.com/watch?v=NH1Tta7purM). - -Similarly, there's great work going on in Rust with allocators that keep track of what they're doing -(like [`alloc_counter`](https://crates.io/crates/alloc_counter)). When it comes to tracking heap -behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard -against future issues. diff --git a/_posts/2019-02-08-compiler-optimizations.md b/_posts/2019-02-08-compiler-optimizations.md deleted file mode 100644 index 4b8b385..0000000 --- a/_posts/2019-02-08-compiler-optimizations.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -layout: post -title: "Compiler Optimizations: What It's Done Lately" -description: "A lot. The answer is a lot." -category: -tags: [rust, understanding-allocations] ---- - -**Update 2019-02-10**: When debugging a -[related issue](https://gitlab.com/sio4/code/alloc-counter/issues/1), it was discovered that the -original code worked because LLVM optimized out the entire function, rather than just the allocation -segments. The code has been updated with proper use of -[`read_volatile`](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html), and a previous section -on vector capacity has been removed. - ---- - -Up to this point, we've been discussing memory usage in the Rust language by focusing on simple -rules that are mostly right for small chunks of code. We've spent time showing how those rules work -themselves out in practice, and become familiar with reading the assembly code needed to see each -memory type (global, stack, heap) in action. - -Throughout the series so far, we've put a handicap on the code. In the name of consistent and -understandable results, we've asked the compiler to pretty please leave the training wheels on. Now -is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the -Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them -do their job. - -Similar to -["What Has My Compiler Done For Me Lately?"](https://www.youtube.com/watch?v=bSkpMdDe4g4), we're -focusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll -still be looking at assembly code to understand what's going on, but it's important to mention -again: **please use automated tools like [alloc-counter](https://crates.io/crates/alloc_counter) to -double-check memory behavior if it's something you care about**. It's far too easy to mis-read -assembly in large code sections, you should always verify behavior if you care about memory usage. - -The guiding principal as we move forward is this: _optimizing compilers won't produce worse programs -than we started with._ There won't be any situations where stack allocations get moved to heap -allocations. There will, however, be an opera of optimization. - -# The Case of the Disappearing Box - -Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently -short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the -stack instead! The way this interacts with `#[inline]` attributes is a bit opaque, but the important -part is that LLVM can sometimes do better than the baseline Rust language: - -```rust -use std::alloc::{GlobalAlloc, Layout, System}; -use std::sync::atomic::{AtomicBool, Ordering}; - -pub fn cmp(x: u32) { - // Turn on panicking if we allocate on the heap - DO_PANIC.store(true, Ordering::SeqCst); - - // The compiler is able to see through the constant `Box` - // and directly compare `x` to 24 - assembly line 73 - let y = Box::new(24); - let equals = x == *y; - - // This call to drop is eliminated - drop(y); - - // Need to mark the comparison result as volatile so that - // LLVM doesn't strip out all the code. If `y` is marked - // volatile instead, allocation will be forced. - unsafe { std::ptr::read_volatile(&equals) }; - - // Turn off panicking, as there are some deallocations - // when we exit main. - DO_PANIC.store(false, Ordering::SeqCst); -} - -fn main() { - cmp(12) -} - -#[global_allocator] -static A: PanicAllocator = PanicAllocator; -static DO_PANIC: AtomicBool = AtomicBool::new(false); -struct PanicAllocator; - -unsafe impl GlobalAlloc for PanicAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if DO_PANIC.load(Ordering::SeqCst) { - panic!("Unexpected allocation."); - } - System.alloc(layout) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if DO_PANIC.load(Ordering::SeqCst) { - panic!("Unexpected deallocation."); - } - System.dealloc(ptr, layout); - } -} -``` - -## -- [Compiler Explorer](https://godbolt.org/z/BZ_Yp3) - -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4a765f753183d5b919f62c71d2109d5d) - -# Dr. Array or: How I Learned to Love the Optimizer - -Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping -out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if -you're not careful, they can make your benchmarks look -[impossibly good](https://www.youtube.com/watch?v=nXaxk27zwlk&feature=youtu.be&t=1199). In Rust, the -`black_box` function (implemented in both -[`libtest`](https://doc.rust-lang.org/1.1.0/test/fn.black_box.html) and -[`criterion`](https://docs.rs/criterion/0.2.10/criterion/fn.black_box.html)) will tell the compiler -to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up -running programs that previously caused errors: - -```rust -#[derive(Default)] -struct TwoFiftySix { - _a: [u64; 32] -} - -#[derive(Default)] -struct EightK { - _a: [TwoFiftySix; 32] -} - -#[derive(Default)] -struct TwoFiftySixK { - _a: [EightK; 32] -} - -#[derive(Default)] -struct EightM { - _a: [TwoFiftySixK; 32] -} - -pub fn main() { - // Normally this blows up because we can't reserve size on stack - // for the `EightM` struct. But because the compiler notices we - // never do anything with `_x`, it optimizes out the stack storage - // and the program completes successfully. - let _x = EightM::default(); -} -``` - -## -- [Compiler Explorer](https://godbolt.org/z/daHn7P) - -[Rust Playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4c253bf26072119896ab93c6ef064dc0) diff --git a/_posts/2019-02-09-summary.md b/_posts/2019-02-09-summary.md deleted file mode 100644 index dd7f06d..0000000 --- a/_posts/2019-02-09-summary.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: post -title: "Summary: What are the Allocation Rules?" -description: "A synopsis and reference." -category: -tags: [rust, understanding-allocations] ---- - -While there's a lot of interesting detail captured in this series, it's often helpful to have a -document that answers some "yes/no" questions. You may not care about what an `Iterator` looks like -in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust -will prioritize the fastest behavior it can, here are the rules for each memory type: - -**Heap Allocation**: - -- Smart pointers (`Box`, `Rc`, `Mutex`, etc.) allocate their contents in heap memory. -- Collections (`HashMap`, `Vec`, `String`, etc.) allocate their contents in heap memory. -- Some smart pointers in the standard library have counterparts in other crates that don't need heap - memory. If possible, use those. - -**Stack Allocation**: - -- Everything not using a smart pointer will be allocated on the stack. -- Structs, enums, iterators, arrays, and closures are all stack allocated. -- Cell types (`RefCell`) behave like smart pointers, but are stack-allocated. -- Inlining (`#[inline]`) will not affect allocation behavior for better or worse. -- Types that are marked `Copy` are guaranteed to have their contents stack-allocated. - -**Global Allocation**: - -- `const` is a fixed value; the compiler is allowed to copy it wherever useful. -- `static` is a fixed reference; the compiler will guarantee it is unique. - -![Container Sizes in Rust](/assets/images/2019-02-04-container-size.svg) -- -[Raph Levien](https://docs.google.com/presentation/d/1q-c7UAyrUlM-eZyTo1pd8SZ0qwA_wYxmPZVOQkoDmH4/edit?usp=sharing) diff --git a/_posts/2019-05-03-making-bread.md b/_posts/2019-05-03-making-bread.md deleted file mode 100644 index de794e0..0000000 --- a/_posts/2019-05-03-making-bread.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -layout: post -title: "Making Bread" -description: "...because I've got some free time now. 🍞" -category: -tags: [baking] ---- - -Having recently started my "gardening leave" between positions, I have some more personal time -available. I'm planning to stay productive, contributing to some open-source projects, but it also -occurred to me that despite [talking about](https://speice.io/2018/05/hello.html) bread pics, this -blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites -and Bytes"? - -Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on -some lighter material. I recently learned two critically important lessons: first, the temperature -of the dough when you put the yeast in makes a huge difference. - -Previously, when I wasn't paying attention to dough temperature: - -![Whole weat dough](/assets/images/2019-05-03-making-bread/whole-wheat-not-rising.jpg) - -Compared with what happens when I put the dough in the microwave for a defrost cycle because the -water I used wasn't warm enough: - -![White dough](/assets/images/2019-05-03-making-bread/white-dough-rising-before-fold.jpg) - -I mean, just look at the bubbles! - -![White dough with bubbles](/assets/images/2019-05-03-making-bread/white-dough-rising-after-fold.jpg) - -After shaping the dough, I've got two loaves ready: - -![Shaped loaves](/assets/images/2019-05-03-making-bread/shaped-loaves.jpg) - -Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from -drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the -bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot -to add the water and learned my second lesson: never add room-temperature water to a glass dish -that's currently at 500 degrees. - -![Shattered glass dish](/assets/images/2019-05-03-making-bread/shattered-glass.jpg) - -Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected -to be doing during my garden leave. - -In the end, the bread crust wasn't great, but the bread itself turned out pretty alright: - -![Baked bread](/assets/images/2019-05-03-making-bread/final-product.jpg) - -I've been writing a lot more during this break, so I'm looking forward to sharing that in the -future. In the mean-time, I'm planning on making a sandwich. diff --git a/_posts/2019-06-31-high-performance-systems.md b/_posts/2019-06-31-high-performance-systems.md deleted file mode 100644 index 23ef44b..0000000 --- a/_posts/2019-06-31-high-performance-systems.md +++ /dev/null @@ -1,296 +0,0 @@ ---- -layout: post -title: "On Building High Performance Systems" -description: "" -category: -tags: [] ---- - -**Update 2019-09-21**: Added notes on `isolcpus` and `systemd` affinity. - -Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is -made up of people who have access to secret techniques mortal developers could only dream of. There -had to be some secret art that could only be learned if one had an appropriately tragic backstory: - -kung-fu fight -> How I assumed HFT people learn their secret techniques - -How else do you explain people working on systems that complete the round trip of market data in to -orders out (a.k.a. tick-to-trade) consistently within -[750-800 nanoseconds](https://stackoverflow.com/a/22082528/1454178)? In roughly the time it takes a -computer to access -[main memory 8 times](https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html), -trading systems are capable of reading the market data packets, deciding what orders to send, doing -risk checks, creating new packets for exchange-specific protocols, and putting those packets on the -wire. - -Having now worked in the trading industry, I can confirm the developers aren't super-human; I've -made some simple mistakes at the very least. Instead, what shows up in public discussions is that -philosophy, not technique, separates high-performance systems from everything else. -Performance-critical systems don't rely on "this one cool C++ optimization trick" to make code fast -(though micro-optimizations have their place); there's a lot more to worry about than just the code -written for the project. - -The framework I'd propose is this: **If you want to build high-performance systems, focus first on -reducing performance variance** (reducing the gap between the fastest and slowest runs of the same -code), **and only look at average latency once variance is at an acceptable level**. - -Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20 -seconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes -a full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a -week is the same in each situation, but you're painfully aware of that minute when it happens. When -it comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds -doesn't mean much if there's a 100ms difference between your fastest and slowest runs. When -performance matters, you need to respond quickly _every time_, not just in aggregate. -High-performance systems should first optimize for time variance. Once you're consistent at the time -scale you care about, then focus on improving average time. - -This focus on variance shows up all the time in industry too (emphasis added in all quotes below): - -- In [marketing materials](https://business.nasdaq.com/market-tech/marketplaces/trading) for - NASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability - is highlighted in addition to instantaneous metrics: - - > Able to **consistently sustain** an order rate of over 100,000 orders per second at sub-40 - > microsecond average latency - -- The [Aeron](https://github.com/real-logic/aeron) message bus has this to say about performance: - - > Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and - > **most predictable latency possible** of any messaging system - -- The company PolySync, which is working on autonomous vehicles, - [mentions why](https://polysync.io/blog/session-types-for-hearty-codecs/) they picked their - specific messaging format: - - > In general, high performance is almost always desirable for serialization. But in the world of - > autonomous vehicles, **steady timing performance is even more important** than peak throughput. - > This is because safe operation is sensitive to timing outliers. Nobody wants the system that - > decides when to slam on the brakes to occasionally take 100 times longer than usual to encode - > its commands. - -- [Solarflare](https://solarflare.com/), which makes highly-specialized network hardware, points out - variance (jitter) as a big concern for - [electronic trading](https://solarflare.com/electronic-trading/): - > The high stakes world of electronic trading, investment banks, market makers, hedge funds and - > exchanges demand the **lowest possible latency and jitter** while utilizing the highest - > bandwidth and return on their investment. - -And to further clarify: we're not discussing _total run-time_, but variance of total run-time. There -are situations where it's not reasonably possible to make things faster, and you'd much rather be -consistent. For example, trading firms use -[wireless networks](https://sniperinmahwah.wordpress.com/2017/06/07/network-effects-part-i/) because -the speed of light through air is faster than through fiber-optic cables. There's still at _absolute -minimum_ a [~33.76 millisecond](http://tinyurl.com/y2vd7tn8) delay required to send data between, -say, -[Chicago and Tokyo](https://www.theice.com/market-data/connectivity-and-feeds/wireless/tokyo-chicago). -If a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a -trade occurs, there's a physical limit to how long that will take. In this situation, the focus is -on keeping variance of _additional processing_ to a minimum, since speed of light is the limiting -factor. - -So how does one go about looking for and eliminating performance variance? To tell the truth, I -don't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep -understanding of the entire technology stack, and (B) actually measuring system performance (though -(C) watching a lot of [CppCon](https://www.youtube.com/channel/UCMlGfpWw-RUdWX_JbLCukXg) videos for -inspiration never hurt). Even then, every project cares about performance to a different degree; you -may need to build an entire -[replica production system](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=3015) to -accurately benchmark at nanosecond precision, or you may be content to simply -[avoid garbage collection](https://www.youtube.com/watch?v=BD9cRbxWQx8&feature=youtu.be&t=1335) in -your Java code. - -Even though everyone has different needs, there are still common things to look for when trying to -isolate and eliminate variance. In no particular order, these are my focus areas when thinking about -high-performance systems: - -## Language-specific - -**Garbage Collection**: How often does garbage collection happen? When is it triggered? What are the -impacts? - -- [In Python](https://rushter.com/blog/python-garbage-collector/), individual objects are collected - if the reference count reaches 0, and each generation is collected if - `num_alloc - num_dealloc > gc_threshold` whenever an allocation happens. The GIL is acquired for - the duration of generational collection. -- Java has - [many](https://docs.oracle.com/en/java/javase/12/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE) - [different](https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573) - [collection](https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector-tuning.html#GUID-90E30ACA-8040-432E-B3A0-1E0440AB556A) - [algorithms](https://docs.oracle.com/en/java/javase/12/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0) - to choose from, each with different characteristics. The default algorithms (Parallel GC in Java - 8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms - ([ZGC](https://wiki.openjdk.java.net/display/zgc) and - [Shenandoah](https://wiki.openjdk.java.net/display/shenandoah)) are designed to keep "stop the - world" to a minimum by doing collection work in parallel. - -**Allocation**: Every language has a different way of interacting with "heap" memory, but the -principle is the same: running the allocator to allocate/deallocate memory takes time that can often -be put to better use. Understanding when your language interacts with the allocator is crucial, and -not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java -does (meaning potential GC pauses). Take time to understand heap behavior (I made a -[a guide for Rust](/2019/02/understanding-allocations-in-rust.html)), and look into alternative -allocators ([jemalloc](http://jemalloc.net/), -[tcmalloc](https://gperftools.github.io/gperftools/tcmalloc.html)) that might run faster than the -operating system default. - -**Data Layout**: How your data is arranged in memory matters; -[data-oriented design](https://www.youtube.com/watch?v=yy8jQgmhbAU) and -[cache locality](https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=1185) can have huge -impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have -guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't -make. [Cachegrind](http://valgrind.org/docs/manual/cg-manual.html) and kernel -[perf](https://perf.wiki.kernel.org/index.php/Main_Page) counters are both great for understanding -how performance relates to memory layout. - -**Just-In-Time Compilation**: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are -great because they optimize your program for how it's actually being used, rather than how a -compiler expects it to be used. However, there's a variance problem if the program stops executing -while waiting for translation from VM bytecode to native code. As a remedy, many languages support -ahead-of-time compilation in addition to the JIT versions -([CoreRT](https://github.com/dotnet/corert) in C# and [GraalVM](https://www.graalvm.org/) in Java). -On the other hand, LLVM supports -[Profile Guided Optimization](https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization), -which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing -apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT -compiler kicked in. - -**Programming Tricks**: These won't make or break performance, but can be useful in specific -circumstances. For example, C++ can use -[templates instead of branches](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=1206) -in critical sections. - -## Kernel - -Code you wrote is almost certainly not the _only_ code running on your hardware. There are many ways -the operating system interacts with your program, from interrupts to system calls, that are -important to watch for. These are written from a Linux perspective, but Windows does typically have -equivalent functionality. - -**Scheduling**: The kernel is normally free to schedule any process on any core, so it's important -to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, -limit the CPU cores that non-critical processes are allowed to run on by excluding cores from -scheduling -([`isolcpus`](https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re46.html) -kernel command-line option), or by setting the `init` process CPU affinity -([`systemd` example](https://access.redhat.com/solutions/2884991)). Second, set critical processes -to run on the isolated cores by setting the -[processor affinity](https://en.wikipedia.org/wiki/Processor_affinity) using -[taskset](https://linux.die.net/man/1/taskset). Finally, use -[`NO_HZ`](https://github.com/torvalds/linux/blob/master/Documentation/timers/NO_HZ.txt) or -[`chrt`](https://linux.die.net/man/1/chrt) to disable scheduling interrupts. Turning off -hyper-threading is also likely beneficial. - -**System calls**: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long -the I/O operation takes, these all trigger expensive -[system calls (syscalls)](https://en.wikipedia.org/wiki/System_call). To handle these, the CPU must -[context switch](https://en.wikipedia.org/wiki/Context_switch) to the kernel, let the kernel -operation complete, then context switch back to your program. We'd rather keep these -[to a minimum](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript) (see -timestamp 18:20). [Strace](https://linux.die.net/man/1/strace) is your friend for understanding when -and where syscalls happen. - -**Signal Handling**: Far less likely to be an issue, but signals do trigger a context switch if your -code has a handler registered. This will be highly dependent on the application, but you can -[block signals](https://www.linuxprogrammingblog.com/all-about-linux-signals?page=show#Blocking_signals) -if it's an issue. - -**Interrupts**: System interrupts are how devices connected to your computer notify the CPU that -something has happened. The CPU will then choose a processor core to pause and context switch to the -OS to handle the interrupt. Make sure that -[SMP affinity](http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux) is -set so that interrupts are handled on a CPU core not running the program you care about. - -**[NUMA](https://www.kernel.org/doc/html/latest/vm/numa.html)**: While NUMA is good at making -multi-cell systems transparent, there are variance implications; if the kernel moves a process -across nodes, future memory accesses must wait for the controller on the original node. Use -[numactl](https://linux.die.net/man/8/numactl) to handle memory-/cpu-cell pinning so this doesn't -happen. - -## Hardware - -**CPU Pipelining/Speculation**: Speculative execution in modern processors gave us vulnerabilities -like Spectre, but it also gave us performance improvements like -[branch prediction](https://stackoverflow.com/a/11227902/1454178). And if the CPU mis-speculates -your code, there's variance associated with rewind and replay. While the compiler knows a lot about -how your CPU [pipelines instructions](https://youtu.be/nAbCKa0FzjQ?t=4467), code can be -[structured to help](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=755) the branch -predictor. - -**Paging**: For most systems, virtual memory is incredible. Applications live in their own worlds, -and the CPU/[MMU](https://en.wikipedia.org/wiki/Memory_management_unit) figures out the details. -However, there's a variance penalty associated with memory paging and caching; if you access more -memory pages than the [TLB](https://en.wikipedia.org/wiki/Translation_lookaside_buffer) can store, -you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an -issue, but using [huge pages](https://blog.pythian.com/performance-tuning-hugepages-in-linux/) can -reduce TLB burdens. Alternately, running applications in a hypervisor like -[Jailhouse](https://github.com/siemens/jailhouse) allows one to skip virtual memory entirely, but -this is probably more work than the benefits are worth. - -**Network Interfaces**: When more than one computer is involved, variance can go up dramatically. -Tuning kernel -[network parameters](https://github.com/leandromoreira/linux-network-performance-parameters) may be -helpful, but modern systems more frequently opt to skip the kernel altogether with a technique -called [kernel bypass](https://blog.cloudflare.com/kernel-bypass/). This typically requires -specialized hardware and [drivers](https://www.openonload.org/), but even industries like -[telecom](https://www.bbc.co.uk/rd/blog/2018-04-high-speed-networking-open-source-kernel-bypass) are -finding the benefits. - -## Networks - -**Routing**: There's a reason financial firms are willing to pay -[millions of euros](https://sniperinmahwah.wordpress.com/2019/03/26/4-les-moeres-english-version/) -for rights to a small plot of land - having a straight-line connection from point A to point B means -the path their data takes is the shortest possible. In contrast, there are currently 6 computers in -between me and Google, but that may change at any moment if my ISP realizes a -[more efficient route](https://en.wikipedia.org/wiki/Border_Gateway_Protocol) is available. Whether -it's using -[research-quality equipment](https://sniperinmahwah.wordpress.com/2018/05/07/shortwave-trading-part-i-the-west-chicago-tower-mystery/) -for shortwave radio, or just making sure there's no data inadvertently going between data centers, -routing matters. - -**Protocol**: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, -and congestion control all built in. But these attributes make the most sense when networking -infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the -setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may -make sense in these contexts as it avoids the chatter needed to track connection state, and -[gap-fill](https://iextrading.com/docs/IEX%20Transport%20Specification.pdf) -[strategies](http://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/moldudp64.pdf) -can handle the rest. - -**Switching**: Many routers/switches handle packets using "store-and-forward" behavior: wait for the -whole packet, validate checksums, and then send to the next device. In variance terms, the time -needed to move data between two nodes is proportional to the size of that data; the switch must -"store" all data before it can calculate checksums and "forward" to the next node. With -["cut-through"](https://www.networkworld.com/article/2241573/latency-and-jitter--cut-through-design-pays-off-for-arista--blade.html) -designs, switches will begin forwarding data as soon as they know where the destination is, -checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter -the size. - -# Final Thoughts - -High-performance systems, regardless of industry, are not magical. They do require extreme precision -and attention to detail, but they're designed, built, and operated by regular people, using a lot of -tools that are publicly available. Interested in seeing how context switching affects performance of -your benchmarks? `taskset` should be installed in all modern Linux distributions, and can be used to -make sure the OS never migrates your process. Curious how often garbage collection triggers during a -crucial operation? Your language of choice will typically expose details of its operations -([Python](https://docs.python.org/3/library/gc.html), -[Java](https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#DebuggingOptions)). -Want to know how hard your program is stressing the TLB? Use `perf record` and look for -`dtlb_load_misses.miss_causes_a_walk`. - -Two final guiding questions, then: first, before attempting to apply some of the technology above to -your own systems, can you first identify -[where/when you care](http://wiki.c2.com/?PrematureOptimization) about "high-performance"? As an -example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable -effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are -they being designed in a way that's actually helpful? Tools like -[Criterion](http://www.serpentine.com/criterion/) (also in -[Rust](https://github.com/bheisler/criterion.rs)) and Google's -[Benchmark](https://github.com/google/benchmark) output not only average run time, but variance as -well; your benchmarking environment is subject to the same concerns your production environment is. - -Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. -Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate -it; once that's at an acceptable level, then optimize for speed. diff --git a/_posts/2019-09-28-binary-format-shootout.md b/_posts/2019-09-28-binary-format-shootout.md deleted file mode 100644 index 675dc37..0000000 --- a/_posts/2019-09-28-binary-format-shootout.md +++ /dev/null @@ -1,263 +0,0 @@ ---- -layout: post -title: "Binary Format Shootout" -description: "Cap'n Proto vs. Flatbuffers vs. SBE" -category: -tags: [rust] ---- - -I've found that in many personal projects, -[analysis paralysis](https://en.wikipedia.org/wiki/Analysis_paralysis) is particularly deadly. -Making good decisions in the beginning avoids pain and suffering later; if extra research prevents -future problems, I'm happy to continue ~~procrastinating~~ researching indefinitely. - -So let's say you're in need of a binary serialization format. Data will be going over the network, -not just in memory, so having a schema document and code generation is a must. Performance is -crucial, so formats that support zero-copy de/serialization are given priority. And the more -languages supported, the better; I use Rust, but can't predict what other languages this could -interact with. - -Given these requirements, the candidates I could find were: - -1. [Cap'n Proto](https://capnproto.org/) has been around the longest, and is the most established -2. [Flatbuffers](https://google.github.io/flatbuffers/) is the newest, and claims to have a simpler - encoding -3. [Simple Binary Encoding](https://github.com/real-logic/simple-binary-encoding) has the simplest - encoding, but the Rust implementation is unmaintained - -Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably -fast, and polyglot support. But how do you actually pick one? It's impossible to know what issues -will follow that choice, so I tend to avoid commitment until the last possible moment. - -Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a -small proof-of-concept system in each format and pit them against each other. All code can be found -in the [repository](https://github.com/speice-io/marketdata-shootout) for this post. - -We'll discuss more in detail, but a quick preview of the results: - -- Cap'n Proto: Theoretically performs incredibly well, the implementation had issues -- Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises -- SBE: Best median and worst-case performance, but the message structure has a limited feature set - -# Prologue: Binary Parsing with Nom - -Our benchmark system will be a simple data processor; given depth-of-book market data from -[IEX](https://iextrading.com/trading/market-data/#deep), serialize each message into the schema -format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. -This test isn't complex, but is representative of the project I need a binary format for. - -But before we make it to that point, we have to actually read in the market data. To do so, I'm -using a library called [`nom`](https://github.com/Geal/nom). Version 5.0 was recently released and -brought some big changes, so this was an opportunity to build a non-trivial program and get -familiar. - -If you don't already know about `nom`, it's a "parser generator". By combining different smaller -parsers, you can assemble a parser to handle complex structures without writing tedious code by -hand. For example, when parsing -[PCAP files](https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#rfc.section.3.3): - -``` - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +---------------------------------------------------------------+ - 0 | Block Type = 0x00000006 | - +---------------------------------------------------------------+ - 4 | Block Total Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - 8 | Interface ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -12 | Timestamp (High) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -16 | Timestamp (Low) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -20 | Captured Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -24 | Packet Len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Packet Data | - | ... | -``` - -...you can build a parser in `nom` that looks like -[this](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/parsers.rs#L59-L93): - -```rust -const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00]; -pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> { - let ( - remaining, - ( - block_type, - block_len, - interface_id, - timestamp_high, - timestamp_low, - captured_len, - packet_len, - ), - ) = tuple(( - tag(ENHANCED_PACKET), - le_u32, - le_u32, - le_u32, - le_u32, - le_u32, - le_u32, - ))(input)?; - - let (remaining, packet_data) = take(captured_len)(remaining)?; - Ok((remaining, packet_data)) -} -``` - -While this example isn't too interesting, more complex formats (like IEX market data) are where -[`nom` really shines](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/iex.rs). - -Ultimately, because the `nom` code in this shootout was the same for all formats, we're not too -interested in its performance. Still, it's worth mentioning that building the market data parser was -actually fun; I didn't have to write tons of boring code by hand. - -# Part 1: Cap'n Proto - -Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried -because of how long it has supported Rust (thanks to [dwrensha](https://github.com/dwrensha) for -maintaining the Rust port since -[2014!](https://github.com/capnproto/capnproto-rust/releases/tag/rustc-0.10)). However, I had a ton -of performance concerns once I started using it. - -To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the -heap to hold the message content, but because builders -[can't be re-used](https://github.com/capnproto/capnproto-rust/issues/111), we have to allocate a -new buffer for every single message. I was able to work around this with a -[special builder](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/capnp_runner.rs#L17-L51) -that could re-use the buffer, but it required reading through Cap'n Proto's -[benchmarks](https://github.com/capnproto/capnproto-rust/blob/master/benchmark/benchmark.rs#L124-L156) -to find an example, and used -[`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) to bypass Rust's borrow -checker. - -The process of reading messages was better, but still had issues. Cap'n Proto has two message -encodings: a ["packed"](https://capnproto.org/encoding.html#packing) representation, and an -"unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into -before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't -able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n -Proto shines; its main selling point is that there's [no decoding step](https://capnproto.org/). -However, accomplishing zero-copy deserialization required code in the private API -([since fixed](https://github.com/capnproto/capnproto-rust/issues/148)), and we allocate a vector on -every read for the segment table. - -In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too -many issues for me to feel comfortable using it long-term. - -# Part 2: Flatbuffers - -This is the new kid on the block. After a -[first attempt](https://github.com/google/flatbuffers/pull/3894) didn't pan out, official support -was [recently launched](https://github.com/google/flatbuffers/pull/4898). Flatbuffers intends to -address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The -difference is that Flatbuffers claims to have a simpler wire format and -[more flexibility](https://google.github.io/flatbuffers/flatbuffers_benchmarks.html). - -On the whole, I enjoyed using Flatbuffers; the [tooling](https://crates.io/crates/flatc-rust) is -nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, -there were still some issues. - -First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats -like the following: - -``` -table Message { - symbol: string; -} -table MultiMessage { - messages:[Message]; -} -``` - -We want to create a `MultiMessage` which contains a vector of `Message`, and each `Message` itself -contains a vector (the `string` type). I was able to work around this by -[caching `Message` elements](https://github.com/speice-io/marketdata-shootout/blob/e9d07d148bf36a211a6f86802b313c4918377d1b/src/flatbuffers_runner.rs#L83) -in a `SmallVec` before building the final `MultiMessage`, but it was a painful process that I -believe contributed to poor serialization performance. - -Second, streaming support in Flatbuffers seems to be something of an -[afterthought](https://github.com/google/flatbuffers/issues/3898). Where Cap'n Proto in Rust handles -reading messages from a stream as part of the API, Flatbuffers just sticks a `u32` at the front of -each message to indicate the size. Not specifically a problem, but calculating message size without -that tag is nigh on impossible. - -Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform -well. - -# Part 3: Simple Binary Encoding - -Support for SBE was added by the author of one of my favorite -[Rust blog posts](https://web.archive.org/web/20190427124806/https://polysync.io/blog/session-types-for-hearty-codecs/). -I've [talked previously]({% post_url 2019-06-31-high-performance-systems %}) about how important -variance is in high-performance systems, so it was encouraging to read about a format that -[directly addressed](https://github.com/real-logic/simple-binary-encoding/wiki/Why-Low-Latency) my -concerns. SBE has by far the simplest binary format, but it does make some tradeoffs. - -Both Cap'n Proto and Flatbuffers use [message offsets](https://capnproto.org/encoding.html#structs) -to handle variable-length data, [unions](https://capnproto.org/language.html#unions), and various -other features. In contrast, messages in SBE are essentially -[just structs](https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-samples/src/main/resources/example-schema.xml); -variable-length data is supported, but there's no union type. - -As mentioned in the beginning, the Rust port of SBE works well, but is -[essentially unmaintained](https://users.rust-lang.org/t/zero-cost-abstraction-frontier-no-copy-low-allocation-ordered-decoding/11515/9). -However, if you don't need union types, and can accept that schemas are XML documents, it's still -worth using. SBE's implementation had the best streaming support of all formats I tested, and -doesn't trigger allocation during de/serialization. - -# Results - -After building a test harness -[for](https://github.com/speice-io/marketdata-shootout/blob/master/src/capnp_runner.rs) -[each](https://github.com/speice-io/marketdata-shootout/blob/master/src/flatbuffers_runner.rs) -[format](https://github.com/speice-io/marketdata-shootout/blob/master/src/sbe_runner.rs), it was -time to actually take them for a spin. I used -[this script](https://github.com/speice-io/marketdata-shootout/blob/master/run_shootout.sh) to run -the benchmarks, and the raw results are -[here](https://github.com/speice-io/marketdata-shootout/blob/master/shootout.csv). All data reported -below is the average of 10 runs on a single day of IEX data. Results were validated to make sure -that each format parsed the data correctly. - -## Serialization - -This test measures, on a -[per-message basis](https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L268-L272), -how long it takes to serialize the IEX message into the desired format and write to a pre-allocated -buffer. - -| Schema | Median | 99th Pctl | 99.9th Pctl | Total | -| :------------------- | :----- | :-------- | :---------- | :----- | -| Cap'n Proto Packed | 413ns | 1751ns | 2943ns | 14.80s | -| Cap'n Proto Unpacked | 273ns | 1828ns | 2836ns | 10.65s | -| Flatbuffers | 355ns | 2185ns | 3497ns | 14.31s | -| SBE | 91ns | 1535ns | 2423ns | 3.91s | - -## Deserialization - -This test measures, on a -[per-message basis](https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L294-L298), -how long it takes to read the previously-serialized message and perform some basic aggregation. The -aggregation code is the same for each format, so any performance differences are due solely to the -format implementation. - -| Schema | Median | 99th Pctl | 99.9th Pctl | Total | -| :------------------- | :----- | :-------- | :---------- | :----- | -| Cap'n Proto Packed | 539ns | 1216ns | 2599ns | 18.92s | -| Cap'n Proto Unpacked | 366ns | 737ns | 1583ns | 12.32s | -| Flatbuffers | 173ns | 421ns | 1007ns | 6.00s | -| SBE | 116ns | 286ns | 659ns | 4.05s | - -# Conclusion - -Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" -type isn't important to me, I can be confident that SBE best addresses my needs. - -While SBE was the fastest in terms of both median and worst-case performance, its worst case -performance was proportionately far higher than any other format. It seems to be that -de/serialization time scales with message size, but I'll need to do some more research to understand -what exactly is going on. diff --git a/_posts/2019-12-14-release-the-gil.md b/_posts/2019-12-14-release-the-gil.md deleted file mode 100644 index 00b47a6..0000000 --- a/_posts/2019-12-14-release-the-gil.md +++ /dev/null @@ -1,370 +0,0 @@ ---- -layout: post -title: "Release the GIL" -description: "Strategies for Parallelism in Python" -category: -tags: [python] ---- - -Complaining about the [Global Interpreter Lock](https://wiki.python.org/moin/GlobalInterpreterLock) -(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision -made before multi-core CPU's were widely available, but the fact that it's still around indicates -that it generally works [Good](https://wiki.c2.com/?PrematureOptimization) -[Enough](https://wiki.c2.com/?YouArentGonnaNeedIt). Besides, there are simple and effective -workarounds; it's not hard to start a -[new process](https://docs.python.org/3/library/multiprocessing.html) and use message passing to -synchronize code running in parallel. - -Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of -asynchronicity and _M:N_ threading, Python seems lacking. The ideal scenario is to take advantage of -both Python's productivity and the modern CPU's parallel capabilities. - -Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes -Python a nice language to start with. Bear in mind: these are just the tools, no claim is made about -whether it's a good idea to use them. Very often, unlocking the GIL is an -[XY problem](https://en.wikipedia.org/wiki/XY_problem); you want application performance, and the -GIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at -the expense of project complexity; messing with the GIL is ultimately messing with Python's memory -model. - -```python -%load_ext Cython -from numba import jit - -N = 1_000_000_000 -``` - -# Cython - -Put simply, [Cython](https://cython.org/) is a programming language that looks a lot like Python, -gets [transpiled](https://en.wikipedia.org/wiki/Source-to-source_compiler) to C/C++, and integrates -well with the [CPython](https://en.wikipedia.org/wiki/CPython) API. It's great for building Python -wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And -when it comes to managing the GIL, there are two special features: - -- The `nogil` - [function annotation](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#declaring-a-function-as-callable-without-the-gil) - asserts that a Cython function is safe to use without the GIL, and compilation will fail if it - interacts with Python in an unsafe manner -- The `with nogil` - [context manager](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#releasing-the-gil) - explicitly unlocks the CPython GIL while active - -Whenever Cython code runs inside a `with nogil` block on a separate thread, the Python interpreter -is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that -demonstrates this principle in action: - -```python -%%cython - -# Annotating a function with `nogil` indicates only that it is safe -# to call in a `with nogil` block. It *does not* release the GIL. -cdef unsigned long fibonacci(unsigned long n) nogil: - if n <= 1: - return n - - cdef unsigned long a = 0, b = 1, c = 0 - - c = a + b - for _i in range(2, n): - a = b - b = c - c = a + b - - return c - - -def cython_nogil(unsigned long n): - # Explicitly release the GIL while running `fibonacci` - with nogil: - value = fibonacci(n) - - return value - - -def cython_gil(unsigned long n): - # Because the GIL is not explicitly released, it implicitly - # remains acquired when running the `fibonacci` function - return fibonacci(n) -``` - -First, let's time how long it takes Cython to calculate the billionth Fibonacci number: - -```python -%%time -_ = cython_gil(N); -``` - ->
-> CPU times: user 365 ms, sys: 0 ns, total: 365 ms
-> Wall time: 372 ms
-> 
- -```python -%%time -_ = cython_nogil(N); -``` - ->
-> CPU times: user 381 ms, sys: 0 ns, total: 381 ms
-> Wall time: 388 ms
-> 
- -Both versions (with and without GIL) take effectively the same amount of time to run. Even when -running this calculation in parallel on separate threads, it is expected that the run time will -double because only one thread can be active at a time: - -```python -%%time -from threading import Thread - -# Create the two threads to run on -t1 = Thread(target=cython_gil, args=[N]) -t2 = Thread(target=cython_gil, args=[N]) -# Start the threads -t1.start(); t2.start() -# Wait for the threads to finish -t1.join(); t2.join() -``` - ->
-> CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms
-> Wall time: 645 ms
-> 
- -However, if the first thread releases the GIL, the second thread is free to acquire it and run in -parallel: - -```python -%%time - -t1 = Thread(target=cython_nogil, args=[N]) -t2 = Thread(target=cython_gil, args=[N]) -t1.start(); t2.start() -t1.join(); t2.join() -``` - ->
-> CPU times: user 717 ms, sys: 372 µs, total: 718 ms
-> Wall time: 358 ms
-> 
- -Because `user` time represents the sum of processing time on all threads, it doesn't change much. -The ["wall time"](https://en.wikipedia.org/wiki/Elapsed_real_time) has been cut roughly in half -because each function is running simultaneously. - -Keep in mind that the **order in which threads are started** makes a difference! - -```python -%%time - -# Note that the GIL-locked version is started first -t1 = Thread(target=cython_gil, args=[N]) -t2 = Thread(target=cython_nogil, args=[N]) -t1.start(); t2.start() -t1.join(); t2.join() -``` - ->
-> CPU times: user 667 ms, sys: 0 ns, total: 667 ms
-> Wall time: 672 ms
-> 
- -Even though the second thread releases the GIL while running, it can't start until the first has -completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads. - -Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the -**interpreter**, not just the thread attempting the unlock: - -```python -%%cython - -cdef int cython_recurse(int n) nogil: - if n <= 0: - return 0 - - with nogil: - return cython_recurse(n - 1) - -cython_recurse(2) -``` - ->
-> Fatal Python error: PyEval_SaveThread: NULL tstate
-> 
-> Thread 0x00007f499effd700 (most recent call first):
->   File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run
->   File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner
->   File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap
-> 
- -In practice, avoiding this issue is simple. First, `nogil` functions probably shouldn't contain -`with nogil` blocks. Second, Cython can -[conditionally acquire/release](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#conditional-acquiring-releasing-the-gil) -the GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for -[external C code](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil) -contains more detail on how to safely manage the GIL. - -To conclude: use Cython's `nogil` annotation to assert that functions are safe for calling when the -GIL is unlocked, and `with nogil` to actually unlock the GIL and run those functions. - -# Numba - -Like Cython, [Numba](https://numba.pydata.org/) is a "compiled Python." Where Cython works by -compiling a Python-like language to C/C++, Numba compiles Python bytecode _directly to machine code_ -at runtime. Behavior is controlled with a special `@jit` decorator; calling a decorated function -first compiles it to machine code before running. Calling the function a second time re-uses that -machine code unless the argument types have changed. - -Numba works best when a `nopython=True` argument is added to the `@jit` decorator; functions -compiled in [`nopython`](http://numba.pydata.org/numba-doc/latest/user/jit.html?#nopython) mode -avoid the CPython API and have performance comparable to C. Further, adding `nogil=True` to the -`@jit` decorator unlocks the GIL while that function is running. Note that `nogil` and `nopython` -are separate arguments; while it is necessary for code to be compiled in `nopython` mode in order to -release the lock, the GIL will remain locked if `nogil=False` (the default). - -Let's repeat the same experiment, this time using Numba instead of Cython: - -```python -# The `int` type annotation is only for humans and is ignored -# by Numba. -@jit(nopython=True, nogil=True) -def numba_nogil(n: int) -> int: - if n <= 1: - return n - - a = 0 - b = 1 - - c = a + b - for _i in range(2, n): - a = b - b = c - c = a + b - - return c - - -# Run using `nopython` mode to receive a performance boost, -# but GIL remains locked due to `nogil=False` by default. -@jit(nopython=True) -def numba_gil(n: int) -> int: - if n <= 1: - return n - - a = 0 - b = 1 - - c = a + b - for _i in range(2, n): - a = b - b = c - c = a + b - - return c - - -# Call each function once to force compilation; we don't want -# the timing statistics to include how long it takes to compile. -numba_nogil(N) -numba_gil(N); -``` - -We'll perform the same tests as above; first, figure out how long it takes the function to run: - -```python -%%time -_ = numba_gil(N) -``` - ->
-> CPU times: user 253 ms, sys: 258 µs, total: 253 ms
-> Wall time: 251 ms
-> 
- - -Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be -effectively identical after compilation. - - -When running two GIL-locked threads, the result (as expected) takes around twice as long to compute: - -```python -%%time -t1 = Thread(target=numba_gil, args=[N]) -t2 = Thread(target=numba_gil, args=[N]) -t1.start(); t2.start() -t1.join(); t2.join() -``` - ->
-> CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms
-> Wall time: 541 ms
-> 
- -But if the GIL-unlocking thread starts first, both threads run in parallel: - -```python -%%time -t1 = Thread(target=numba_nogil, args=[N]) -t2 = Thread(target=numba_gil, args=[N]) -t1.start(); t2.start() -t1.join(); t2.join() -``` - ->
-> CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms
-> Wall time: 279 ms
-> 
- -Just like Cython, starting the GIL-locked thread first leads to poor performance: - -```python -%%time -t1 = Thread(target=numba_gil, args=[N]) -t2 = Thread(target=numba_nogil, args=[N]) -t1.start(); t2.start() -t1.join(); t2.join() -``` - ->
-> CPU times: user 524 ms, sys: 0 ns, total: 524 ms
-> Wall time: 522 ms
-> 
- -Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; -recursively calling `@jit(nogil=True)` functions is perfectly safe: - -```python -from numba import jit - -@jit(nopython=True, nogil=True) -def numba_recurse(n: int) -> int: - if n <= 0: - return 0 - - return numba_recurse(n - 1) - -numba_recurse(2); -``` - -# Conclusion - -Before finishing, it's important to address pain points that will show up if these techniques are -used in a more realistic project: - -First, code running in a GIL-free context will likely also need non-trivial data structures; -GIL-free functions aren't useful if they're constantly interacting with Python objects whose access -requires the GIL. Cython provides -[extension types](http://docs.cython.org/en/latest/src/tutorial/cdef_classes.html) and Numba -provides a [`@jitclass`](https://numba.pydata.org/numba-doc/dev/user/jitclass.html) decorator to -address this need. - -Second, building and distributing applications that make use of Cython/Numba can be complicated. -Cython packages require running the compiler, (potentially) linking/packaging external dependencies, -and distributing a binary wheel. Numba is generally simpler because the code being distributed is -pure Python, but can be tricky since errors aren't detected until runtime. - -Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba -provide tools to directly manage the GIL when appropriate. This enables true parallelism (not just -[concurrency](https://stackoverflow.com/a/1050257)) that is impossible in vanilla Python. diff --git a/_posts/2022-11-20-webpack-industrial-complex.md b/_posts/2022-11-20-webpack-industrial-complex.md deleted file mode 100644 index 33fe67a..0000000 --- a/_posts/2022-11-20-webpack-industrial-complex.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -layout: post -title: "The webpack industrial complex" -description: "Reflections on a new project" -category: -tags: [webpack, react, vite] ---- - -This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW). - -The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process. - -## Starting strong - -The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser." - -Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an `onEvent` handler and a function easy. - -Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical." - -## Continuing on - -Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead? - -The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API [was missing](https://github.com/microsoft/TypeScript/issues/28308). After searching out Github issues and (unsuccessfully) tweaking the `.tsconfig` settings, I settled on installing a package and moving on. - -The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use `new URL(, import.meta.url)` and it worked! Well, kind of: - -![Browser error](/assets/images/2022-11-20-video_mp2t.png) - -That file has the audio processor code, so why does it get served with `Content-Type: video/mp2t`? - -## Floundering about - -Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to [just use JavaScript](https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474) and stuck by the original TypeScript requirement. - -I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package. - -I tried three different CRA tools - `react-app-rewired`, `craco`, `customize-react-app` - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well. - -I tried changing the webpack configuration: using [new](https://github.com/webpack/webpack/issues/11543#issuecomment-917673256) [loaders](https://github.com/popelenkow/worker-url), setting [asset rules](https://github.com/webpack/webpack/discussions/14093#discussioncomment-1257149), even [changing how webpack detects worker resources](https://github.com/webpack/webpack/issues/11543#issuecomment-826897590). In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up. - -I tried so many application frameworks. Next.js looked like a good candidate, but added its own [bespoke webpack complexity](https://github.com/vercel/next.js/issues/24907) to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work. - -## Learning and reflecting - -I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned. - -For myself: - -- I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work -- I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts - -For the tools: - -- Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity -- Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaks -- There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it - -In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down. \ No newline at end of file diff --git a/archive/index.html b/archive/index.html new file mode 100644 index 0000000..fc96043 --- /dev/null +++ b/archive/index.html @@ -0,0 +1 @@ +Archive | The Old Speice Guy \ No newline at end of file diff --git a/assets/css/fonts.css b/assets/css/fonts.css deleted file mode 100644 index e07ecfc..0000000 --- a/assets/css/fonts.css +++ /dev/null @@ -1,15 +0,0 @@ -@font-face { - font-family: 'JetBrains Mono'; - src: url('/assets/font/JetBrainsMono-Regular.woff2') format('woff2'), - url('/assets/font/JetBrainsMono-Regular.woff') format('woff'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'Lato'; - src: url('/assets/font/lato-regular-webfont.woff2') format('woff2'), - url('/assets/font/lato-regular-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} \ No newline at end of file diff --git a/assets/css/style.scss b/assets/css/style.scss deleted file mode 100644 index ea280e2..0000000 --- a/assets/css/style.scss +++ /dev/null @@ -1,119 +0,0 @@ ---- ---- - -// Import the theme rules -@import "theme"; - -body { - max-width: 100%; - overflow-x: hidden; - font-family: 'Lato', sans-serif; -} - -.navbar { - color: $gray; -} - -.separator { - margin-right: .45rem; - margin-left: .25rem; - color: #000; - &:after { - content: '\00a0/'; - } -} - -header { - padding-top: 80px; - padding-bottom: 0; -}; - -header h1,h2 { - color: #000; -} - -.post-description { - color: #555; -} - -.post-container a { - color: #555; - border-bottom-color: $gray; - border-bottom-style: dotted; - border-bottom-width: 1px; - - position: relative; - display: inline-block; - padding: 1px 1px; - transition: color ease 0.3s; - - &::after { - content: ''; - position: absolute; - z-index: -1; - width: 100%; - height: 0%; - left: 0; - bottom: 0; - background-color: $gray; - transition: all ease 0.3s; - } - - &:hover { - color: #fff; - border-bottom-style: solid; - &::after { - height: 100%; - } - } -} - -body pre { - font-size: 15px; -} - -pre.highlight, code { - font-family: 'JetBrains Mono', monospace; -} - -div.highlighter-rouge { - // Default theme uses `width: 100vw`, which while cool, does cause the page - // to exceed screen width and trigger horizontal scrolling. No bueno. - width: 99vw; -} - -.post-date { - // On the front page, make sure titles don't force wrapping the date box content - text-align: right; - white-space: nowrap; -} - -blockquote { - color: #555; - right: 100px; - margin-left: 0; - padding-left: 1.8rem; - border-left: 5px solid $gray; -} - -.post-nav { - /* Insert your custom styling here. Example: - - font-size: 14px; - */ - display: flex; - margin-top: 1em; - margin-bottom: 1em; -} -.post-nav div { - /* flex-grow, flex-shrink, flex-basis */ - flex: 1 1 0; -} -.post-nav-next { - text-align: right; -} - -th, td { - border-bottom: 1px solid $gray; - padding: 0.75em; -} diff --git a/assets/css/styles.ae6ff4a3.css b/assets/css/styles.ae6ff4a3.css new file mode 100644 index 0000000..9ed0982 --- /dev/null +++ b/assets/css/styles.ae6ff4a3.css @@ -0,0 +1 @@ +:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-500:var(--ifm-color-gray-500);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:transparent;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:.4rem;--ifm-hover-overlay:rgba(0,0,0,.05);--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:.2s;--ifm-transition-slow:.4s;--ifm-transition-timing-default:cubic-bezier(.08,.52,.52,1);--ifm-global-shadow-lw:0 1px 2px 0 rgba(0,0,0,.1);--ifm-global-shadow-md:0 5px 40px rgba(0,0,0,.2);--ifm-global-shadow-tl:0 12px 28px 0 rgba(0,0,0,.2),0 2px 4px 0 rgba(0,0,0,.1);--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:.1rem;--ifm-code-padding-vertical:.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:.875rem;--ifm-h6-font-size:.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:.75rem;--ifm-table-background:transparent;--ifm-table-stripe-background:rgba(0,0,0,.03);--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:.8rem;--ifm-breadcrumb-padding-vertical:.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url("data:image/svg+xml;utf8,");--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-color:var(--ifm-font-color-base-inverse);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:.5rem;--ifm-toc-padding-horizontal:.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:.75rem;--ifm-menu-link-padding-vertical:.375rem;--ifm-menu-link-sublist-icon:url("data:image/svg+xml;utf8,");--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:.75rem;--ifm-navbar-item-padding-vertical:.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-hover-color:var(--ifm-color-primary);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url("data:image/svg+xml;utf8,");--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem}*{box-sizing:border-box}html{background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base)var(--ifm-font-family-base);-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}body{word-wrap:break-word;margin:0}iframe{color-scheme:normal;border:0}.container{max-width:var(--ifm-container-width);padding:0 var(--ifm-spacing-horizontal);width:100%;margin:0 auto}.container--fluid{max-width:inherit}.row{margin:0 calc(var(--ifm-spacing-horizontal)*-1);flex-wrap:wrap;display:flex}.row--no-gutters{margin-left:0;margin-right:0}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;max-width:var(--ifm-col-width);padding:0 var(--ifm-spacing-horizontal);flex:1 0;width:100%;margin-left:0}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:calc(1/12*100%)}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:calc(2/12*100%)}.col--offset-2{margin-left:16.6667%}.col--3{--ifm-col-width:calc(3/12*100%)}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:calc(4/12*100%)}.col--offset-4{margin-left:33.3333%}.col--5{--ifm-col-width:calc(5/12*100%)}.col--offset-5{margin-left:41.6667%}.col--6{--ifm-col-width:calc(6/12*100%)}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:calc(7/12*100%)}.col--offset-7{margin-left:58.3333%}.col--8{--ifm-col-width:calc(8/12*100%)}.col--offset-8{margin-left:66.6667%}.col--9{--ifm-col-width:calc(9/12*100%)}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:calc(10/12*100%)}.col--offset-10{margin-left:83.3333%}.col--11{--ifm-col-width:calc(11/12*100%)}.col--offset-11{margin-left:91.6667%}.col--12{--ifm-col-width:calc(12/12*100%)}.col--offset-12{margin-left:100%}.margin--none{margin:0!important}.margin-top--none{margin-top:0!important}.margin-left--none{margin-left:0!important}.margin-bottom--none{margin-bottom:0!important}.margin-right--none{margin-right:0!important}.margin-vert--none{margin-top:0!important;margin-bottom:0!important}.margin-horiz--none{margin-left:0!important;margin-right:0!important}.margin--xs{margin:.25rem!important}.margin-top--xs{margin-top:.25rem!important}.margin-left--xs{margin-left:.25rem!important}.margin-bottom--xs{margin-bottom:.25rem!important}.margin-right--xs{margin-right:.25rem!important}.margin-vert--xs{margin-top:.25rem!important;margin-bottom:.25rem!important}.margin-horiz--xs{margin-left:.25rem!important;margin-right:.25rem!important}.margin--sm{margin:.5rem!important}.margin-top--sm{margin-top:.5rem!important}.margin-left--sm{margin-left:.5rem!important}.margin-bottom--sm{margin-bottom:.5rem!important}.margin-right--sm{margin-right:.5rem!important}.margin-vert--sm{margin-top:.5rem!important;margin-bottom:.5rem!important}.margin-horiz--sm{margin-left:.5rem!important;margin-right:.5rem!important}.margin--md{margin:1rem!important}.margin-top--md{margin-top:1rem!important}.margin-left--md{margin-left:1rem!important}.margin-bottom--md{margin-bottom:1rem!important}.margin-right--md{margin-right:1rem!important}.margin-vert--md{margin-top:1rem!important;margin-bottom:1rem!important}.margin-horiz--md{margin-left:1rem!important;margin-right:1rem!important}.margin--lg{margin:2rem!important}.margin-top--lg{margin-top:2rem!important}.margin-left--lg{margin-left:2rem!important}.margin-bottom--lg{margin-bottom:2rem!important}.margin-right--lg{margin-right:2rem!important}.margin-vert--lg{margin-top:2rem!important;margin-bottom:2rem!important}.margin-horiz--lg{margin-left:2rem!important;margin-right:2rem!important}.margin--xl{margin:5rem!important}.margin-top--xl{margin-top:5rem!important}.margin-left--xl{margin-left:5rem!important}.margin-bottom--xl{margin-bottom:5rem!important}.margin-right--xl{margin-right:5rem!important}.margin-vert--xl{margin-top:5rem!important;margin-bottom:5rem!important}.margin-horiz--xl{margin-left:5rem!important;margin-right:5rem!important}.padding--none{padding:0!important}.padding-top--none{padding-top:0!important}.padding-left--none{padding-left:0!important}.padding-bottom--none{padding-bottom:0!important}.padding-right--none{padding-right:0!important}.padding-vert--none{padding-top:0!important;padding-bottom:0!important}.padding-horiz--none{padding-left:0!important;padding-right:0!important}.padding--xs{padding:.25rem!important}.padding-top--xs{padding-top:.25rem!important}.padding-left--xs{padding-left:.25rem!important}.padding-bottom--xs{padding-bottom:.25rem!important}.padding-right--xs{padding-right:.25rem!important}.padding-vert--xs{padding-top:.25rem!important;padding-bottom:.25rem!important}.padding-horiz--xs{padding-left:.25rem!important;padding-right:.25rem!important}.padding--sm{padding:.5rem!important}.padding-top--sm{padding-top:.5rem!important}.padding-left--sm{padding-left:.5rem!important}.padding-bottom--sm{padding-bottom:.5rem!important}.padding-right--sm{padding-right:.5rem!important}.padding-vert--sm{padding-top:.5rem!important;padding-bottom:.5rem!important}.padding-horiz--sm{padding-left:.5rem!important;padding-right:.5rem!important}.padding--md{padding:1rem!important}.padding-top--md{padding-top:1rem!important}.padding-left--md{padding-left:1rem!important}.padding-bottom--md{padding-bottom:1rem!important}.padding-right--md{padding-right:1rem!important}.padding-vert--md{padding-top:1rem!important;padding-bottom:1rem!important}.padding-horiz--md{padding-left:1rem!important;padding-right:1rem!important}.padding--lg{padding:2rem!important}.padding-top--lg{padding-top:2rem!important}.padding-left--lg{padding-left:2rem!important}.padding-bottom--lg{padding-bottom:2rem!important}.padding-right--lg{padding-right:2rem!important}.padding-vert--lg{padding-top:2rem!important;padding-bottom:2rem!important}.padding-horiz--lg{padding-left:2rem!important;padding-right:2rem!important}.padding--xl{padding:5rem!important}.padding-top--xl{padding-top:5rem!important}.padding-left--xl{padding-left:5rem!important}.padding-bottom--xl{padding-bottom:5rem!important}.padding-right--xl{padding-right:5rem!important}.padding-vert--xl{padding-top:5rem!important;padding-bottom:5rem!important}.padding-horiz--xl{padding-left:5rem!important;padding-right:5rem!important}code{background-color:var(--ifm-code-background);border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical)var(--ifm-code-padding-horizontal);vertical-align:middle;border:.1rem solid rgba(0,0,0,.1)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height)var(--ifm-font-family-monospace);margin:0 0 var(--ifm-spacing-vertical);padding:var(--ifm-pre-padding);overflow:auto}pre code{font-size:100%;line-height:inherit;background-color:transparent;border:none;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);border-radius:.2rem;padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top)0 var(--ifm-heading-margin-bottom)0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:before{content:"";display:table}.markdown:after{clear:both;content:"";display:table}.markdown>:last-child{margin-bottom:0!important}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading));margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading));margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading));margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>pre,.markdown>ul,.markdown>p{margin-bottom:var(--ifm-leading)}.markdown li{word-wrap:break-word}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ul,ol{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ul ul,ul ol,ol ol,ol ul{margin:0}ul ul ol,ul ol ol,ol ul ol,ol ol ol{list-style-type:lower-alpha}table{border-collapse:collapse;margin-bottom:var(--ifm-spacing-vertical);display:block;overflow:auto}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead{background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width)solid var(--ifm-table-border-color)}table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table th,table td{border:var(--ifm-table-border-width)solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);-webkit-text-decoration:var(--ifm-link-decoration);text-decoration:var(--ifm-link-decoration);transition:color var(--ifm-transition-fast)var(--ifm-transition-timing-default)}a:hover{color:var(--ifm-link-hover-color);-webkit-text-decoration:var(--ifm-link-hover-decoration);text-decoration:var(--ifm-link-hover-decoration)}a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width)solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);margin:0 0 var(--ifm-spacing-vertical);padding:var(--ifm-blockquote-padding-vertical)var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical)0;border:0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.text--break{word-wrap:break-word!important;word-break:break-word!important}.text--no-decoration,.text--no-decoration:hover{text-decoration:none}.clean-btn{color:inherit;cursor:pointer;background:0 0;border:none;padding:0;font-family:inherit}.clean-list{padding-left:0;list-style:none}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:rgba(53,120,229,.15);--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:rgba(235,237,240,.15);--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:rgba(0,164,0,.15);--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:rgba(84,199,236,.15);--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:rgba(255,186,0,.15);--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:rgba(250,56,62,.15);--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width)solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);color:var(--ifm-alert-foreground-color);padding:var(--ifm-alert-padding-vertical)var(--ifm-alert-padding-horizontal)}.alert__heading{font:bold var(--ifm-h5-font-size)/var(--ifm-heading-line-height)var(--ifm-heading-font-family);text-transform:uppercase;align-items:center;margin-bottom:.5rem;display:flex}.alert__icon{margin-right:.4em;display:inline-flex}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{color:var(--ifm-alert-foreground-color);margin:calc(var(--ifm-alert-padding-vertical)*-1)calc(var(--ifm-alert-padding-horizontal)*-1)0 0;opacity:.75}.alert .close:hover,.alert .close:focus{opacity:1}.alert a{-webkit-text-decoration-color:var(--ifm-alert-border-color);text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{height:var(--ifm-avatar-photo-size);width:var(--ifm-avatar-photo-size);border-radius:50%;display:block;overflow:hidden}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{text-align:var(--ifm-avatar-intro-alignment);flex-direction:column;flex:1;justify-content:center;display:flex}.avatar__name{font:bold var(--ifm-h4-font-size)/var(--ifm-heading-line-height)var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:.5rem;flex-direction:column;align-items:center}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width)solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);padding:var(--ifm-badge-padding-vertical)var(--ifm-badge-padding-horizontal);line-height:1;display:inline-block}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary);--ifm-badge-border-color:var(--ifm-badge-background-color)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);--ifm-badge-border-color:var(--ifm-badge-background-color);color:var(--ifm-color-black)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success);--ifm-badge-border-color:var(--ifm-badge-background-color)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info);--ifm-badge-border-color:var(--ifm-badge-background-color)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning);--ifm-badge-border-color:var(--ifm-badge-background-color)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger);--ifm-badge-border-color:var(--ifm-badge-background-color)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item{display:inline-block}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator)center;content:" ";filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));display:inline-block}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);color:var(--ifm-font-color-base);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier))calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-property:background,color;transition-duration:var(--ifm-transition-fast);transition-timing-function:var(--ifm-transition-timing-default);display:inline-block}.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width)solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);color:var(--ifm-button-color);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier))calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;-webkit-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap;transition-property:color,background,border-color;transition-duration:var(--ifm-button-transition-duration);transition-timing-function:var(--ifm-transition-timing-default);line-height:1.5;display:inline-block}.button:hover{color:var(--ifm-button-color);text-decoration:none}.button--outline{--ifm-button-background-color:transparent;--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--outline:hover,.button--outline:active,.button--outline.button--active{--ifm-button-color:var(--ifm-font-color-base-inverse)}.button--link{--ifm-button-background-color:transparent;--ifm-button-border-color:transparent;color:var(--ifm-link-color);-webkit-text-decoration:var(--ifm-link-decoration);text-decoration:var(--ifm-link-decoration)}.button--link:hover,.button--link:active,.button--link.button--active{color:var(--ifm-link-hover-color);-webkit-text-decoration:var(--ifm-link-hover-decoration);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{width:100%;display:block}.button.button--secondary{color:var(--ifm-color-gray-900)}.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary:active,.button--primary.button--active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary:active,.button--secondary.button--active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success:active,.button--success.button--active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info:active,.button--info.button--active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning:active,.button--warning.button--active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger:active,.button--danger.button--active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{gap:var(--ifm-button-group-spacing);display:inline-flex}.button-group>.button:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.button-group>.button:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.button-group--block{justify-content:stretch;display:flex}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);flex-direction:column;display:flex;overflow:hidden}.card--full-height{height:100%}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__header,.card__body,.card__footer{padding:var(--ifm-card-vertical-spacing)var(--ifm-card-horizontal-spacing)}.card__header:not(:last-child),.card__body:not(:last-child),.card__footer:not(:last-child){padding-bottom:0}.card__header>:last-child,.card__body>:last-child,.card__footer>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{padding:var(--ifm-toc-padding-vertical)0;margin-bottom:0;font-size:.8rem}.table-of-contents,.table-of-contents ul{padding-left:var(--ifm-toc-padding-horizontal);list-style:none}.table-of-contents li{margin:var(--ifm-toc-padding-vertical)var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link:hover,.table-of-contents__link:hover code,.table-of-contents__link--active,.table-of-contents__link--active code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);opacity:.5;transition:opacity var(--ifm-transition-fast)var(--ifm-transition-timing-default);padding:1rem;line-height:1}.close:hover{opacity:.7}.close:focus{opacity:.8}.dropdown{font-weight:var(--ifm-dropdown-font-weight);vertical-align:top;display:inline-flex;position:relative}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;visibility:visible;transform:translateY(-1px)}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);opacity:0;pointer-events:none;left:0;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);visibility:hidden;z-index:var(--ifm-z-index-dropdown);transition-property:opacity,transform,visibility;transition-duration:var(--ifm-transition-fast);transition-timing-function:var(--ifm-transition-timing-default);min-width:10rem;max-height:80vh;padding:.5rem;list-style:none;position:absolute;overflow-y:auto;transform:translateY(-.625rem)}.dropdown__link{color:var(--ifm-dropdown-link-color);white-space:nowrap;border-radius:.25rem;margin-top:.2rem;padding:.25rem .5rem;font-size:.875rem;display:block}.dropdown__link:hover,.dropdown__link--active{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{content:"";border:.4em solid transparent;border-top-color:currentColor;border-bottom:0 solid;margin-left:.3em;display:inline-block;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical)var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{max-width:var(--ifm-footer-logo-max-width);margin-top:1rem}.footer__title{color:var(--ifm-footer-title-color);font:bold var(--ifm-h4-font-size)/var(--ifm-heading-line-height)var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.footer__item{margin-top:0}.footer__items{margin-bottom:0}[type=checkbox]{padding:0}.hero{background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);align-items:center;padding:4rem 2rem;display:flex}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu{font-weight:var(--ifm-font-weight-semibold);overflow-x:hidden}.menu__list{margin:0;padding-left:0;list-style:none}.menu__list .menu__list{padding-left:var(--ifm-menu-link-padding-horizontal);flex:0 0 100%;margin-top:.25rem}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.menu__list-item--collapsed .menu__link--sublist:after,.menu__list-item--collapsed .menu__caret:before{transform:rotate(90deg)}.menu__list-item-collapsible{transition:background var(--ifm-transition-fast)var(--ifm-transition-timing-default);border-radius:.25rem;flex-wrap:wrap;display:flex;position:relative}.menu__list-item-collapsible:hover,.menu__list-item-collapsible--active{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link:hover,.menu__list-item-collapsible .menu__link--active{background:0 0!important}.menu__link,.menu__caret{transition:background var(--ifm-transition-fast)var(--ifm-transition-timing-default);border-radius:.25rem;align-items:center;display:flex}.menu__link:hover,.menu__caret:hover{background:var(--ifm-menu-color-background-hover)}.menu__link{color:var(--ifm-menu-color);padding:var(--ifm-menu-link-padding-vertical)var(--ifm-menu-link-padding-horizontal);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);transition:color var(--ifm-transition-fast)var(--ifm-transition-timing-default);text-decoration:none}.menu__link--sublist-caret:after{content:"";background:var(--ifm-menu-link-sublist-icon)50%/2rem 2rem;filter:var(--ifm-menu-link-sublist-icon-filter);transition:transform var(--ifm-transition-fast)linear;width:1.25rem;min-width:1.25rem;height:1.25rem;margin-left:auto;transform:rotate(180deg)}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret{padding:var(--ifm-menu-link-padding-vertical)var(--ifm-menu-link-padding-horizontal)}.menu__caret:before{content:"";background:var(--ifm-menu-link-sublist-icon)50%/2rem 2rem;filter:var(--ifm-menu-link-sublist-icon-filter);transition:transform var(--ifm-transition-fast)linear;width:1.25rem;height:1.25rem;transform:rotate(180deg)}html[data-theme=dark],.navbar--dark{--ifm-menu-link-sublist-icon-filter:invert(100%)sepia(94%)saturate(17%)hue-rotate(223deg)brightness(104%)contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical)var(--ifm-navbar-padding-horizontal);display:flex}.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{z-index:var(--ifm-z-index-fixed);position:sticky;top:0}.navbar__inner{flex-wrap:wrap;justify-content:space-between;width:100%;display:flex}.navbar__brand{color:var(--ifm-navbar-link-color);align-items:center;min-width:0;margin-right:1rem;display:flex}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar__title{flex:auto}.navbar__toggle{margin-right:.5rem;display:none}.navbar__logo{flex:none;height:2rem;margin-right:.5rem}.navbar__logo img{height:100%}.navbar__items{flex:1;align-items:center;min-width:0;display:flex}.navbar__items--center{flex:none}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:none;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{padding:var(--ifm-navbar-item-padding-vertical)var(--ifm-navbar-item-padding-horizontal);display:inline-block}.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.navbar__link{color:var(--ifm-navbar-link-color);font-weight:var(--ifm-font-weight-semibold)}.navbar__link:hover,.navbar__link--active{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:rgba(255,255,255,.1);--ifm-navbar-search-input-placeholder-color:rgba(255,255,255,.5);color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-navbar-link-hover-color:var(--ifm-color-primary);--ifm-menu-color-background-active:rgba(255,255,255,.05);--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{appearance:none;background:var(--ifm-navbar-search-input-background-color)var(--ifm-navbar-search-input-icon)no-repeat .75rem center/1rem 1rem;color:var(--ifm-navbar-search-input-color);cursor:text;border:none;border-radius:2rem;width:12.5rem;height:2rem;padding:0 .5rem 0 2.25rem;font-size:1rem;display:inline-block}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);opacity:0;visibility:hidden;width:var(--ifm-navbar-sidebar-width);transition-property:opacity,visibility,transform;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;transform:translate(-100%)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar--show .navbar-sidebar{transform:translate(0,0)}.navbar-sidebar__backdrop{opacity:0;visibility:hidden;transition-property:opacity,visibility;transition-duration:var(--ifm-transition-fast);background-color:rgba(0,0,0,.6);transition-timing-function:ease-in-out;position:fixed;inset:0}.navbar-sidebar__brand{box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical)var(--ifm-navbar-padding-horizontal);flex:1;align-items:center;display:flex}.navbar-sidebar__items{height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast)ease-in-out;display:flex;transform:translateZ(0)}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{width:calc(var(--ifm-navbar-sidebar-width));flex-shrink:0;padding:.5rem}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);text-align:left;width:calc(100% + 1rem);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;top:-.5rem}.navbar-sidebar__close{margin-left:auto;display:flex}.pagination{column-gap:var(--ifm-pagination-page-spacing);font-size:var(--ifm-pagination-font-size);padding-left:0;display:flex}.pagination--sm{--ifm-pagination-font-size:.8rem;--ifm-pagination-padding-horizontal:.8rem;--ifm-pagination-padding-vertical:.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{background:var(--ifm-pagination-item-active-background);color:var(--ifm-pagination-color-active)}.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);padding:var(--ifm-pagination-padding-vertical)var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast)var(--ifm-transition-timing-default);display:inline-block}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr);display:grid}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast)var(--ifm-transition-timing-default);height:100%;display:block}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{text-align:right;grid-column:2/3}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills{gap:var(--ifm-pills-spacing);padding-left:0;display:flex}.pills__item{cursor:pointer;font-weight:var(--ifm-font-weight-bold);transition:background var(--ifm-transition-fast)var(--ifm-transition-timing-default);border-radius:.5rem;padding:.25rem 1rem;display:inline-block}.pills__item--active{background:var(--ifm-pills-color-background-active);color:var(--ifm-pills-color-active)}.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{text-align:center;flex-grow:1}.tabs{color:var(--ifm-tabs-color);font-weight:var(--ifm-font-weight-bold);margin-bottom:0;padding-left:0;display:flex;overflow-x:auto}.tabs__item{border-radius:var(--ifm-global-radius);cursor:pointer;padding:var(--ifm-tabs-padding-vertical)var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast)var(--ifm-transition-timing-default);border-bottom:3px solid transparent;display:inline-flex}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);color:var(--ifm-tabs-color-active);border-bottom-right-radius:0;border-bottom-left-radius:0}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-500:var(--ifm-color-gray-500);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:rgba(255,255,255,.05);--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%)sepia(11%)saturate(0%)hue-rotate(149deg)brightness(99%)contrast(95%);--ifm-code-background:rgba(255,255,255,.1);--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:rgba(255,255,255,.07);--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.footer__link-separator{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{width:max-content;display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__item{display:none}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0s;--ifm-transition-slow:0s}}@media print{.table-of-contents,.footer,.menu,.navbar,.pagination-nav{display:none}.tabs{page-break-inside:avoid}}:root{--docusaurus-progress-bar-color:var(--ifm-color-primary)}#nprogress{pointer-events:none}#nprogress .bar{background:var(--docusaurus-progress-bar-color);z-index:1031;width:100%;height:2px;position:fixed;top:0;left:0}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);opacity:1;width:100px;height:100%;position:absolute;right:0;transform:rotate(3deg)translateY(-4px)}:root{--ifm-container-width:1280px;--ifm-container-width-xl:1440px;--ifm-footer-padding-vertical:.5rem;--ifm-spacing-horizontal:.8rem}.header-github-link:hover{opacity:.6}.header-github-link:before{content:"";background:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;width:24px;height:24px;display:flex}[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}body:not(.navigation-with-keyboard) :not(input):focus{outline:none}#__docusaurus-base-url-issue-banner-container{display:none}.skipToContent_fXgn{z-index:calc(var(--ifm-z-index-fixed) + 1);padding:calc(var(--ifm-global-spacing)/2)var(--ifm-global-spacing);color:var(--ifm-color-emphasis-900);background-color:var(--ifm-background-surface-color);position:fixed;top:1rem;left:100%}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{padding:0;line-height:0}.content_knG7{text-align:center;padding:5px 0;font-size:85%}.content_knG7 a{color:inherit;text-decoration:underline}:root{--docusaurus-announcement-bar-height:auto}.announcementBar_mb4j{height:var(--docusaurus-announcement-bar-height);background-color:var(--ifm-color-white);color:var(--ifm-color-black);border-bottom:1px solid var(--ifm-color-emphasis-100);align-items:center;display:flex}html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{flex:0 0 30px;align-self:stretch}.announcementBarContent_xLdY{flex:auto}@media print{.announcementBar_mb4j{display:none}}@media (min-width:997px){:root{--docusaurus-announcement-bar-height:30px}.announcementBarPlaceholder_vyr4,.announcementBarClose_gvF7{flex-basis:50px}}.toggle_vylO{width:2rem;height:2rem}.toggleButton_gllP{-webkit-tap-highlight-color:transparent;transition:background var(--ifm-transition-fast);border-radius:50%;justify-content:center;align-items:center;width:100%;height:100%;display:flex}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}[data-theme=light] .darkToggleIcon_wfgR,[data-theme=dark] .lightToggleIcon_pyhR{display:none}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}.themedComponent_mlkZ{display:none}[data-theme=light] .themedComponent--light_NVdE,[data-theme=dark] .themedComponent--dark_xIcU,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{vertical-align:text-bottom;margin-right:5px}.navbarSearchContainer_Bca1:empty{display:none}@media (max-width:996px){.navbarSearchContainer_Bca1{right:var(--ifm-navbar-padding-horizontal);position:absolute}}@media (min-width:997px){.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical)var(--ifm-navbar-item-padding-horizontal)}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast)ease}.navbarHidden_jGov{transform:translateY(calc(-100% - 2px))}@media (max-width:996px){.colorModeToggle_DEke{display:none}}.errorBoundaryError_a6uf{white-space:pre-wrap;color:red}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast)var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover{opacity:1}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none;padding-left:.5rem}.hash-link:before{content:"#"}.hash-link:focus,:hover>.hash-link{opacity:1}html,body{height:100%}.mainWrapper_z2l0{flex-direction:column;flex:1 0 auto;display:flex}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{flex-direction:column;min-height:100%;display:flex}.sidebar_re4s{max-height:calc(100vh - (var(--ifm-navbar-height) + 2rem));top:calc(var(--ifm-navbar-height) + 2rem);position:sticky;overflow-y:auto}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size);font-weight:var(--ifm-font-weight-bold)}.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLink_mo7H:hover{text-decoration:none}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}@media (max-width:996px){.sidebar_re4s{display:none}}.yearGroupHeading_rMGB{margin-top:1.6rem;margin-bottom:.4rem}.yearGroupHeading_QT03{margin:1rem .75rem .5rem}.title_f1Hy{font-size:3rem}@media (max-width:576px){.title_f1Hy{font-size:2rem}}.container_mt6G{font-size:.9rem}[data-theme=dark] .githubSvg_Uu4N{fill:var(--light)}[data-theme=light] .githubSvg_Uu4N{fill:var(--dark)}[data-theme=dark] .xSvg_y3PF{fill:var(--light)}[data-theme=light] .xSvg_y3PF{fill:var(--dark)}:root{--docusaurus-blog-social-icon-size:1rem}.authorSocials_rSDt{height:var(--docusaurus-blog-social-icon-size);line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;flex-wrap:wrap;align-items:center;line-height:0;display:flex;overflow:hidden}.authorSocialLink_owbf{height:var(--docusaurus-blog-social-icon-size);width:var(--docusaurus-blog-social-icon-size);margin-right:.4rem;line-height:0}.authorSocialIcon_XYv3{width:var(--docusaurus-blog-social-icon-size);height:var(--docusaurus-blog-social-icon-size)}.authorImage_XqGP{--ifm-avatar-photo-size:3.6rem}.author-as-h1_n9oJ .authorImage_XqGP{--ifm-avatar-photo-size:7rem}.author-as-h2_gXvM .authorImage_XqGP{--ifm-avatar-photo-size:5.4rem}.authorDetails_lV9A{flex-direction:column;justify-content:space-around;align-items:flex-start;display:flex}.authorName_yefp{flex-direction:row;font-size:1.1rem;line-height:1.1rem;display:flex}.author-as-h1_n9oJ .authorName_yefp{font-size:2.4rem;line-height:2.4rem;display:inline}.author-as-h2_gXvM .authorName_yefp{font-size:1.4rem;line-height:1.4rem;display:inline}.authorTitle_nd0D{line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical;font-size:.8rem;line-height:1rem;display:-webkit-box;overflow:hidden}.author-as-h1_n9oJ .authorTitle_nd0D{font-size:1.2rem;line-height:1.6rem}.author-as-h2_gXvM .authorTitle_nd0D{font-size:1rem;line-height:1.3rem}.authorBlogPostCount_iiJ5{background:var(--ifm-color-secondary);color:var(--ifm-color-black);border-radius:var(--ifm-global-radius);margin-left:.3rem;padding:.1rem .4rem;font-size:.8rem;line-height:1.2}.authorListItem_n3yI{margin-bottom:2rem;list-style-type:none}.authorCol_Hf19{max-width:inherit!important}.imageOnlyAuthorRow_pa_O{flex-flow:wrap;display:flex}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color);margin-bottom:var(--ifm-leading);box-shadow:var(--ifm-global-shadow-lw);border-radius:var(--ifm-code-border-radius)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);font-size:var(--ifm-code-font-size);padding:.75rem var(--ifm-pre-padding);border-top-left-radius:inherit;border-top-right-radius:inherit;font-weight:500}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockStandalone_MEMb{padding:0}.codeBlockLines_e6Vv{font:inherit;float:left;padding:var(--ifm-pre-padding);min-width:100%}.codeBlockLinesWithNumbering_o6Pm{padding:var(--ifm-pre-padding)0;display:table}@media print{.codeBlockLines_e6Vv{white-space:pre-wrap}}.buttonGroup__atx{right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2);column-gap:.2rem;display:flex;position:absolute}.buttonGroup__atx button{background:var(--prism-background-color);color:var(--prism-color);border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);transition:opacity var(--ifm-transition-fast)ease-in-out;opacity:0;align-items:center;padding:.4rem;line-height:0;display:flex}.buttonGroup__atx button:hover{opacity:1!important}.buttonGroup__atx button:focus-visible{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);margin:0 calc(-1*var(--ifm-pre-padding));padding:0 var(--ifm-pre-padding);display:block}.codeLine_lJS_{counter-increment:line-count;display:table-row}.codeLineNumber_Tfdd{text-align:right;padding:0 var(--ifm-pre-padding);background:var(--ifm-pre-background);overflow-wrap:normal;width:1%;display:table-cell;position:sticky;left:0}.codeLineNumber_Tfdd:before{content:counter(line-count);opacity:.4}.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{width:1.125rem;height:1.125rem;position:relative}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;opacity:inherit;width:inherit;height:inherit;transition:all var(--ifm-transition-fast)ease;position:absolute;top:0;left:0}.copyButtonSuccessIcon_LjdS{opacity:0;color:#00d600;top:50%;left:50%;transform:translate(-50%,-50%)scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transition-delay:75ms;transform:translate(-50%,-50%)scale(1)}.wordWrapButtonIcon_Bwma{width:1.2rem;height:1.2rem}.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.details_lb9f{--docusaurus-details-summary-arrow-size:.38rem;--docusaurus-details-transition:transform .2s ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;list-style:none;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{content:"";border-width:var(--docusaurus-details-summary-arrow-size);border-style:solid;border-color:transparent transparent transparent var(--docusaurus-details-decoration-color);transition:var(--docusaurus-details-transition);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2)50%;position:absolute;top:.45rem;left:0;transform:rotate(0)}.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before{transform:rotate(90deg)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child{margin-bottom:0}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast)ease;margin:0 0 var(--ifm-spacing-vertical);border:1px solid var(--ifm-alert-border-color)}.containsTaskList_mC6p{list-style:none}:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.img_ev3q{height:auto}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight)var(--ifm-h5-font-size)/var(--ifm-heading-line-height)var(--ifm-heading-font-family);text-transform:uppercase}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{vertical-align:middle;margin-right:.4em;display:inline-block}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);width:1.6em;height:1.6em;display:inline-block}.admonitionContent_BuS1>:last-child{margin-bottom:0}.iconEdit_Z9Sw{vertical-align:sub;margin-right:.3em}.lastUpdated_JAkA{margin-top:.2rem;font-size:smaller;font-style:italic}@media (min-width:997px){.lastUpdated_JAkA{text-align:right}}:root{--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);padding:.2rem .5rem .3rem;font-size:90%}.tagWithCount_h2kH{border-left:0;align-items:center;padding:0 .5rem 0 1rem;display:flex;position:relative}.tagWithCount_h2kH:before,.tagWithCount_h2kH:after{content:"";border:1px solid var(--docusaurus-tag-list-border);transition:inherit;position:absolute;top:50%}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;width:1.18rem;height:1.18rem;right:100%;transform:translate(50%,-50%)rotate(-45deg)}.tagWithCount_h2kH:after{border-radius:50%;width:.5rem;height:.5rem;left:0;transform:translateY(-50%)}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);color:var(--ifm-color-black);border-radius:var(--ifm-global-radius);margin-left:.3rem;padding:.1rem .4rem;font-size:.7rem;line-height:1.2}.tags_jXut{display:inline}.tag_QGVx{margin:0 .4rem .5rem 0;display:inline-block}.tableOfContents_bqdL{max-height:calc(100vh - (var(--ifm-navbar-height) + 2rem));top:calc(var(--ifm-navbar-height) + 1rem);position:sticky;overflow-y:auto}@media (max-width:996px){.tableOfContents_bqdL{display:none}.docItemContainer_F8PC{padding:0 .3rem}}.algolia-docsearch-suggestion{border-bottom-color:#3a3dd1}.algolia-docsearch-suggestion--category-header{background-color:#4b54de}.algolia-docsearch-suggestion--highlight{color:#3a33d1}.algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight{background-color:#4d47d5}.aa-cursor .algolia-docsearch-suggestion--content{color:#272296}.aa-cursor .algolia-docsearch-suggestion{background:#ebebfb}@media (min-width:768px){.algolia-docsearch-suggestion{border-bottom-color:#7671df}.algolia-docsearch-suggestion--subcategory-column{color:#4e4726;border-right-color:#7671df}}.searchbox{white-space:nowrap;box-sizing:border-box;width:200px;display:inline-block;position:relative;visibility:visible!important;height:32px!important}.searchbox .algolia-autocomplete{width:100%;height:100%;display:block}.searchbox__wrapper{z-index:999;width:100%;height:100%;position:relative}.searchbox__input{box-sizing:border-box;vertical-align:middle;white-space:normal;appearance:none;border:0;border-radius:16px;width:100%;height:100%;padding:0 26px 0 32px;font-size:12px;transition:box-shadow .4s,background .4s;display:inline-block;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important}.searchbox__input::-webkit-search-decoration{display:none}.searchbox__input::-webkit-search-cancel-button{display:none}.searchbox__input::-webkit-search-results-button{display:none}.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:focus,.searchbox__input:active{background:#fff;outline:0;box-shadow:inset 0 0 0 1px #aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;user-select:none;top:0;right:inherit;background-color:rgba(69,142,225,0);border:0;border-radius:16px 0 0 16px;width:32px;height:100%;margin:0;padding:0;position:absolute;left:0}.searchbox__submit:before{vertical-align:middle;content:"";height:100%;margin-right:-4px;display:inline-block}.searchbox__submit:hover,.searchbox__submit:active{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{vertical-align:middle;fill:#6d7e96;width:14px;height:14px}.searchbox__reset{cursor:pointer;font-size:inherit;-webkit-user-select:none;user-select:none;fill:rgba(0,0,0,.5);background:0 0;border:0;margin:0;padding:0;display:block;position:absolute;top:8px;right:8px}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{width:8px;height:8px;margin:4px;display:block}.searchbox__input:valid~.searchbox__reset{animation-name:sbx-reset-in;animation-duration:.15s;display:block}@keyframes sbx-reset-in{0%{opacity:0;transform:translate(-20%)}to{opacity:1;transform:none}}.algolia-autocomplete .ds-dropdown-menu:before{content:"";z-index:1000;background:#373940;border-top:1px solid #373940;border-right:1px solid #373940;border-radius:2px;width:14px;height:14px;display:block;position:absolute;top:-7px;transform:rotate(-45deg)}.algolia-autocomplete .ds-dropdown-menu{box-shadow:0 1px rgba(0,0,0,.2),0 2px 3px rgba(0,0,0,.1)}@media (min-width:601px){.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete .ds-dropdown-menu{text-align:left;z-index:999;background:0 0;border:none;border-radius:4px;min-width:500px;max-width:600px;height:auto;margin:6px 0 0;padding:0;position:relative;top:-6px}}@media (max-width:600px){.algolia-autocomplete .ds-dropdown-menu{z-index:100;width:600px;max-width:calc(100% - 2rem);max-height:calc(100% - 5rem);display:block;position:fixed!important;top:50px!important;left:auto!important;right:1rem!important}.algolia-autocomplete .ds-dropdown-menu:before{right:6rem}}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{z-index:1000;position:relative}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{background:#fff;border-radius:4px;padding:0;position:relative;overflow:auto}.algolia-autocomplete .ds-dropdown-menu *{box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{padding:0;text-decoration:none;display:block;position:relative;overflow:hidden}.algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--wrapper{background:#f1f1f1;box-shadow:inset -2px 0 #61dafb}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{background:#ffe564;padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight{color:inherit;background:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{background:inherit;color:inherit;padding:0 0 1px;box-shadow:inset 0 -2px rgba(69,142,225,.8)}.algolia-autocomplete .algolia-docsearch-suggestion--content{float:right;cursor:pointer;width:70%;padding:5.33333px 0 5.33333px 10.6667px;display:block;position:relative}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";background:#ececec;width:1px;height:100%;display:block;position:absolute;top:0;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{letter-spacing:.08em;text-transform:uppercase;color:#fff;background-color:#373940;margin:0;padding:5px 8px;font-size:14px;font-weight:700;display:none;position:relative}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{float:left;background-color:#fff;width:100%;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;text-align:right;color:#777;word-wrap:break-word;width:30%;padding:5.33333px 10.6667px;font-size:.9em;display:none;position:relative}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";background:#ececec;width:1px;height:100%;display:block;position:absolute;top:0;right:0}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column .algolia-docsearch-suggestion--highlight{background-color:inherit;color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{color:#02060c;margin-bottom:4px;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{color:#63676d;padding-right:2px;font-size:.85em;line-height:1.2em;display:block}.algolia-autocomplete .algolia-docsearch-suggestion--version{color:#a6aab1;padding-top:2px;padding-right:2px;font-size:.65em;display:block}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{text-align:center;background-color:#373940;width:100%;margin-top:-8px;padding:8px 0;font-size:1.2em}.algolia-autocomplete .algolia-docsearch-suggestion--no-results .algolia-docsearch-suggestion--text{color:#fff;margin-top:4px}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{color:#222;background-color:#ebebeb;border:none;border-radius:3px;padding:1px 5px;font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace;font-size:90%}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:0 0}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header{color:#fff;display:block}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--subcategory-column{display:block}.algolia-autocomplete .algolia-docsearch-footer{z-index:2000;float:right;background-color:#fff;width:100%;height:30px;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{text-indent:-9000px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 130 18'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='-36.87%25' x2='129.43%25' y1='134.94%25' y2='-27.7%25'%3E%3Cstop stop-color='%252300AEFF' offset='0%25'/%3E%3Cstop stop-color='%25233369E7' offset='100%25'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath fill='url(%2523a)' d='M59.4.02h13.3a2.37 2.37 0 0 1 2.38 2.37V15.6a2.37 2.37 0 0 1-2.38 2.36H59.4a2.37 2.37 0 0 1-2.38-2.36V2.38A2.37 2.37 0 0 1 59.4.02z'/%3E%3Cpath fill='%2523FFF' d='M66.26 4.56c-2.82 0-5.1 2.27-5.1 5.08 0 2.8 2.28 5.07 5.1 5.07 2.8 0 5.1-2.26 5.1-5.07 0-2.8-2.28-5.07-5.1-5.07zm0 8.65c-2 0-3.6-1.6-3.6-3.56 0-1.97 1.6-3.58 3.6-3.58 1.98 0 3.6 1.6 3.6 3.58a3.58 3.58 0 0 1-3.6 3.57zm0-6.4v2.66c0 .07.08.13.15.1l2.4-1.24c.04-.02.06-.1.03-.14a2.96 2.96 0 0 0-2.46-1.5c-.06 0-.1.05-.1.1zm-3.33-1.96l-.3-.3a.78.78 0 0 0-1.12 0l-.36.36a.77.77 0 0 0 0 1.1l.3.3c.05.05.13.04.17 0 .2-.25.4-.5.6-.7.23-.23.46-.43.7-.6.07-.04.07-.1.03-.16zm5-.8V3.4a.78.78 0 0 0-.78-.78h-1.83a.78.78 0 0 0-.78.78v.63c0 .07.06.12.14.1a5.74 5.74 0 0 1 1.58-.22c.52 0 1.04.07 1.54.2a.1.1 0 0 0 .13-.1z'/%3E%3Cpath fill='%2523182359' d='M102.16 13.76c0 1.46-.37 2.52-1.12 3.2-.75.67-1.9 1-3.44 1-.56 0-1.74-.1-2.67-.3l.34-1.7c.78.17 1.82.2 2.36.2.86 0 1.48-.16 1.84-.5.37-.36.55-.88.55-1.57v-.35a6.37 6.37 0 0 1-.84.3 4.15 4.15 0 0 1-1.2.17 4.5 4.5 0 0 1-1.6-.28 3.38 3.38 0 0 1-1.26-.82 3.74 3.74 0 0 1-.8-1.35c-.2-.54-.3-1.5-.3-2.2 0-.67.1-1.5.3-2.06a3.92 3.92 0 0 1 .9-1.43 4.12 4.12 0 0 1 1.45-.92 5.3 5.3 0 0 1 1.94-.37c.7 0 1.35.1 1.97.2a15.86 15.86 0 0 1 1.6.33v8.46zm-5.95-4.2c0 .9.2 1.88.6 2.3.4.4.9.62 1.53.62.34 0 .66-.05.96-.15a2.75 2.75 0 0 0 .73-.33V6.7a8.53 8.53 0 0 0-1.42-.17c-.76-.02-1.36.3-1.77.8-.4.5-.62 1.4-.62 2.23zm16.13 0c0 .72-.1 1.26-.32 1.85a4.4 4.4 0 0 1-.9 1.53c-.38.42-.85.75-1.4.98-.54.24-1.4.37-1.8.37-.43 0-1.27-.13-1.8-.36a4.1 4.1 0 0 1-1.4-.97 4.5 4.5 0 0 1-.92-1.52 5.04 5.04 0 0 1-.33-1.84c0-.72.1-1.4.32-2 .22-.6.53-1.1.92-1.5.4-.43.86-.75 1.4-.98a4.55 4.55 0 0 1 1.78-.34 4.7 4.7 0 0 1 1.8.34c.54.23 1 .55 1.4.97.38.42.68.92.9 1.5.23.6.35 1.3.35 2zm-2.2 0c0-.92-.2-1.7-.6-2.22-.38-.54-.94-.8-1.64-.8-.72 0-1.27.26-1.67.8-.4.54-.58 1.3-.58 2.22 0 .93.2 1.56.6 2.1.38.54.94.8 1.64.8s1.25-.26 1.65-.8c.4-.55.6-1.17.6-2.1zm6.97 4.7c-3.5.02-3.5-2.8-3.5-3.27L113.57.92l2.15-.34v10c0 .25 0 1.87 1.37 1.88v1.8zm3.77 0h-2.15v-9.2l2.15-.33v9.54zM119.8 3.74c.7 0 1.3-.58 1.3-1.3 0-.7-.58-1.3-1.3-1.3-.73 0-1.3.6-1.3 1.3 0 .72.58 1.3 1.3 1.3zm6.43 1c.7 0 1.3.1 1.78.27.5.18.88.42 1.17.73.28.3.5.74.6 1.18.13.46.2.95.2 1.5v5.47a25.24 25.24 0 0 1-1.5.25c-.67.1-1.42.15-2.25.15a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.37-.27-.9-.27-1.44 0-.52.1-.85.3-1.2.2-.37.48-.67.83-.9a3.6 3.6 0 0 1 1.23-.5 7.07 7.07 0 0 1 2.2-.1l.83.16v-.35c0-.25-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.18-.34-.3-.58-.4a2.54 2.54 0 0 0-.92-.17c-.5 0-.94.06-1.35.13-.4.08-.75.16-1 .25l-.27-1.74c.27-.1.67-.18 1.2-.28a9.34 9.34 0 0 1 1.65-.14zm.18 7.74c.66 0 1.15-.04 1.5-.1V10.2a5.1 5.1 0 0 0-2-.1c-.23.03-.45.1-.64.2a1.17 1.17 0 0 0-.47.38c-.13.17-.18.26-.18.52 0 .5.17.8.5.98.32.2.74.3 1.3.3zM84.1 4.8c.72 0 1.3.08 1.8.26.48.17.87.42 1.15.73.3.3.5.72.6 1.17.14.45.2.94.2 1.47v5.48a25.24 25.24 0 0 1-1.5.26c-.67.1-1.42.14-2.25.14a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.38-.27-.9-.27-1.44 0-.53.1-.86.3-1.22.2-.36.5-.65.84-.88a3.6 3.6 0 0 1 1.24-.5 7.07 7.07 0 0 1 2.2-.1c.26.03.54.08.84.15v-.35c0-.24-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.17-.34-.3-.58-.4a2.54 2.54 0 0 0-.9-.15c-.5 0-.96.05-1.37.12-.4.07-.75.15-1 .24l-.26-1.75c.27-.08.67-.17 1.18-.26a8.9 8.9 0 0 1 1.66-.15zm.2 7.73c.65 0 1.14-.04 1.48-.1v-2.17a5.1 5.1 0 0 0-1.98-.1c-.24.03-.46.1-.65.18a1.17 1.17 0 0 0-.47.4c-.12.17-.17.26-.17.52 0 .5.18.8.5.98.32.2.75.3 1.3.3zm8.68 1.74c-3.5 0-3.5-2.82-3.5-3.28L89.45.92 91.6.6v10c0 .25 0 1.87 1.38 1.88v1.8z'/%3E%3Cpath fill='%25231D3657' d='M5.03 11.03c0 .7-.26 1.24-.76 1.64-.5.4-1.2.6-2.1.6-.88 0-1.6-.14-2.17-.42v-1.2c.36.16.74.3 1.14.38.4.1.78.15 1.13.15.5 0 .88-.1 1.12-.3a.94.94 0 0 0 .35-.77.98.98 0 0 0-.33-.74c-.22-.2-.68-.44-1.37-.72-.72-.3-1.22-.62-1.52-1C.23 8.27.1 7.82.1 7.3c0-.65.22-1.17.7-1.55.46-.37 1.08-.56 1.86-.56.76 0 1.5.16 2.25.48l-.4 1.05c-.7-.3-1.32-.44-1.87-.44-.4 0-.73.08-.94.26a.9.9 0 0 0-.33.72c0 .2.04.38.12.52.08.15.22.3.42.4.2.14.55.3 1.06.52.58.24 1 .47 1.27.67.27.2.47.44.6.7.12.26.18.57.18.92zM9 13.27c-.92 0-1.64-.27-2.16-.8-.52-.55-.78-1.3-.78-2.24 0-.97.24-1.73.72-2.3.5-.54 1.15-.82 2-.82.78 0 1.4.25 1.85.72.46.48.7 1.14.7 1.97v.67H7.35c0 .58.17 1.02.46 1.33.3.3.7.47 1.24.47.36 0 .68-.04.98-.1a5.1 5.1 0 0 0 .98-.33v1.02a3.87 3.87 0 0 1-.94.32 5.72 5.72 0 0 1-1.08.1zm-.22-5.2c-.4 0-.73.12-.97.38s-.37.62-.42 1.1h2.7c0-.48-.13-.85-.36-1.1-.23-.26-.54-.38-.94-.38zm7.7 5.1l-.26-.84h-.05c-.28.36-.57.6-.86.74-.28.13-.65.2-1.1.2-.6 0-1.05-.16-1.38-.48-.32-.32-.5-.77-.5-1.34 0-.62.24-1.08.7-1.4.45-.3 1.14-.47 2.07-.5l1.02-.03V9.2c0-.37-.1-.65-.27-.84-.17-.2-.45-.28-.82-.28-.3 0-.6.04-.88.13a6.68 6.68 0 0 0-.8.33l-.4-.9a4.4 4.4 0 0 1 1.05-.4 4.86 4.86 0 0 1 1.08-.12c.76 0 1.33.18 1.7.5.4.33.6.85.6 1.56v4h-.9zm-1.9-.87c.47 0 .83-.13 1.1-.38.3-.26.43-.62.43-1.08v-.52l-.76.03c-.6.03-1.02.13-1.3.3s-.4.45-.4.82c0 .26.08.47.24.6.16.16.4.23.7.23zm7.57-5.2c.25 0 .46.03.62.06l-.12 1.18a2.38 2.38 0 0 0-.56-.06c-.5 0-.92.16-1.24.5-.3.32-.47.75-.47 1.27v3.1h-1.27V7.23h1l.16 1.05h.05c.2-.36.45-.64.77-.85a1.83 1.83 0 0 1 1.02-.3zm4.12 6.17c-.9 0-1.58-.27-2.05-.8-.47-.52-.7-1.27-.7-2.25 0-1 .24-1.77.73-2.3.5-.54 1.2-.8 2.12-.8.63 0 1.2.1 1.7.34l-.4 1c-.52-.2-.96-.3-1.3-.3-1.04 0-1.55.68-1.55 2.05 0 .67.13 1.17.38 1.5.26.34.64.5 1.13.5a3.23 3.23 0 0 0 1.6-.4v1.1a2.53 2.53 0 0 1-.73.28 4.36 4.36 0 0 1-.93.08zm8.28-.1h-1.27V9.5c0-.45-.1-.8-.28-1.02-.18-.23-.47-.34-.88-.34-.53 0-.9.16-1.16.48-.25.3-.38.85-.38 1.6v2.94h-1.26V4.8h1.26v2.12c0 .34-.02.7-.06 1.1h.08a1.76 1.76 0 0 1 .72-.67c.3-.16.66-.24 1.07-.24 1.43 0 2.15.74 2.15 2.2v3.86zM42.2 7.1c.74 0 1.32.28 1.73.82.4.53.62 1.3.62 2.26 0 .97-.2 1.73-.63 2.27-.42.54-1 .82-1.75.82s-1.33-.27-1.75-.8h-.08l-.23.7h-.94V4.8h1.26v2l-.02.64-.03.56h.05c.4-.6 1-.9 1.78-.9zm-.33 1.04c-.5 0-.88.15-1.1.45-.22.3-.34.8-.35 1.5v.08c0 .72.12 1.24.35 1.57.23.32.6.48 1.12.48.44 0 .78-.17 1-.53.24-.35.36-.87.36-1.53 0-1.35-.47-2.03-1.4-2.03zm3.24-.92h1.4l1.2 3.37c.18.47.3.92.36 1.34h.04l.18-.72 1.37-4H51l-2.53 6.73c-.46 1.23-1.23 1.85-2.3 1.85-.3 0-.56-.03-.83-.1v-1c.2.05.4.08.65.08.6 0 1.03-.36 1.28-1.06l.22-.56-2.4-5.94z'/%3E%3C/g%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100%;width:110px;height:100%;margin-left:auto;margin-right:5px;display:block;overflow:hidden}html[data-theme=dark] .algolia-docsearch-suggestion--category-header,html[data-theme=dark] .algolia-docsearch-suggestion--wrapper,html[data-theme=dark] .algolia-docsearch-footer{background:var(--ifm-background-color)!important;color:var(--ifm-font-color-base)!important}html[data-theme=dark] .algolia-docsearch-suggestion--title{color:var(--ifm-font-color-base)!important}html[data-theme=dark] .ds-cursor .algolia-docsearch-suggestion--wrapper{background:var(--ifm-background-surface-color)!important}mark{background-color:#add8e6} \ No newline at end of file diff --git a/assets/font/JetBrainsMono-Regular.woff b/assets/font/JetBrainsMono-Regular.woff deleted file mode 100644 index dc1d85f..0000000 Binary files a/assets/font/JetBrainsMono-Regular.woff and /dev/null differ diff --git a/assets/font/JetBrainsMono-Regular.woff2 b/assets/font/JetBrainsMono-Regular.woff2 deleted file mode 100644 index fdf95dd..0000000 Binary files a/assets/font/JetBrainsMono-Regular.woff2 and /dev/null differ diff --git a/assets/font/lato-regular-webfont.woff b/assets/font/lato-regular-webfont.woff deleted file mode 100644 index 4fe6d31..0000000 Binary files a/assets/font/lato-regular-webfont.woff and /dev/null differ diff --git a/assets/font/lato-regular-webfont.woff2 b/assets/font/lato-regular-webfont.woff2 deleted file mode 100644 index f7c4d26..0000000 Binary files a/assets/font/lato-regular-webfont.woff2 and /dev/null differ diff --git a/assets/images/1-0d5e8450555296218deb0517b80440f3.png b/assets/images/1-0d5e8450555296218deb0517b80440f3.png new file mode 100644 index 0000000..012aadb Binary files /dev/null and b/assets/images/1-0d5e8450555296218deb0517b80440f3.png differ diff --git a/assets/images/1-2d6670430a11b01011e4c231ea594db1.png b/assets/images/1-2d6670430a11b01011e4c231ea594db1.png new file mode 100644 index 0000000..6702a9f Binary files /dev/null and b/assets/images/1-2d6670430a11b01011e4c231ea594db1.png differ diff --git a/assets/images/10-b7987a0ff93705d5045057cbdaa2ede9.png b/assets/images/10-b7987a0ff93705d5045057cbdaa2ede9.png new file mode 100644 index 0000000..c6270e4 Binary files /dev/null and b/assets/images/10-b7987a0ff93705d5045057cbdaa2ede9.png differ diff --git a/assets/images/2-062e1e47a07f200ff3b1531a02812bc7.png b/assets/images/2-062e1e47a07f200ff3b1531a02812bc7.png new file mode 100644 index 0000000..d3a25db Binary files /dev/null and b/assets/images/2-062e1e47a07f200ff3b1531a02812bc7.png differ diff --git a/assets/images/2-46bb7cc9cf739d97050c199eedced1a7.png b/assets/images/2-46bb7cc9cf739d97050c199eedced1a7.png new file mode 100644 index 0000000..51b3375 Binary files /dev/null and b/assets/images/2-46bb7cc9cf739d97050c199eedced1a7.png differ diff --git a/assets/images/2018-10-heaptrack/heaptrack-after.png b/assets/images/2018-10-heaptrack/heaptrack-after.png deleted file mode 100644 index b5f8d8f..0000000 Binary files a/assets/images/2018-10-heaptrack/heaptrack-after.png and /dev/null differ diff --git a/assets/images/2018-10-heaptrack/heaptrack-flamegraph.xcf b/assets/images/2018-10-heaptrack/heaptrack-flamegraph.xcf deleted file mode 100644 index 3e804e0..0000000 Binary files a/assets/images/2018-10-heaptrack/heaptrack-flamegraph.xcf and /dev/null differ diff --git a/assets/images/3-2f5c483659f81d741809de6d095bd577.png b/assets/images/3-2f5c483659f81d741809de6d095bd577.png new file mode 100644 index 0000000..c461680 Binary files /dev/null and b/assets/images/3-2f5c483659f81d741809de6d095bd577.png differ diff --git a/assets/images/3-eea635f8cfe4a12ae649ceb6c984e0cd.png b/assets/images/3-eea635f8cfe4a12ae649ceb6c984e0cd.png new file mode 100644 index 0000000..3c98570 Binary files /dev/null and b/assets/images/3-eea635f8cfe4a12ae649ceb6c984e0cd.png differ diff --git a/assets/images/4-63dc81954b1604cfa91f4c789da144a5.png b/assets/images/4-63dc81954b1604cfa91f4c789da144a5.png new file mode 100644 index 0000000..c030210 Binary files /dev/null and b/assets/images/4-63dc81954b1604cfa91f4c789da144a5.png differ diff --git a/assets/images/4-b4c3dbfa10b1997706bc271ca71e2ff5.png b/assets/images/4-b4c3dbfa10b1997706bc271ca71e2ff5.png new file mode 100644 index 0000000..0107d47 Binary files /dev/null and b/assets/images/4-b4c3dbfa10b1997706bc271ca71e2ff5.png differ diff --git a/assets/images/5-8f10acd82b2f025abe57cb93d435a25f.png b/assets/images/5-8f10acd82b2f025abe57cb93d435a25f.png new file mode 100644 index 0000000..4cc4983 Binary files /dev/null and b/assets/images/5-8f10acd82b2f025abe57cb93d435a25f.png differ diff --git a/assets/images/5-ae210d26729cea1700924579adf2c44c.png b/assets/images/5-ae210d26729cea1700924579adf2c44c.png new file mode 100644 index 0000000..4a58b6e Binary files /dev/null and b/assets/images/5-ae210d26729cea1700924579adf2c44c.png differ diff --git a/assets/images/6-456ca1125f48947cf3c1c13722af95a0.png b/assets/images/6-456ca1125f48947cf3c1c13722af95a0.png new file mode 100644 index 0000000..f414900 Binary files /dev/null and b/assets/images/6-456ca1125f48947cf3c1c13722af95a0.png differ diff --git a/assets/images/6-f07e72ff0b4639453034c75b2e62faba.png b/assets/images/6-f07e72ff0b4639453034c75b2e62faba.png new file mode 100644 index 0000000..70d426a Binary files /dev/null and b/assets/images/6-f07e72ff0b4639453034c75b2e62faba.png differ diff --git a/assets/images/7-e0793eed6c42845d8ce4e3e79c1d44d8.png b/assets/images/7-e0793eed6c42845d8ce4e3e79c1d44d8.png new file mode 100644 index 0000000..b9e785f Binary files /dev/null and b/assets/images/7-e0793eed6c42845d8ce4e3e79c1d44d8.png differ diff --git a/assets/images/8-3eb2ad63e4c40b6717ee4516223d73ed.png b/assets/images/8-3eb2ad63e4c40b6717ee4516223d73ed.png new file mode 100644 index 0000000..d05599c Binary files /dev/null and b/assets/images/8-3eb2ad63e4c40b6717ee4516223d73ed.png differ diff --git a/assets/images/9-630bd32c43e654f068e3c3bea79810e5.png b/assets/images/9-630bd32c43e654f068e3c3bea79810e5.png new file mode 100644 index 0000000..2a85bfa Binary files /dev/null and b/assets/images/9-630bd32c43e654f068e3c3bea79810e5.png differ diff --git a/assets/images/_notebook_11_0-1c14b9b64e0cc03bce9e40f936d85202.png b/assets/images/_notebook_11_0-1c14b9b64e0cc03bce9e40f936d85202.png new file mode 100644 index 0000000..a57bfcc Binary files /dev/null and b/assets/images/_notebook_11_0-1c14b9b64e0cc03bce9e40f936d85202.png differ diff --git a/assets/images/_notebook_11_0-2d0fe64b876b1c32a095f2d74b128f3c.png b/assets/images/_notebook_11_0-2d0fe64b876b1c32a095f2d74b128f3c.png new file mode 100644 index 0000000..6843a02 Binary files /dev/null and b/assets/images/_notebook_11_0-2d0fe64b876b1c32a095f2d74b128f3c.png differ diff --git a/assets/images/_notebook_12_0-1106bdfe947224ae55d7227b5a631d0e.svg b/assets/images/_notebook_12_0-1106bdfe947224ae55d7227b5a631d0e.svg new file mode 100644 index 0000000..fab9413 --- /dev/null +++ b/assets/images/_notebook_12_0-1106bdfe947224ae55d7227b5a631d0e.svg @@ -0,0 +1,121 @@ + + + + + Years + + + + 1 + 5 + 2 + 3 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 50 + 100 + 150 + 200 + + + Value + + + + + + + diff --git a/assets/images/_notebook_12_0-78c0e39ab1b402672551d197e388d2ba.png b/assets/images/_notebook_12_0-78c0e39ab1b402672551d197e388d2ba.png new file mode 100644 index 0000000..9a36597 Binary files /dev/null and b/assets/images/_notebook_12_0-78c0e39ab1b402672551d197e388d2ba.png differ diff --git a/assets/images/_notebook_13_0-2d0fe64b876b1c32a095f2d74b128f3c.png b/assets/images/_notebook_13_0-2d0fe64b876b1c32a095f2d74b128f3c.png new file mode 100644 index 0000000..6843a02 Binary files /dev/null and b/assets/images/_notebook_13_0-2d0fe64b876b1c32a095f2d74b128f3c.png differ diff --git a/assets/images/_notebook_13_0-d109b38c5db52ca12be209a2a268c6eb.png b/assets/images/_notebook_13_0-d109b38c5db52ca12be209a2a268c6eb.png new file mode 100644 index 0000000..28d2423 Binary files /dev/null and b/assets/images/_notebook_13_0-d109b38c5db52ca12be209a2a268c6eb.png differ diff --git a/assets/images/_notebook_14_0-8fad23eda4377ce379465c56be3eb022.png b/assets/images/_notebook_14_0-8fad23eda4377ce379465c56be3eb022.png new file mode 100644 index 0000000..9cb3892 Binary files /dev/null and b/assets/images/_notebook_14_0-8fad23eda4377ce379465c56be3eb022.png differ diff --git a/assets/images/_notebook_14_1-22c2867e2cee02c45b87635ab4d3b76a.png b/assets/images/_notebook_14_1-22c2867e2cee02c45b87635ab4d3b76a.png new file mode 100644 index 0000000..d47c41f Binary files /dev/null and b/assets/images/_notebook_14_1-22c2867e2cee02c45b87635ab4d3b76a.png differ diff --git a/assets/images/_notebook_16_1-144f4c4021e22c02fe015acc38d26343.png b/assets/images/_notebook_16_1-144f4c4021e22c02fe015acc38d26343.png new file mode 100644 index 0000000..2a5f796 Binary files /dev/null and b/assets/images/_notebook_16_1-144f4c4021e22c02fe015acc38d26343.png differ diff --git a/assets/images/_notebook_16_1-eaa9ebc93d4557216c77a63df7df5192.png b/assets/images/_notebook_16_1-eaa9ebc93d4557216c77a63df7df5192.png new file mode 100644 index 0000000..d37f05b Binary files /dev/null and b/assets/images/_notebook_16_1-eaa9ebc93d4557216c77a63df7df5192.png differ diff --git a/assets/images/_notebook_18_1-0c204d1f3b296db4c925816140a946f2.png b/assets/images/_notebook_18_1-0c204d1f3b296db4c925816140a946f2.png new file mode 100644 index 0000000..7ab528a Binary files /dev/null and b/assets/images/_notebook_18_1-0c204d1f3b296db4c925816140a946f2.png differ diff --git a/assets/images/_notebook_18_1-f61745c7c099b114becca8acb3175541.png b/assets/images/_notebook_18_1-f61745c7c099b114becca8acb3175541.png new file mode 100644 index 0000000..f27e668 Binary files /dev/null and b/assets/images/_notebook_18_1-f61745c7c099b114becca8acb3175541.png differ diff --git a/assets/images/_notebook_20_1-76d1356ea34f0db5122ddbeb90dc117c.png b/assets/images/_notebook_20_1-76d1356ea34f0db5122ddbeb90dc117c.png new file mode 100644 index 0000000..10ba689 Binary files /dev/null and b/assets/images/_notebook_20_1-76d1356ea34f0db5122ddbeb90dc117c.png differ diff --git a/assets/images/_notebook_20_1-ea40789d2365d20a0725aca866680217.png b/assets/images/_notebook_20_1-ea40789d2365d20a0725aca866680217.png new file mode 100644 index 0000000..3ad1f11 Binary files /dev/null and b/assets/images/_notebook_20_1-ea40789d2365d20a0725aca866680217.png differ diff --git a/assets/images/_notebook_22_1-210909ddb46467b78aa3f65c8ae519fd.png b/assets/images/_notebook_22_1-210909ddb46467b78aa3f65c8ae519fd.png new file mode 100644 index 0000000..8566bf7 Binary files /dev/null and b/assets/images/_notebook_22_1-210909ddb46467b78aa3f65c8ae519fd.png differ diff --git a/assets/images/_notebook_23_1-86585ab19c818b386afb7ec00dbec595.png b/assets/images/_notebook_23_1-86585ab19c818b386afb7ec00dbec595.png new file mode 100644 index 0000000..4432ff1 Binary files /dev/null and b/assets/images/_notebook_23_1-86585ab19c818b386afb7ec00dbec595.png differ diff --git a/assets/images/_notebook_25_1-0db87f90eaf0febd08b4775910528a75.png b/assets/images/_notebook_25_1-0db87f90eaf0febd08b4775910528a75.png new file mode 100644 index 0000000..943f619 Binary files /dev/null and b/assets/images/_notebook_25_1-0db87f90eaf0febd08b4775910528a75.png differ diff --git a/assets/images/_notebook_26_1-686b3995a84cbcac983b369843d1e222.png b/assets/images/_notebook_26_1-686b3995a84cbcac983b369843d1e222.png new file mode 100644 index 0000000..5ec4434 Binary files /dev/null and b/assets/images/_notebook_26_1-686b3995a84cbcac983b369843d1e222.png differ diff --git a/assets/images/_notebook_3_0-6ba22789c3bcc8bd99c64f3fbfa11b30.png b/assets/images/_notebook_3_0-6ba22789c3bcc8bd99c64f3fbfa11b30.png new file mode 100644 index 0000000..d860f2f Binary files /dev/null and b/assets/images/_notebook_3_0-6ba22789c3bcc8bd99c64f3fbfa11b30.png differ diff --git a/assets/images/_notebook_4_0-46068cab7ea025b2c7ee79ad91eaf317.png b/assets/images/_notebook_4_0-46068cab7ea025b2c7ee79ad91eaf317.png new file mode 100644 index 0000000..f9c5c81 Binary files /dev/null and b/assets/images/_notebook_4_0-46068cab7ea025b2c7ee79ad91eaf317.png differ diff --git a/assets/images/_notebook_5_0-34febf65365a147cd218c9266b77e4fb.png b/assets/images/_notebook_5_0-34febf65365a147cd218c9266b77e4fb.png new file mode 100644 index 0000000..eef8ebc Binary files /dev/null and b/assets/images/_notebook_5_0-34febf65365a147cd218c9266b77e4fb.png differ diff --git a/assets/images/_notebook_5_0-85416fdde3eb77aa133be1e7dab17d9f.png b/assets/images/_notebook_5_0-85416fdde3eb77aa133be1e7dab17d9f.png new file mode 100644 index 0000000..feef3bc Binary files /dev/null and b/assets/images/_notebook_5_0-85416fdde3eb77aa133be1e7dab17d9f.png differ diff --git a/assets/images/_notebook_6_0-46e660e38189a411644eac491e9b35ad.svg b/assets/images/_notebook_6_0-46e660e38189a411644eac491e9b35ad.svg new file mode 100644 index 0000000..918535a --- /dev/null +++ b/assets/images/_notebook_6_0-46e660e38189a411644eac491e9b35ad.svg @@ -0,0 +1,121 @@ + + + + + Months + + + + 1 + 5 + 2 + 3 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 95 + 100 + 105 + 110 + 115 + 120 + + + Value + + + + + + + diff --git a/assets/images/_notebook_7_0-a9df30d31e6b96a01619455d5040eb8b.png b/assets/images/_notebook_7_0-a9df30d31e6b96a01619455d5040eb8b.png new file mode 100644 index 0000000..1d00856 Binary files /dev/null and b/assets/images/_notebook_7_0-a9df30d31e6b96a01619455d5040eb8b.png differ diff --git a/assets/images/_notebook_8_0-f511f25f81b5b7b1baeaef267dd1a2b4.png b/assets/images/_notebook_8_0-f511f25f81b5b7b1baeaef267dd1a2b4.png new file mode 100644 index 0000000..8210cb3 Binary files /dev/null and b/assets/images/_notebook_8_0-f511f25f81b5b7b1baeaef267dd1a2b4.png differ diff --git a/assets/images/_notebook_9_0-1bd353a1fa4f84f07d0964b59b00be1e.png b/assets/images/_notebook_9_0-1bd353a1fa4f84f07d0964b59b00be1e.png new file mode 100644 index 0000000..70f5140 Binary files /dev/null and b/assets/images/_notebook_9_0-1bd353a1fa4f84f07d0964b59b00be1e.png differ diff --git a/assets/images/2018-05-28-bread.jpg b/assets/images/bread-52bb152a7c29148e837d94bdf1755e1c.jpg similarity index 100% rename from assets/images/2018-05-28-bread.jpg rename to assets/images/bread-52bb152a7c29148e837d94bdf1755e1c.jpg diff --git a/assets/images/2019-02-04-container-size.svg b/assets/images/container-size-7fd54cbb2391e3e7310b0424c5f92cc1.svg similarity index 100% rename from assets/images/2019-02-04-container-size.svg rename to assets/images/container-size-7fd54cbb2391e3e7310b0424c5f92cc1.svg diff --git a/assets/images/2018-09-15-electron-percy-wasm.png b/assets/images/electron-percy-wasm-9ccb2be15a9bed6da44486afc266bad5.png similarity index 100% rename from assets/images/2018-09-15-electron-percy-wasm.png rename to assets/images/electron-percy-wasm-9ccb2be15a9bed6da44486afc266bad5.png diff --git a/assets/images/2019-05-03-making-bread/final-product.jpg b/assets/images/final-product-607f96e84dada915fa422a7e5d524ca1.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/final-product.jpg rename to assets/images/final-product-607f96e84dada915fa422a7e5d524ca1.jpg diff --git a/assets/images/2018-06-25-gravel-mound.jpg b/assets/images/gravel-mound-4afad8bdb1cd6b0e40dd2fd41adca36f.jpg similarity index 100% rename from assets/images/2018-06-25-gravel-mound.jpg rename to assets/images/gravel-mound-4afad8bdb1cd6b0e40dd2fd41adca36f.jpg diff --git a/assets/images/2018-10-heaptrack/heaptrack-before.png b/assets/images/heaptrack-before-11fba190f97831448cc539ebb32fa579.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-before.png rename to assets/images/heaptrack-before-11fba190f97831448cc539ebb32fa579.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-closeup.png b/assets/images/heaptrack-closeup-12ae3897c033ccb3684a88dd45592e14.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-closeup.png rename to assets/images/heaptrack-closeup-12ae3897c033ccb3684a88dd45592e14.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-closeup-after.png b/assets/images/heaptrack-closeup-after-967bc4596c480bcc9e8410b0a7a64a00.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-closeup-after.png rename to assets/images/heaptrack-closeup-after-967bc4596c480bcc9e8410b0a7a64a00.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-dtparse-colorized.png b/assets/images/heaptrack-dtparse-colorized-e6caf224f50df2dd56981f5b02970325.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-dtparse-colorized.png rename to assets/images/heaptrack-dtparse-colorized-e6caf224f50df2dd56981f5b02970325.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-flamegraph.png b/assets/images/heaptrack-flamegraph-5094664fa79faaf2664b38505c15ac1f.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-flamegraph.png rename to assets/images/heaptrack-flamegraph-5094664fa79faaf2664b38505c15ac1f.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-flamegraph-after.png b/assets/images/heaptrack-flamegraph-after-cedc4c3519313f5af538364165e92c34.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-flamegraph-after.png rename to assets/images/heaptrack-flamegraph-after-cedc4c3519313f5af538364165e92c34.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-flamegraph-default.png b/assets/images/heaptrack-flamegraph-default-26cc411d387f58f50cb548f8e81df1a1.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-flamegraph-default.png rename to assets/images/heaptrack-flamegraph-default-26cc411d387f58f50cb548f8e81df1a1.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-main-colorized.png b/assets/images/heaptrack-main-colorized-cfe5d7d345d32cfc1a0f297580619718.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-main-colorized.png rename to assets/images/heaptrack-main-colorized-cfe5d7d345d32cfc1a0f297580619718.png diff --git a/assets/images/2018-10-heaptrack/heaptrack-parseinfo-colorized.png b/assets/images/heaptrack-parseinfo-colorized-a1898beaf28a3997ac86810f872539b7.png similarity index 100% rename from assets/images/2018-10-heaptrack/heaptrack-parseinfo-colorized.png rename to assets/images/heaptrack-parseinfo-colorized-a1898beaf28a3997ac86810f872539b7.png diff --git a/assets/images/2018-09-15-incorrect-MIME-type.png b/assets/images/incorrect-MIME-type-a977835e8dcbfdb20fdda3c67ee4f76c.png similarity index 100% rename from assets/images/2018-09-15-incorrect-MIME-type.png rename to assets/images/incorrect-MIME-type-a977835e8dcbfdb20fdda3c67ee4f76c.png diff --git a/assets/images/2019-04-24-kung-fu.webp b/assets/images/kung-fu-5715f30eef7bf3aaa26770b1247024dc.webp similarity index 100% rename from assets/images/2019-04-24-kung-fu.webp rename to assets/images/kung-fu-5715f30eef7bf3aaa26770b1247024dc.webp diff --git a/assets/images/2018-05-28-rocks.jpg b/assets/images/rocks-6b9a0c44bf45210d496e2ebe2f896e0c.jpg similarity index 100% rename from assets/images/2018-05-28-rocks.jpg rename to assets/images/rocks-6b9a0c44bf45210d496e2ebe2f896e0c.jpg diff --git a/assets/images/2019-05-03-making-bread/shaped-loaves.jpg b/assets/images/shaped-loaves-cea15e9ccef6b180525abaee2d288880.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/shaped-loaves.jpg rename to assets/images/shaped-loaves-cea15e9ccef6b180525abaee2d288880.jpg diff --git a/assets/images/2019-05-03-making-bread/shattered-glass.jpg b/assets/images/shattered-glass-0b56af0302f7a8c3295bf43cbab77ffe.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/shattered-glass.jpg rename to assets/images/shattered-glass-0b56af0302f7a8c3295bf43cbab77ffe.jpg diff --git a/assets/images/2022-11-20-video_mp2t.png b/assets/images/video_mp2t-1decc5fbd88b54dadd06691ce4c629ec.png similarity index 100% rename from assets/images/2022-11-20-video_mp2t.png rename to assets/images/video_mp2t-1decc5fbd88b54dadd06691ce4c629ec.png diff --git a/assets/images/watch-the-world-burn-630e740c91d090f5790a3f4e103f1142.webp b/assets/images/watch-the-world-burn-630e740c91d090f5790a3f4e103f1142.webp new file mode 100644 index 0000000..df663f3 Binary files /dev/null and b/assets/images/watch-the-world-burn-630e740c91d090f5790a3f4e103f1142.webp differ diff --git a/assets/images/2019-05-03-making-bread/white-dough-rising-after-fold.jpg b/assets/images/white-dough-rising-after-fold-d7a27f12c1d2be572807105d6d7321f3.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/white-dough-rising-after-fold.jpg rename to assets/images/white-dough-rising-after-fold-d7a27f12c1d2be572807105d6d7321f3.jpg diff --git a/assets/images/2019-05-03-making-bread/white-dough-rising-before-fold.jpg b/assets/images/white-dough-rising-before-fold-c5a4424f9a5227f1f8e86b13b436782c.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/white-dough-rising-before-fold.jpg rename to assets/images/white-dough-rising-before-fold-c5a4424f9a5227f1f8e86b13b436782c.jpg diff --git a/assets/images/2019-05-03-making-bread/whole-wheat-not-rising.jpg b/assets/images/whole-wheat-not-rising-922d19641c91922b7634fff1d6f15e6d.jpg similarity index 100% rename from assets/images/2019-05-03-making-bread/whole-wheat-not-rising.jpg rename to assets/images/whole-wheat-not-rising-922d19641c91922b7634fff1d6f15e6d.jpg diff --git a/assets/js/0fb9ce37.ec625f5c.js b/assets/js/0fb9ce37.ec625f5c.js new file mode 100644 index 0000000..2406647 --- /dev/null +++ b/assets/js/0fb9ce37.ec625f5c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7848"],{6330:function(e,n,t){t.r(n),t.d(n,{assets:function(){return l},contentTitle:function(){return o},default:function(){return d},frontMatter:function(){return a},metadata:function(){return i},toc:function(){return c}});var i=t(6160),s=t(5893),r=t(65);let a={slug:"2019/12/release-the-gil",title:"Release the GIL",date:new Date("2019-12-14T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Cython",id:"cython",level:2},{value:"Numba",id:"numba",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){let n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Complaining about the ",(0,s.jsx)(n.a,{href:"https://wiki.python.org/moin/GlobalInterpreterLock",children:"Global Interpreter Lock"}),"\n(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision\nmade before multi-core CPU's were widely available, but the fact that it's still around indicates\nthat it generally works ",(0,s.jsx)(n.a,{href:"https://wiki.c2.com/?PrematureOptimization",children:"Good"}),"\n",(0,s.jsx)(n.a,{href:"https://wiki.c2.com/?YouArentGonnaNeedIt",children:"Enough"}),". Besides, there are simple and effective\nworkarounds; it's not hard to start a\n",(0,s.jsx)(n.a,{href:"https://docs.python.org/3/library/multiprocessing.html",children:"new process"})," and use message passing to\nsynchronize code running in parallel."]}),"\n",(0,s.jsxs)(n.p,{children:["Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of\nasynchronicity and ",(0,s.jsx)(n.em,{children:"M:N"})," threading, Python seems lacking. The ideal scenario is to take advantage of\nboth Python's productivity and the modern CPU's parallel capabilities."]}),"\n",(0,s.jsxs)(n.p,{children:["Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes\nPython a nice language to start with. Bear in mind: these are just the tools, no claim is made about\nwhether it's a good idea to use them. Very often, unlocking the GIL is an\n",(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/XY_problem",children:"XY problem"}),"; you want application performance, and the\nGIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at\nthe expense of project complexity; messing with the GIL is ultimately messing with Python's memory\nmodel."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%load_ext Cython\nfrom numba import jit\n\nN = 1_000_000_000\n"})}),"\n",(0,s.jsx)(n.h2,{id:"cython",children:"Cython"}),"\n",(0,s.jsxs)(n.p,{children:["Put simply, ",(0,s.jsx)(n.a,{href:"https://cython.org/",children:"Cython"})," is a programming language that looks a lot like Python,\ngets ",(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Source-to-source_compiler",children:"transpiled"})," to C/C++, and integrates\nwell with the ",(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/CPython",children:"CPython"})," API. It's great for building Python\nwrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And\nwhen it comes to managing the GIL, there are two special features:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"nogil"}),"\n",(0,s.jsx)(n.a,{href:"https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#declaring-a-function-as-callable-without-the-gil",children:"function annotation"}),"\nasserts that a Cython function is safe to use without the GIL, and compilation will fail if it\ninteracts with Python in an unsafe manner"]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"with nogil"}),"\n",(0,s.jsx)(n.a,{href:"https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#releasing-the-gil",children:"context manager"}),"\nexplicitly unlocks the CPython GIL while active"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Whenever Cython code runs inside a ",(0,s.jsx)(n.code,{children:"with nogil"}),' block on a separate thread, the Python interpreter\nis unblocked and allowed to continue work elsewhere. We\'ll define a "busy work" function that\ndemonstrates this principle in action:']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%cython\n\n# Annotating a function with `nogil` indicates only that it is safe\n# to call in a `with nogil` block. It *does not* release the GIL.\ncdef unsigned long fibonacci(unsigned long n) nogil:\n if n <= 1:\n return n\n\n cdef unsigned long a = 0, b = 1, c = 0\n\n c = a + b\n for _i in range(2, n):\n a = b\n b = c\n c = a + b\n\n return c\n\n\ndef cython_nogil(unsigned long n):\n # Explicitly release the GIL while running `fibonacci`\n with nogil:\n value = fibonacci(n)\n\n return value\n\n\ndef cython_gil(unsigned long n):\n # Because the GIL is not explicitly released, it implicitly\n # remains acquired when running the `fibonacci` function\n return fibonacci(n)\n"})}),"\n",(0,s.jsx)(n.p,{children:"First, let's time how long it takes Cython to calculate the billionth Fibonacci number:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\n_ = cython_gil(N);\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 365 ms, sys: 0 ns, total: 365 ms\nWall time: 372 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\n_ = cython_nogil(N);\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 381 ms, sys: 0 ns, total: 381 ms\nWall time: 388 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Both versions (with and without GIL) take effectively the same amount of time to run. Even when\nrunning this calculation in parallel on separate threads, it is expected that the run time will\ndouble because only one thread can be active at a time:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\nfrom threading import Thread\n\n# Create the two threads to run on\nt1 = Thread(target=cython_gil, args=[N])\nt2 = Thread(target=cython_gil, args=[N])\n# Start the threads\nt1.start(); t2.start()\n# Wait for the threads to finish\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms\nWall time: 645 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"However, if the first thread releases the GIL, the second thread is free to acquire it and run in\nparallel:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\n\nt1 = Thread(target=cython_nogil, args=[N])\nt2 = Thread(target=cython_gil, args=[N])\nt1.start(); t2.start()\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 717 ms, sys: 372 \xb5s, total: 718 ms\nWall time: 358 ms"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Because ",(0,s.jsx)(n.code,{children:"user"})," time represents the sum of processing time on all threads, it doesn't change much.\nThe ",(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Elapsed_real_time",children:'"wall time"'})," has been cut roughly in half\nbecause each function is running simultaneously."]}),"\n",(0,s.jsxs)(n.p,{children:["Keep in mind that the ",(0,s.jsx)(n.strong,{children:"order in which threads are started"})," makes a difference!"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\n\n# Note that the GIL-locked version is started first\nt1 = Thread(target=cython_gil, args=[N])\nt2 = Thread(target=cython_nogil, args=[N])\nt1.start(); t2.start()\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 667 ms, sys: 0 ns, total: 667 ms\nWall time: 672 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Even though the second thread releases the GIL while running, it can't start until the first has\ncompleted. Thus, the overall runtime is effectively the same as running two GIL-locked threads."}),"\n",(0,s.jsxs)(n.p,{children:["Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the\n",(0,s.jsx)(n.strong,{children:"interpreter"}),", not just the thread attempting the unlock:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%cython\n\ncdef int cython_recurse(int n) nogil:\n if n <= 0:\n return 0\n\n with nogil:\n return cython_recurse(n - 1)\n\ncython_recurse(2)\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)("pre",{children:[(0,s.jsx)(n.p,{children:"Fatal Python error: PyEval_SaveThread: NULL tstate"}),(0,s.jsx)(n.p,{children:'Thread 0x00007f499effd700 (most recent call first):\nFile "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run\nFile "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner\nFile "/usr/lib/python3.7/threading.py", line 890 in _bootstrap'})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["In practice, avoiding this issue is simple. First, ",(0,s.jsx)(n.code,{children:"nogil"})," functions probably shouldn't contain\n",(0,s.jsx)(n.code,{children:"with nogil"})," blocks. Second, Cython can\n",(0,s.jsx)(n.a,{href:"https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#conditional-acquiring-releasing-the-gil",children:"conditionally acquire/release"}),"\nthe GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for\n",(0,s.jsx)(n.a,{href:"https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil",children:"external C code"}),"\ncontains more detail on how to safely manage the GIL."]}),"\n",(0,s.jsxs)(n.p,{children:["To conclude: use Cython's ",(0,s.jsx)(n.code,{children:"nogil"})," annotation to assert that functions are safe for calling when the\nGIL is unlocked, and ",(0,s.jsx)(n.code,{children:"with nogil"})," to actually unlock the GIL and run those functions."]}),"\n",(0,s.jsx)(n.h2,{id:"numba",children:"Numba"}),"\n",(0,s.jsxs)(n.p,{children:["Like Cython, ",(0,s.jsx)(n.a,{href:"https://numba.pydata.org/",children:"Numba"}),' is a "compiled Python." Where Cython works by\ncompiling a Python-like language to C/C++, Numba compiles Python bytecode ',(0,s.jsx)(n.em,{children:"directly to machine code"}),"\nat runtime. Behavior is controlled with a special ",(0,s.jsx)(n.code,{children:"@jit"})," decorator; calling a decorated function\nfirst compiles it to machine code before running. Calling the function a second time re-uses that\nmachine code unless the argument types have changed."]}),"\n",(0,s.jsxs)(n.p,{children:["Numba works best when a ",(0,s.jsx)(n.code,{children:"nopython=True"})," argument is added to the ",(0,s.jsx)(n.code,{children:"@jit"})," decorator; functions\ncompiled in ",(0,s.jsx)(n.a,{href:"http://numba.pydata.org/numba-doc/latest/user/jit.html?#nopython",children:(0,s.jsx)(n.code,{children:"nopython"})})," mode\navoid the CPython API and have performance comparable to C. Further, adding ",(0,s.jsx)(n.code,{children:"nogil=True"})," to the\n",(0,s.jsx)(n.code,{children:"@jit"})," decorator unlocks the GIL while that function is running. Note that ",(0,s.jsx)(n.code,{children:"nogil"})," and ",(0,s.jsx)(n.code,{children:"nopython"}),"\nare separate arguments; while it is necessary for code to be compiled in ",(0,s.jsx)(n.code,{children:"nopython"})," mode in order to\nrelease the lock, the GIL will remain locked if ",(0,s.jsx)(n.code,{children:"nogil=False"})," (the default)."]}),"\n",(0,s.jsx)(n.p,{children:"Let's repeat the same experiment, this time using Numba instead of Cython:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"# The `int` type annotation is only for humans and is ignored\n# by Numba.\n@jit(nopython=True, nogil=True)\ndef numba_nogil(n: int) -> int:\n if n <= 1:\n return n\n\n a = 0\n b = 1\n\n c = a + b\n for _i in range(2, n):\n a = b\n b = c\n c = a + b\n\n return c\n\n\n# Run using `nopython` mode to receive a performance boost,\n# but GIL remains locked due to `nogil=False` by default.\n@jit(nopython=True)\ndef numba_gil(n: int) -> int:\n if n <= 1:\n return n\n\n a = 0\n b = 1\n\n c = a + b\n for _i in range(2, n):\n a = b\n b = c\n c = a + b\n\n return c\n\n\n# Call each function once to force compilation; we don't want\n# the timing statistics to include how long it takes to compile.\nnumba_nogil(N)\nnumba_gil(N);\n"})}),"\n",(0,s.jsx)(n.p,{children:"We'll perform the same tests as above; first, figure out how long it takes the function to run:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\n_ = numba_gil(N)\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 253 ms, sys: 258 \xb5s, total: 253 ms\nWall time: 251 ms"})}),"\n"]}),"\n",(0,s.jsx)("small",{children:(0,s.jsx)(n.p,{children:"Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be\neffectively identical after compilation."})}),"\n",(0,s.jsx)(n.p,{children:"When running two GIL-locked threads, the result (as expected) takes around twice as long to compute:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\nt1 = Thread(target=numba_gil, args=[N])\nt2 = Thread(target=numba_gil, args=[N])\nt1.start(); t2.start()\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms\nWall time: 541 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"But if the GIL-unlocking thread starts first, both threads run in parallel:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\nt1 = Thread(target=numba_nogil, args=[N])\nt2 = Thread(target=numba_gil, args=[N])\nt1.start(); t2.start()\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms\nWall time: 279 ms"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Just like Cython, starting the GIL-locked thread first leads to poor performance:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"%%time\nt1 = Thread(target=numba_gil, args=[N])\nt2 = Thread(target=numba_nogil, args=[N])\nt1.start(); t2.start()\nt1.join(); t2.join()\n"})}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)("pre",{children:(0,s.jsx)(n.p,{children:"CPU times: user 524 ms, sys: 0 ns, total: 524 ms\nWall time: 522 ms"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired;\nrecursively calling ",(0,s.jsx)(n.code,{children:"@jit(nogil=True)"})," functions is perfectly safe:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"from numba import jit\n\n@jit(nopython=True, nogil=True)\ndef numba_recurse(n: int) -> int:\n if n <= 0:\n return 0\n\n return numba_recurse(n - 1)\n\nnumba_recurse(2);\n"})}),"\n",(0,s.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(n.p,{children:"Before finishing, it's important to address pain points that will show up if these techniques are\nused in a more realistic project:"}),"\n",(0,s.jsxs)(n.p,{children:["First, code running in a GIL-free context will likely also need non-trivial data structures;\nGIL-free functions aren't useful if they're constantly interacting with Python objects whose access\nrequires the GIL. Cython provides\n",(0,s.jsx)(n.a,{href:"http://docs.cython.org/en/latest/src/tutorial/cdef_classes.html",children:"extension types"})," and Numba\nprovides a ",(0,s.jsx)(n.a,{href:"https://numba.pydata.org/numba-doc/dev/user/jitclass.html",children:(0,s.jsx)(n.code,{children:"@jitclass"})})," decorator to\naddress this need."]}),"\n",(0,s.jsx)(n.p,{children:"Second, building and distributing applications that make use of Cython/Numba can be complicated.\nCython packages require running the compiler, (potentially) linking/packaging external dependencies,\nand distributing a binary wheel. Numba is generally simpler because the code being distributed is\npure Python, but can be tricky since errors aren't detected until runtime."}),"\n",(0,s.jsxs)(n.p,{children:["Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba\nprovide tools to directly manage the GIL when appropriate. This enables true parallelism (not just\n",(0,s.jsx)(n.a,{href:"https://stackoverflow.com/a/1050257",children:"concurrency"}),") that is impossible in vanilla Python."]})]})}function d(e={}){let{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},65:function(e,n,t){t.d(n,{Z:function(){return o},a:function(){return a}});var i=t(7294);let s={},r=i.createContext(s);function a(e){let n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}},6160:function(e){e.exports=JSON.parse('{"permalink":"/2019/12/release-the-gil","source":"@site/blog/2019-12-14-release-the-gil/index.mdx","title":"Release the GIL","description":"Complaining about the Global Interpreter Lock","date":"2019-12-14T12:00:00.000Z","tags":[],"readingTime":8.58,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/12/release-the-gil","title":"Release the GIL","date":"2019-12-14T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"The webpack industrial complex","permalink":"/2011/11/webpack-industrial-complex"},"nextItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"}}')}}]); \ No newline at end of file diff --git a/assets/js/130b4a4b.8e30fd10.js b/assets/js/130b4a4b.8e30fd10.js new file mode 100644 index 0000000..24ed8b6 --- /dev/null +++ b/assets/js/130b4a4b.8e30fd10.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["294"],{6056:function(e,n,t){t.r(n),t.d(n,{assets:function(){return l},contentTitle:function(){return o},default:function(){return h},frontMatter:function(){return a},metadata:function(){return i},toc:function(){return c}});var i=t(7497),s=t(5893),r=t(65);let a={slug:"2018/09/primitives-in-rust-are-weird",title:"Primitives in Rust are weird (and cool)",date:new Date("2018-09-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Defining primitives (Java)",id:"defining-primitives-java",level:2},{value:"Low Level Handling of Primitives (C)",id:"low-level-handling-of-primitives-c",level:2},{value:"impl primitive (and Python)",id:"impl-primitive-and-python",level:2},{value:"Conclusion",id:"conclusion",level:2}];function d(e){let n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it\ncouldn't possibly run:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:'fn main() {\n println!("{}", 8.to_string())\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:"And to my complete befuddlement, it compiled, ran, and produced a completely sensible output."}),"\n",(0,s.jsxs)(n.p,{children:["The reason I was so surprised has to do with how Rust treats a special category of things I'm going to\ncall ",(0,s.jsx)(n.em,{children:"primitives"}),". In the current version of the Rust book, you'll see them referred to as\n",(0,s.jsx)(n.a,{href:"https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html#scalar-types",children:"scalars"}),", and in older versions they'll be called ",(0,s.jsx)(n.a,{href:"https://doc.rust-lang.org/book/first-edition/primitive-types.html",children:"primitives"}),", but\nwe're going to stick with the name ",(0,s.jsx)(n.em,{children:"primitive"})," for the time being. Explaining why this program is so\ncool requires talking about a number of other programming languages, and keeping a consistent\nterminology makes things easier."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"You've been warned:"})," this is going to be a tedious post about a relatively minor issue that\ninvolves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking\nabout with assembly."]}),"\n",(0,s.jsx)(n.h2,{id:"defining-primitives-java",children:"Defining primitives (Java)"}),"\n",(0,s.jsxs)(n.p,{children:["The reason I'm using the name ",(0,s.jsx)(n.em,{children:"primitive"})," comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special\nname for some specific types of values:"]}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"bool char byte\nshort int long\nfloat double\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["They are referred to as ",(0,s.jsx)(n.a,{href:"https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html",children:"primitives"}),". And relative to the other bits of Java,\nthey have two unique features. First, they don't have to worry about the\n",(0,s.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions",children:"billion-dollar mistake"}),";\nprimitives in Java can never be ",(0,s.jsx)(n.code,{children:"null"}),". Second: ",(0,s.jsx)(n.em,{children:"they can't have instance methods"}),".\nRemember that Rust program from earlier? Java has no idea what to do with it:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"class Main {\n public static void main(String[] args) {\n int x = 8;\n System.out.println(x.toString()); // Triggers a compiler error\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"The error is:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Main.java:5: error: int cannot be dereferenced\n System.out.println(x.toString());\n ^\n1 error\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Specifically, Java's ",(0,s.jsx)(n.a,{href:"https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html",children:(0,s.jsx)(n.code,{children:"Object"})}),"\nand things that inherit from it are pointers under the hood, and we have to dereference them before\nthe fields and methods they define can be used. In contrast, ",(0,s.jsx)(n.em,{children:"primitive types are just values"})," -\nthere's nothing to be dereferenced. In memory, they're just a sequence of bits."]}),"\n",(0,s.jsxs)(n.p,{children:["If we really want, we can turn the ",(0,s.jsx)(n.code,{children:"int"})," into an\n",(0,s.jsx)(n.a,{href:"https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html",children:(0,s.jsx)(n.code,{children:"Integer"})})," and then dereference\nit, but it's a bit wasteful:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-java",children:"class Main {\n public static void main(String[] args) {\n int x = 8;\n Integer y = Integer.valueOf(x);\n System.out.println(y.toString());\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This creates the variable ",(0,s.jsx)(n.code,{children:"y"})," of type ",(0,s.jsx)(n.code,{children:"Integer"})," (which inherits ",(0,s.jsx)(n.code,{children:"Object"}),"), and at run time we\ndereference ",(0,s.jsx)(n.code,{children:"y"})," to locate the ",(0,s.jsx)(n.code,{children:"toString()"})," function and call it. Rust obviously handles things a bit\ndifferently, but we have to dig into the low-level details to see it in action."]}),"\n",(0,s.jsx)(n.h2,{id:"low-level-handling-of-primitives-c",children:"Low Level Handling of Primitives (C)"}),"\n",(0,s.jsxs)(n.p,{children:["We first need to build a foundation for reading and understanding the assembly code the final answer\nrequires. Let's begin with showing how the ",(0,s.jsx)(n.code,{children:"C"}),' language (and your computer) thinks about "primitive"\nvalues in memory:']}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-c",children:"void my_function(int num) {}\n\nint main() {\n int x = 8;\n my_function(x);\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"https://godbolt.org/z/lgNYcc",children:"compiler explorer"})," gives us an easy way of showing off the\nassembly-level code that's generated: ",(0,s.jsx)("small",{children:"whose output has been lightly\nedited"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-nasm",children:"main:\n push rbp\n mov rbp, rsp\n sub rsp, 16\n\n ; We assign the value `8` to `x` here\n mov DWORD PTR [rbp-4], 8\n\n ; And copy the bits making up `x` to a location\n ; `my_function` can access (`edi`)\n mov eax, DWORD PTR [rbp-4]\n mov edi, eax\n\n ; Call `my_function` and give it control\n call my_function\n\n mov eax, 0\n leave\n ret\n\nmy_function:\n push rbp\n mov rbp, rsp\n\n ; Copy the bits out of the pre-determined location (`edi`)\n ; to somewhere we can use\n mov DWORD PTR [rbp-4], edi\n nop\n\n pop rbp\n ret\n"})}),"\n",(0,s.jsxs)(n.p,{children:["At a really low level of memory, we're copying bits around using the ",(0,s.jsx)(n.a,{href:"http://www.cs.virginia.edu/~evans/cs216/guides/x86.html",children:(0,s.jsx)(n.code,{children:"mov"})})," instruction;\nnothing crazy. But to show how similar Rust is, let's take a look at our program translated from C\nto Rust:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"fn my_function(x: i32) {}\n\nfn main() {\n let x = 8;\n my_function(x)\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["And the assembly generated when we stick it in the\n",(0,s.jsx)(n.a,{href:"https://godbolt.org/z/cAlmk0",children:"compiler explorer"}),": ",(0,s.jsx)("small",{children:"again, lightly\nedited"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-nasm",children:"example::main:\n push rax\n\n ; Look familiar? We're copying bits to a location for `my_function`\n ; The compiler just optimizes out holding `x` in memory\n mov edi, 8\n\n ; Call `my_function` and give it control\n call example::my_function\n\n pop rax\n ret\n\nexample::my_function:\n sub rsp, 4\n\n ; And copying those bits again, just like in C\n mov dword ptr [rsp], edi\n\n add rsp, 4\n ret\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The generated Rust assembly is functionally pretty close to the C assembly: ",(0,s.jsx)(n.em,{children:"When working with\nprimitives, we're just dealing with bits in memory"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to\ndereference. So what exactly is going on with this ",(0,s.jsx)(n.code,{children:".to_string()"})," function call?"]}),"\n",(0,s.jsx)(n.h2,{id:"impl-primitive-and-python",children:"impl primitive (and Python)"}),"\n",(0,s.jsxs)(n.p,{children:["Now it's time to ",(0,s.jsx)("strike",{children:"reveal my trap card"})," show the revelation that tied all this\ntogether: ",(0,s.jsx)(n.em,{children:"Rust has implementations for its primitive types."})," That's right, ",(0,s.jsx)(n.code,{children:"impl"})," blocks aren't\nonly for ",(0,s.jsx)(n.code,{children:"structs"})," and ",(0,s.jsx)(n.code,{children:"traits"}),", primitives get them too. Don't believe me? Check out\n",(0,s.jsx)(n.a,{href:"https://doc.rust-lang.org/std/primitive.u32.html",children:"u32"}),",\n",(0,s.jsx)(n.a,{href:"https://doc.rust-lang.org/std/primitive.f64.html",children:"f64"})," and\n",(0,s.jsx)(n.a,{href:"https://doc.rust-lang.org/std/primitive.char.html",children:"char"})," as examples."]}),"\n",(0,s.jsxs)(n.p,{children:["But the really interesting bit is how Rust turns those ",(0,s.jsx)(n.code,{children:"impl"})," blocks into assembly. Let's break out\nthe ",(0,s.jsx)(n.a,{href:"https://godbolt.org/z/6LBEwq",children:"compiler explorer"})," once again:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"pub fn main() {\n 8.to_string()\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["And the interesting bits in the assembly: ",(0,s.jsx)("small",{children:"heavily trimmed down"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-nasm",children:"example::main:\n sub rsp, 24\n mov rdi, rsp\n lea rax, [rip + .Lbyte_str.u]\n mov rsi, rax\n\n ; Cool stuff right here\n call ::to_string@PLT\n\n mov rdi, rsp\n call core::ptr::drop_in_place\n add rsp, 24\n ret\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Now, this assembly is a bit more complicated, but here's the big revelation: ",(0,s.jsxs)(n.strong,{children:["we're calling\n",(0,s.jsx)(n.code,{children:"to_string()"})," as a function that exists all on its own, and giving it the instance of ",(0,s.jsx)(n.code,{children:"8"})]}),". Instead\nof thinking of the value 8 as an instance of ",(0,s.jsx)(n.code,{children:"u32"})," and then peeking in to find the location of the\nfunction we want to call (like Java), we have a function that exists outside of the instance and\njust give that function the value ",(0,s.jsx)(n.code,{children:"8"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["This is an incredibly technical detail, but the interesting idea I had was this: ",(0,s.jsxs)(n.em,{children:["if ",(0,s.jsx)(n.code,{children:"to_string()"}),"\nis a static function, can I refer to the unbound function and give it an instance?"]})]}),"\n",(0,s.jsxs)(n.p,{children:["Better explained in code (and a ",(0,s.jsx)(n.a,{href:"https://godbolt.org/z/fJY-gA",children:"compiler explorer"})," link because I\nseriously love this thing):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",children:"struct MyVal {\n x: u32\n}\n\nimpl MyVal {\n fn to_string(&self) -> String {\n self.x.to_string()\n }\n}\n\npub fn main() {\n let my_val = MyVal { x: 8 };\n\n // THESE ARE THE SAME\n my_val.to_string();\n MyVal::to_string(&my_val);\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:'Rust is totally fine "binding" the function call to the instance, and also as a static.'}),"\n",(0,s.jsx)(n.p,{children:"MIND == BLOWN."}),"\n",(0,s.jsx)(n.p,{children:"Python does the same thing where I can both call functions bound to their instances and also call as\nan unbound function where I give it the instance:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"class MyClass():\n x = 24\n\n def my_function(self):\n print(self.x)\n\nm = MyClass()\n\nm.my_function()\nMyClass.my_function(m)\n"})}),"\n",(0,s.jsxs)(n.p,{children:["And Python tries to make you ",(0,s.jsx)(n.em,{children:"think"})," that primitives can have instance methods..."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:">>> dir(8)\n['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',\n'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__',\n...\n'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__',\n...]\n\n>>> # Theoretically `8.__str__()` should exist, but:\n\n>>> 8.__str__()\n File \"\", line 1\n 8.__str__()\n ^\nSyntaxError: invalid syntax\n\n>>> # It will run if we assign it first though:\n>>> x = 8\n>>> x.__str__()\n'8'\n"})}),"\n",(0,s.jsx)(n.p,{children:"...but in practice it's a bit complicated."}),"\n",(0,s.jsx)(n.p,{children:"So while Python handles binding instance methods in a way similar to Rust, it's still not able to\nrun the example we started with."}),"\n",(0,s.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(n.p,{children:"This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor\ndetails like primitives leads to really cool effects. Primitives are optimized like C in how they\nhave a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python\n(like both instance and late binding)."}),"\n",(0,s.jsxs)(n.p,{children:["And when you put it together, there are areas where Rust does cool things nobody else can; as a\nquirky feature of Rust's type system, ",(0,s.jsx)(n.code,{children:"8.to_string()"})," is actually valid code."]}),"\n",(0,s.jsx)(n.p,{children:"Now go forth and fool your friends into thinking you know assembly. This is all I've got."})]})}function h(e={}){let{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},65:function(e,n,t){t.d(n,{Z:function(){return o},a:function(){return a}});var i=t(7294);let s={},r=i.createContext(s);function a(e){let n=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}},7497:function(e){e.exports=JSON.parse('{"permalink":"/2018/09/primitives-in-rust-are-weird","source":"@site/blog/2018-09-01-primitives-in-rust-are-weird/index.mdx","title":"Primitives in Rust are weird (and cool)","description":"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it","date":"2018-09-01T12:00:00.000Z","tags":[],"readingTime":6.945,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/primitives-in-rust-are-weird","title":"Primitives in Rust are weird (and cool)","date":"2018-09-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"},"nextItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"}}')}}]); \ No newline at end of file diff --git a/assets/js/16c8da5a.6e786399.js b/assets/js/16c8da5a.6e786399.js new file mode 100644 index 0000000..eb6b5c5 --- /dev/null +++ b/assets/js/16c8da5a.6e786399.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["95"],{8066:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return o},metadata:function(){return i},toc:function(){return h}});var i=n(845),a=n(5893),s=n(65);let o={slug:"2018/06/dateutil-parser-to-rust",title:"What I learned porting dateutil to Rust",date:new Date("2018-06-25T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,l={authorsImageUrls:[void 0]},h=[{value:"Slow down, what?",id:"slow-down-what",level:2},{value:"Lost in Translation",id:"lost-in-translation",level:2},{value:"Using a young language",id:"using-a-young-language",level:2},{value:"Trial Maintenance Policy",id:"trial-maintenance-policy",level:2},{value:"Roadmap and Conclusion",id:"roadmap-and-conclusion",level:2}];function c(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(t.p,{children:["I've mostly been a lurker in Rust for a while, making a couple small contributions here and there.\nSo launching ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse",children:"dtparse"})," feels like nice step towards becoming a\nfunctioning member of society. But not too much, because then you know people start asking you to\npay bills, and ain't nobody got time for that."]}),"\n",(0,a.jsx)(t.p,{children:"But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you\nwhat to do with your life (but you should totally keep reading)."}),"\n",(0,a.jsx)(t.h2,{id:"slow-down-what",children:"Slow down, what?"}),"\n",(0,a.jsxs)(t.p,{children:["OK, fine, I guess I should start with ",(0,a.jsx)(t.em,{children:"why"})," someone would do this."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.a,{href:"https://github.com/dateutil/dateutil",children:"Dateutil"})," is a Python library for handling dates. The\nstandard library support for time in Python is kinda dope, but there are a lot of extras that go\ninto making it useful beyond just the ",(0,a.jsx)(t.a,{href:"https://docs.python.org/3.6/library/datetime.html",children:"datetime"}),"\nmodule. ",(0,a.jsx)(t.code,{children:"dateutil.parser"})," specifically is code to take all the super-weird time formats people come\nup with and turn them into something actually useful."]}),"\n",(0,a.jsxs)(t.p,{children:["Date/time parsing, it turns out, is just like everything else involving\n",(0,a.jsx)(t.a,{href:"https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time",children:"computers"})," and\n",(0,a.jsx)(t.a,{href:"https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time",children:"time"}),": it\nfeels like it shouldn't be that difficult to do, until you try to do it, and you realize that people\nsuck and this is why\n",(0,a.jsx)(t.a,{href:"https://zachholman.com/talk/utc-is-enough-for-everyone-right",children:"we can't we have nice things"}),". But\nalas, we'll try and make contemporary art out of the rubble and give it a pretentious name like\n",(0,a.jsx)(t.em,{children:"Time"}),"."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"A gravel mound",src:n(9394).Z+"",width:"800",height:"374"})}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://www.goodfreephotos.com/united-states/montana/elkhorn/remains-of-the-mining-operation-elkhorn.jpg.php",children:"Time"})}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["What makes ",(0,a.jsx)(t.code,{children:"dateutil.parser"})," great is that there's single function with a single argument that\ndrives what programmers interact with:\n",(0,a.jsx)(t.a,{href:"https://github.com/dateutil/dateutil/blob/6dde5d6298cfb81a4c594a38439462799ed2aef2/dateutil/parser/_parser.py#L1258",children:(0,a.jsx)(t.code,{children:"parse(timestr)"})}),'.\nIt takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can\npossibly do to make sense of your input" value. It doesn\'t expect much of you.']}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L1332",children:"And now it's in Rust."})}),"\n",(0,a.jsx)(t.h2,{id:"lost-in-translation",children:"Lost in Translation"}),"\n",(0,a.jsxs)(t.p,{children:["Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm\nadmittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can\nactually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better\nexperiences than\n",(0,a.jsx)(t.a,{href:"https://webcache.googleusercontent.com/search?q=cache:wkYMpktJtnUJ:https://jackstouffer.com/blog/porting_dateutil.html+&cd=3&hl=en&ct=clnk&gl=us",children:"this guy"}),"\nwho attempted the same thing for D. These are the actual take-aways:"]}),"\n",(0,a.jsxs)(t.p,{children:["When transcribing code, ",(0,a.jsx)(t.strong,{children:"stay as close to the original library as possible"}),". I'm talking about\nusing the same variable names, same access patterns, the whole shebang. It's way too easy to make a\ncouple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference\nmanual for verbatim what your code should be means that you don't spend that long debugging\ncomplicated logic, you're more looking for typos."]}),"\n",(0,a.jsxs)(t.p,{children:["Also, ",(0,a.jsx)(t.strong,{children:"don't use nice Rust things like enums"}),". While\n",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L88-L94",children:"one time it worked out OK for me"}),",\nI also managed to shoot myself in the foot a couple times because ",(0,a.jsx)(t.code,{children:"dateutil"})," stores AM/PM as a\nboolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In\ngeneral, writing nice code ",(0,a.jsx)(t.em,{children:"should not be a first-pass priority"})," when you're just trying to recreate\nthe same functionality."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"Exceptions are a pain."}),' Make peace with it. Python code is just allowed to skip stack frames. So\nwhen a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out\n',(0,a.jsx)(t.a,{href:"https://github.com/rust-lang/rfcs/pull/243",children:"he's not quite right"}),", and I'm OK with that. And while\n",(0,a.jsx)(t.code,{children:"dateutil"})," is pretty well-behaved about not skipping multiple stack frames,\n",(0,a.jsx)(t.a,{href:"https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L730-L865",children:"130-line try-catch blocks"}),"\ntake a while to verify."]}),"\n",(0,a.jsxs)(t.p,{children:["As another Python quirk, ",(0,a.jsxs)(t.strong,{children:["be very careful about\n",(0,a.jsx)(t.a,{href:"https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L494-L568",children:"long nested if-elif-else blocks"})]}),".\nI used to think that Python's whitespace was just there to get you to format your code correctly. I\nthink that no longer. It's way too easy to close a block too early and have incredibly weird issues\nin the logic. Make sure you use an editor that displays indentation levels so you can keep things\nstraight."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"Rust macros are not free."})," I originally had the\n",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/b0e737f088eca8e83ab4244c6621a2797d247697/tests/compat.rs#L63-L217",children:"main test body"}),"\nwrapped up in a macro using ",(0,a.jsx)(t.a,{href:"https://github.com/PyO3/PyO3",children:"pyo3"}),". It took two minutes to compile.\nAfter\n",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/e017018295c670e4b6c6ee1cfff00dbb233db47d/tests/compat.rs#L76-L205",children:"moving things to a function"}),"\ncompile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code\nto be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually\nfunctions that need to be liberated, man."]}),"\n",(0,a.jsxs)(t.p,{children:["Finally, ",(0,a.jsx)(t.strong,{children:"I really miss list comprehensions and dictionary comprehensions."})," As a quick comparison,\nsee\n",(0,a.jsx)(t.a,{href:"https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L476",children:"this dateutil code"}),"\nand\n",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L619-L629",children:"the implementation in Rust"}),".\nI probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be\nadded through macros or syntax extensions. Either way, they're expressive, save typing, and are\nsuper-readable. Let's get more of that."]}),"\n",(0,a.jsx)(t.h2,{id:"using-a-young-language",children:"Using a young language"}),"\n",(0,a.jsx)(t.p,{children:"Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On\nmore than one occasion though, I've had issues navigating the Rust ecosystem."}),"\n",(0,a.jsxs)(t.p,{children:['What I\'ll call the "canonical library" is still being built. In Python, if you need datetime\nparsing, you use ',(0,a.jsx)(t.code,{children:"dateutil"}),". If you want ",(0,a.jsx)(t.code,{children:"decimal"})," types, it's already in the\n",(0,a.jsx)(t.a,{href:"https://docs.python.org/3.6/library/decimal.html",children:"standard library"}),". While I might've gotten away\nwith ",(0,a.jsx)(t.code,{children:"f64"}),", ",(0,a.jsx)(t.code,{children:"dateutil"})," uses decimals, and I wanted to follow the principle of ",(0,a.jsx)(t.strong,{children:"staying as close to\nthe original library as possible"}),". Thus began my quest to find a decimal library in Rust. What I\nquickly found was summarized in a comment:"]}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsxs)(t.p,{children:["Writing a BigDecimal is easy. Writing a ",(0,a.jsx)(t.em,{children:"good"})," BigDecimal is hard."]}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.a,{href:"https://github.com/rust-lang/rust/issues/8937#issuecomment-34582794",children:"-cmr"})}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["In practice, this means that there are at least ",(0,a.jsx)(t.a,{href:"https://crates.io/crates/bigdecimal",children:"4"}),"\n",(0,a.jsx)(t.a,{href:"https://crates.io/crates/rust_decimal",children:"different"}),"\n",(0,a.jsx)(t.a,{href:"https://crates.io/crates/decimal",children:"implementations"})," ",(0,a.jsx)(t.a,{href:"https://crates.io/crates/decimate",children:"available"}),".\nAnd that's a lot of decisions to worry about when all I'm thinking is \"why can't\n",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Calendar_reform",children:"calendar reform"})," be a thing\" and I'm forced to dig\nthrough a ",(0,a.jsx)(t.a,{href:"https://github.com/rust-lang/rust/issues/8937#issuecomment-31661916",children:"couple"}),"\n",(0,a.jsx)(t.a,{href:"https://github.com/rust-lang/rfcs/issues/334",children:"different"}),"\n",(0,a.jsx)(t.a,{href:"https://github.com/rust-num/num/issues/8",children:"threads"})," to figure out if the library I'm look at is dead\nor just stable."]}),"\n",(0,a.jsxs)(t.p,{children:['And even when the "canonical library" exists, there\'s no guarantees that it will be well-maintained.\n',(0,a.jsx)(t.a,{href:"https://github.com/chronotope/chrono",children:"Chrono"})," is the ",(0,a.jsx)(t.em,{children:"de facto"})," date/time library in Rust, and just\nreleased version 0.4.4 like two days ago. Meanwhile,\n",(0,a.jsx)(t.a,{href:"https://github.com/chronotope/chrono-tz",children:"chrono-tz"})," appears to be dead in the water even though\n",(0,a.jsx)(t.a,{href:"https://github.com/chronotope/chrono-tz/issues/19",children:"there are people happy to help maintain it"}),". I\nknow relatively little about it, but it appears that most of the release process is automated;\nkeeping that up to date should be a no-brainer."]}),"\n",(0,a.jsx)(t.h2,{id:"trial-maintenance-policy",children:"Trial Maintenance Policy"}),"\n",(0,a.jsxs)(t.p,{children:['Specifically given "maintenance" being an\n',(0,a.jsx)(t.a,{href:"https://www.reddit.com/r/rust/comments/48540g/thoughts_on_initiators_vs_maintainers/",children:"oft-discussed"}),"\nissue, I'm going to try out the following policy to keep things moving on ",(0,a.jsx)(t.code,{children:"dtparse"}),":"]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsxs)(t.p,{children:["Issues/PRs needing ",(0,a.jsx)(t.em,{children:"maintainer"})," feedback will be updated at least weekly. I want to make sure\nnobody's blocking on me."]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsxs)(t.p,{children:["To keep issues/PRs needing ",(0,a.jsx)(t.em,{children:"contributor"})," feedback moving, I'm going to (kindly) ask the\ncontributor to check in after two weeks, and close the issue without resolution if I hear nothing\nback after a month."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"The second point I think has the potential to be a bit controversial, so I'm happy to receive\nfeedback on that. And if a contributor responds with \"hey, still working on it, had a kid and I'm\nrunning on 30 seconds of sleep a night,\" then first: congratulations on sustaining human life. And\nsecond: I don't mind keeping those requests going indefinitely. I just want to try and balance\nkeeping things moving with giving people the necessary time they need."}),"\n",(0,a.jsx)(t.p,{children:"I should also note that I'm still getting some best practices in place - CONTRIBUTING and\nCONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are\nperfect."}),"\n",(0,a.jsx)(t.h2,{id:"roadmap-and-conclusion",children:"Roadmap and Conclusion"}),"\n",(0,a.jsxs)(t.p,{children:["So if I've now built a ",(0,a.jsx)(t.code,{children:"dateutil"}),"-compatible parser, we're done, right? Of course not! That's not\nnearly ambitious enough."]}),"\n",(0,a.jsxs)(t.p,{children:["Ultimately, I'd love to have a library that's capable of parsing everything the Linux ",(0,a.jsx)(t.code,{children:"date"})," command\ncan do (and not ",(0,a.jsx)(t.code,{children:"date"})," on OSX, because seriously, BSD coreutils are the worst). I know Rust has a\ncoreutils rewrite going on, and ",(0,a.jsx)(t.code,{children:"dtparse"})," would potentially be an interesting candidate since it\ndoesn't bring in a lot of extra dependencies. ",(0,a.jsx)(t.a,{href:"https://crates.io/crates/humantime",children:(0,a.jsx)(t.code,{children:"humantime"})}),"\ncould help pick up some of the (current) slack in dtparse, so maybe we can share and care with each\nother?"]}),"\n",(0,a.jsx)(t.p,{children:"All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month\non redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going\nto take it hard."}),"\n",(0,a.jsx)(t.p,{children:"And in the mean time, I'm looking forward to building more. Onwards."})]})}function d(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},9394:function(e,t,n){n.d(t,{Z:function(){return i}});let i=n.p+"assets/images/gravel-mound-4afad8bdb1cd6b0e40dd2fd41adca36f.jpg"},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return o}});var i=n(7294);let a={},s=i.createContext(a);function o(e){let t=i.useContext(s);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(s.Provider,{value:t},e.children)}},845:function(e){e.exports=JSON.parse('{"permalink":"/2018/06/dateutil-parser-to-rust","source":"@site/blog/2018-06-25-dateutil-parser-to-rust/index.mdx","title":"What I learned porting dateutil to Rust","description":"I\'ve mostly been a lurker in Rust for a while, making a couple small contributions here and there.","date":"2018-06-25T12:00:00.000Z","tags":[],"readingTime":6.99,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/06/dateutil-parser-to-rust","title":"What I learned porting dateutil to Rust","date":"2018-06-25T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"},"nextItem":{"title":"Hello!","permalink":"/2018/05/hello"}}')}}]); \ No newline at end of file diff --git a/assets/js/1803684d.778a092f.js b/assets/js/1803684d.778a092f.js new file mode 100644 index 0000000..9c5860a --- /dev/null +++ b/assets/js/1803684d.778a092f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7624"],{3570:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return a},default:function(){return d},frontMatter:function(){return i},metadata:function(){return s},toc:function(){return h}});var s=n(510),o=n(5893),r=n(65);let i={slug:"2016/10/rustic-repodcasting",title:"A Rustic re-podcasting server",date:new Date("2016-10-22T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,l={authorsImageUrls:[void 0]},h=[{value:"The Setup",id:"the-setup",level:2},{value:"Issue 1: Strings",id:"issue-1-strings",level:2},{value:"Issue 2: Fighting with the borrow checker",id:"issue-2-fighting-with-the-borrow-checker",level:2},{value:"Conclusion",id:"conclusion",level:2}];function c(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,r.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"Learning Rust by fire (it sounds better than learning by corrosion)"}),"\n",(0,o.jsxs)(t.p,{children:["I listen to a lot of Drum and Bass music, because it's beautiful music. And\nthere's a particular site, ",(0,o.jsx)(t.a,{href:"http://bassdrive.com/",children:"Bassdrive.com"})," that hosts\na lot of great content. Specifically, the\n",(0,o.jsx)(t.a,{href:"http://archives.bassdrivearchive.com/",children:"archives"})," section of the site has a\nlist of the past shows that you can download and listen to. The issue is, it's\njust a ",(0,o.jsx)(t.a,{href:"http://archives.bassdrivearchive.com/6%20-%20Saturday/Electronic%20Warfare%20-%20The%20Overfiend/",children:"giant list of links to download"}),". I'd really like\nthis in a podcast format to take with me on the road, etc."]}),"\n",(0,o.jsxs)(t.p,{children:["So I wrote the ",(0,o.jsx)(t.a,{href:"https://github.com/bspeice/elektricity",children:"elektricity"})," web\napplication to actually accomplish all that. Whenever you request a feed, it\ngoes out to Bassdrive, processes all the links on a page, and serves up some\nfresh, tasty RSS to satisfy your ears. I hosted it on Heroku using the free\ntier because it's really not resource-intensive at all."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"The issue so far"})," is that I keep running out of free tier hours during a\nmonth because my podcasting application likes to have a server scan for new\nepisodes constantly. Not sure why it's doing that, but I don't have a whole\nlot of control over it. It's a phenomenal application otherwise."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"My (over-engineered) solution"}),": Re-write the application using the\n",(0,o.jsx)(t.a,{href:"https://www.rust-lang.org/en-US/",children:"Rust"})," programming language. I'd like to run\nthis on a small hacker board I own, and doing this in Rust would allow me to\neasily cross-compile it. Plus, I've been very interested in the Rust language\nfor a while and this would be a great opportunity to really learn it well.\nThe code is available ",(0,o.jsx)(t.a,{href:"https://github.com/bspeice/nutone",children:"here"})," as development\nprogresses."]}),"\n",(0,o.jsx)(t.h2,{id:"the-setup",children:"The Setup"}),"\n",(0,o.jsxs)(t.p,{children:["We'll be using the ",(0,o.jsx)(t.a,{href:"http://ironframework.io/",children:"iron"})," library to handle the\nserver, and ",(0,o.jsx)(t.a,{href:"http://hyper.rs/",children:"hyper"})," to fetch the data we need from elsewhere\non the interwebs. ",(0,o.jsx)(t.a,{href:"http://doc.servo.org/html5ever/index.html",children:"HTML5Ever"})," allows\nus to ingest the content that will be coming from Bassdrive, and finally,\noutput is done with ",(0,o.jsx)(t.a,{href:"http://sunng87.github.io/handlebars-rust/handlebars/index.html",children:"handlebars-rust"}),"."]}),"\n",(0,o.jsx)(t.p,{children:"It will ultimately be interesting to see how much more work must be done to\nactually get this working over another language like Python. Coming from a\ndynamic state of mind it's super easy to just chain stuff together, ship it out,\nand call it a day. I think I'm going to end up getting much dirtier trying to\nwrite all of this out."}),"\n",(0,o.jsx)(t.h2,{id:"issue-1-strings",children:"Issue 1: Strings"}),"\n",(0,o.jsxs)(t.p,{children:["Strings in Rust are hard. I acknowledge Python can get away with some things\nthat make strings super easy (and Python 3 has gotten better at cracking down\non some bad cases, ",(0,o.jsx)(t.code,{children:"str <-> bytes"})," specifically), but Rust is hard."]}),"\n",(0,o.jsxs)(t.p,{children:["Let's take for example the ",(0,o.jsx)(t.code,{children:"404"})," error handler I'm trying to write. The result\nshould be incredibly simple: All I want is to echo back\n",(0,o.jsx)(t.code,{children:"Didn't find URL: "}),". Shouldn't be that hard right? In Python I'd just do\nsomething like:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-python",children:'def echo_handler(request):\n return "You\'re visiting: {}".format(request.uri)\n'})}),"\n",(0,o.jsx)(t.p,{children:"And we'd call it a day. Rust isn't so simple. Let's start with the trivial\nexamples people post online:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'fn hello_world(req: &mut Request) -> IronResult {\n Ok(Response::with((status::Ok, "You found the server!")))\n}\n'})}),"\n",(0,o.jsxs)(t.p,{children:["Doesn't look too bad right? In fact, it's essentially the same as the Python\nversion! All we need to do is just send back a string of some form. So, we\nlook up the documentation for ",(0,o.jsx)(t.a,{href:"http://ironframework.io/doc/iron/request/struct.Request.html",children:(0,o.jsx)(t.code,{children:"Request"})})," and see a ",(0,o.jsx)(t.code,{children:"url"})," field that will contain\nwhat we want. Let's try the first iteration:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'fn hello_world(req: &mut Request) -> IronResult {\n Ok(Response::with((status::Ok, "You found the URL: " + req.url)))\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"Which yields the error:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error[E0369]: binary operation `+` cannot be applied to type `&'static str`\n"})}),"\n",(0,o.jsxs)(t.p,{children:["OK, what's going on here? Time to start Googling for ",(0,o.jsx)(t.a,{href:"https://www.google.com/#q=concatenate+strings+in+rust",children:'"concatenate strings in Rust"'}),". That's what we\nwant to do right? Concatenate a static string and the URL."]}),"\n",(0,o.jsxs)(t.p,{children:["After Googling, we come across a helpful ",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/std/macro.concat!.html",children:(0,o.jsx)(t.code,{children:"concat!"})})," macro that looks really nice! Let's try that one:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'fn hello_world(req: &mut Request) -> IronResult {\n Ok(Response::with((status::Ok, concat!("You found the URL: ", req.url))))\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"And the error:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error: expected a literal\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Turns out Rust actually blows up because the ",(0,o.jsx)(t.code,{children:"concat!"})," macro expects us to know\nat compile time what ",(0,o.jsx)(t.code,{children:"req.url"})," is. Which, in my outsider opinion, is a bit\nstrange. ",(0,o.jsx)(t.code,{children:"println!"})," and ",(0,o.jsx)(t.code,{children:"format!"}),", etc., all handle values they don't know at\ncompile time. Why can't ",(0,o.jsx)(t.code,{children:"concat!"}),"? By any means, we need a new plan of attack.\nHow about we try formatting strings?"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'fn hello_world(req: &mut Request) -> IronResult {\n Ok(Response::with((status::Ok, format!("You found the URL: {}", req.url))))\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"And at long last, it works. Onwards!"}),"\n",(0,o.jsx)(t.h2,{id:"issue-2-fighting-with-the-borrow-checker",children:"Issue 2: Fighting with the borrow checker"}),"\n",(0,o.jsxs)(t.p,{children:["Rust's single coolest feature is how the compiler can guarantee safety in your\nprogram. As long as you don't use ",(0,o.jsx)(t.code,{children:"unsafe"})," pointers in Rust, you're guaranteed\nsafety. And not having truly manual memory management is really cool; I'm\ntotally OK with never having to write ",(0,o.jsx)(t.code,{children:"malloc()"})," again."]}),"\n",(0,o.jsxs)(t.p,{children:["That said, even ",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/book/ownership.html",children:"the Rust documentation"})," makes a specific note:"]}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsx)(t.p,{children:"Many new users to Rust experience something we like to call\n\u2018fighting with the borrow checker\u2019, where the Rust compiler refuses to\ncompile a program that the author thinks is valid."}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"If you have to put it in the documentation, it's not a helpful note:\nit's hazing."}),"\n",(0,o.jsxs)(t.p,{children:["So now that we have a handler which works with information from the request, we\nwant to start making something that looks like an actual web application.\nThe router provided by ",(0,o.jsx)(t.code,{children:"iron"})," isn't terribly difficult so I won't cover it.\nInstead, the thing that had me stumped for a couple hours was trying to\ndynamically create routes."]}),"\n",(0,o.jsx)(t.p,{children:"The unfortunate thing with Rust (in my limited experience at the moment) is that\nthere is a severe lack of non-trivial examples. Using the router is easy when\nyou want to give an example of a static function. But how do you you start\nworking on things that are a bit more complex?"}),"\n",(0,o.jsxs)(t.p,{children:["We're going to cover that here. Our first try: creating a function which returns\nother functions. This is a principle called ",(0,o.jsx)(t.a,{href:"http://stackoverflow.com/a/36321/1454178",children:"currying"}),". We set up a function that allows us to keep some data in scope\nfor another function to come later."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:"fn build_handler(message: String) -> Fn(&mut Request) -> IronResult {\n move |_: &mut Request| {\n Ok(Response::with((status::Ok, message)))\n }\n}\n"})}),"\n",(0,o.jsxs)(t.p,{children:["We've simply set up a function that returns another anonymous function with the\n",(0,o.jsx)(t.code,{children:"message"})," parameter scoped in. If you compile this, you get not 1, not 2, but 5\nnew errors. 4 of them are the same though:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error[E0277]: the trait bound `for<'r, 'r, 'r> std::ops::Fn(&'r mut iron::Request<'r, 'r>) -> std::result::Result + 'static: std::marker::Sized` is not satisfied\n"})}),"\n",(0,o.jsx)(t.p,{children:"...oookay. I for one, am not going to spend time trying to figure out what's\ngoing on there."}),"\n",(0,o.jsxs)(t.p,{children:["And it is here that I will save the audience many hours of frustrated effort.\nAt this point, I decided to switch from ",(0,o.jsx)(t.code,{children:"iron"})," to pure ",(0,o.jsx)(t.code,{children:"hyper"})," since using\n",(0,o.jsx)(t.code,{children:"hyper"})," would give me a much simpler API. All I would have to do is build a\nfunction that took two parameters as input, and we're done. That said, it\nultimately posed many more issues because I started getting into a weird fight\nwith the ",(0,o.jsx)(t.code,{children:"'static"})," ",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/book/lifetimes.html",children:"lifetime"}),"\nand being a Rust newbie I just gave up on trying to understand it."]}),"\n",(0,o.jsxs)(t.p,{children:["Instead, we will abandon (mostly) the curried function attempt, and instead\ntake advantage of something Rust actually intends us to use: ",(0,o.jsx)(t.code,{children:"struct"})," and\n",(0,o.jsx)(t.code,{children:"trait"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Remember when I talked about a lack of non-trivial examples on the Internet?\nThis is what I was talking about. I could only find ",(0,o.jsx)(t.em,{children:"one"})," example of this\navailable online, and it was incredibly complex and contained code we honestly\ndon't need or care about. There was no documentation of how to build routes that\ndidn't use static functions, etc. But, I'm assuming you don't really care about\nmy whining, so let's get to it."]}),"\n",(0,o.jsxs)(t.p,{children:["The ",(0,o.jsx)(t.code,{children:"iron"})," documentation mentions the ",(0,o.jsx)(t.a,{href:"http://ironframework.io/doc/iron/middleware/trait.Handler.html",children:(0,o.jsx)(t.code,{children:"Handler"})})," trait as being something we can implement.\nDoes the function signature for that ",(0,o.jsx)(t.code,{children:"handle()"})," method look familiar? It's what\nwe've been working with so far."]}),"\n",(0,o.jsxs)(t.p,{children:["The principle is that we need to define a new ",(0,o.jsx)(t.code,{children:"struct"})," to hold our data, then\nimplement that ",(0,o.jsx)(t.code,{children:"handle()"})," method to return the result. Something that looks\nlike this might do:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'struct EchoHandler {\n message: String\n}\n\nimpl Handler for EchoHandler {\n fn handle(&self, _: &mut Request) -> IronResult {\n Ok(Response::with((status::Ok, self.message)))\n }\n}\n\n// Later in the code when we set up the router...\nlet echo = EchoHandler {\n message: "Is it working yet?"\n}\nrouter.get("/", echo.handle, "index");\n'})}),"\n",(0,o.jsxs)(t.p,{children:["We attempt to build a struct, and give its ",(0,o.jsx)(t.code,{children:"handle"})," method off to the router\nso the router knows what to do."]}),"\n",(0,o.jsx)(t.p,{children:"You guessed it, more errors:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error: attempted to take value of method `handle` on type `EchoHandler`\n"})}),"\n",(0,o.jsx)(t.p,{children:"Now, the Rust compiler is actually a really nice fellow, and offers us help:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" help: maybe a `()` to call it is missing? If not, try an anonymous function\n"})}),"\n",(0,o.jsx)(t.p,{children:"We definitely don't want to call that function, so maybe try an anonymous\nfunction as it recommends?"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'router.get("/", |req: &mut Request| echo.handle(req), "index");\n'})}),"\n",(0,o.jsx)(t.p,{children:"Another error:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error[E0373]: closure may outlive the current function, but it borrows `echo`, which is owned by the current function\n"})}),"\n",(0,o.jsx)(t.p,{children:"Another helpful message:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" help: to force the closure to take ownership of `echo` (and any other referenced variables), use the `move` keyword\n"})}),"\n",(0,o.jsx)(t.p,{children:"We're getting closer though! Let's implement this change:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:'router.get("/", move |req: &mut Request| echo.handle(req), "index");\n'})}),"\n",(0,o.jsx)(t.p,{children:"And here's where things get strange:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:" error[E0507]: cannot move out of borrowed content\n --\x3e src/main.rs:18:40\n |\n 18 | Ok(Response::with((status::Ok, self.message)))\n | ^^^^ cannot move out of borrowed content\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Now, this took me another couple hours to figure out. I'm going to explain it,\nbut ",(0,o.jsx)(t.strong,{children:"keep this in mind: Rust only allows one reference at a time"})," (exceptions\napply of course)."]}),"\n",(0,o.jsxs)(t.p,{children:["When we attempt to use ",(0,o.jsx)(t.code,{children:"self.message"})," as it has been created in the earlier\n",(0,o.jsx)(t.code,{children:"struct"}),", we essentially are trying to give it away to another piece of code.\nRust's semantics then state that ",(0,o.jsx)(t.em,{children:"we may no longer access it"})," unless it is\nreturned to us (which ",(0,o.jsx)(t.code,{children:"iron"}),"'s code does not do). There are two ways to fix\nthis:"]}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsxs)(t.li,{children:["Only give away references (i.e. ",(0,o.jsx)(t.code,{children:"&self.message"})," instead of ",(0,o.jsx)(t.code,{children:"self.message"}),")\ninstead of transferring ownership"]}),"\n",(0,o.jsx)(t.li,{children:"Make a copy of the underlying value which will be safe to give away"}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["I didn't know these were the two options originally, so I hope this helps the\naudience out. Because ",(0,o.jsx)(t.code,{children:"iron"})," won't accept a reference, we are forced into the\nsecond option: making a copy. To do so, we just need to change the function\nto look like this:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-rust",children:"Ok(Response::with((status::Ok, self.message.clone())))\n"})}),"\n",(0,o.jsx)(t.p,{children:"Not so bad, huh? My only complaint is that it took so long to figure out exactly\nwhat was going on."}),"\n",(0,o.jsx)(t.p,{children:"And now we have a small server that we can configure dynamically. At long last."}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsxs)(t.p,{children:["Final sidenote: You can actually do this without anonymous functions. Just\nchange the router line to:\n",(0,o.jsx)(t.code,{children:'router.get("/", echo, "index");'})]}),"\n",(0,o.jsxs)(t.p,{children:["Rust's type system seems to figure out that we want to use the ",(0,o.jsx)(t.code,{children:"handle()"})," method."]}),"\n"]}),"\n",(0,o.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,o.jsx)(t.p,{children:"After a good long days' work, we now have the routing functionality set up on\nour application. We should be able to scale this pretty well in the future:\nthe RSS content we need to deliver in the future can be treated as a string, so\nthe building blocks are in place."}),"\n",(0,o.jsx)(t.p,{children:"There are two important things I learned starting with Rust today:"}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsx)(t.li,{children:"Rust is a new language, and while the code is high-quality, the mindshare is coming."}),"\n",(0,o.jsx)(t.li,{children:"I'm a terrible programmer."}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:["Number 1 is pretty obvious and not surprising to anyone. Number two caught me\noff guard. I've gotten used to having either a garbage collector (Java, Python,\netc.) or playing a little fast and loose with scoping rules (C, C++). You don't\nhave to worry about object lifetime there. With Rust, it's forcing me to fully\nunderstand and use well the memory in my applications. In the final mistake I\nfixed (using ",(0,o.jsx)(t.code,{children:".clone()"}),') I would have been fine in C++ to just give away that\nreference and never use it again. I wouldn\'t have run into a "use-after-free"\nerror, but I would have potentially been leaking memory. Rust forced me to be\nincredibly precise about how I use it.']}),"\n",(0,o.jsx)(t.p,{children:"All said I'm excited for using Rust more. I think it's super cool, it's just\ngoing to take me a lot longer to do this than I originally thought."})]})}function d(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return i}});var s=n(7294);let o={},r=s.createContext(o);function i(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(r.Provider,{value:t},e.children)}},510:function(e){e.exports=JSON.parse('{"permalink":"/2016/10/rustic-repodcasting","source":"@site/blog/2016-10-22-rustic-repodcasting/index.mdx","title":"A Rustic re-podcasting server","description":"Learning Rust by fire (it sounds better than learning by corrosion)","date":"2016-10-22T12:00:00.000Z","tags":[],"readingTime":10.405,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/10/rustic-repodcasting","title":"A Rustic re-podcasting server","date":"2016-10-22T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"},"nextItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"}}')}}]); \ No newline at end of file diff --git a/assets/js/1806d708.22f71128.js b/assets/js/1806d708.22f71128.js new file mode 100644 index 0000000..6b867c3 --- /dev/null +++ b/assets/js/1806d708.22f71128.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["3241"],{1859:function(e,n,s){s.r(n),s.d(n,{assets:function(){return o},contentTitle:function(){return l},default:function(){return h},frontMatter:function(){return r},metadata:function(){return a},toc:function(){return m}});var a=s(8279),i=s(5893),t=s(65);let r={slug:"2015/11/autocallable",title:"Autocallable Bonds",date:new Date("2015-11-27T12:00:00.000Z"),authors:["bspeice"],tags:[]},l=void 0,o={authorsImageUrls:[void 0]},m=[{value:"Underlying simulation",id:"underlying-simulation",level:2},{value:"Defining the simulation",id:"defining-the-simulation",level:3},{value:"Example simulation",id:"example-simulation",level:3},{value:"Computing the term structure",id:"computing-the-term-structure",level:3},{value:"Illustrating the term structure",id:"illustrating-the-term-structure",level:3},{value:"The full underlying simulation",id:"the-full-underlying-simulation",level:3},{value:"Final simulation",id:"final-simulation",level:3},{value:"Athena Simulation",id:"athena-simulation",level:2},{value:"Phoenix without Memory Simulation",id:"phoenix-without-memory-simulation",level:2},{value:"Phoenix with Memory Simulation",id:"phoenix-with-memory-simulation",level:2}];function c(e){let n={a:"a",annotation:"annotation",code:"code",h1:"h1",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",math:"math",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",msub:"msub",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products."}),"\n",(0,i.jsx)(n.p,{children:"My only non-core class this semester has been in Structure Products. We've been surveying a wide variety of products, and the final project was to pick one to report on.\nBecause these are all very similar, we decided to demonstrate all 3 products at once."}),"\n",(0,i.jsxs)(n.p,{children:["What follows below is a notebook demonstrating the usage of ",(0,i.jsx)(n.a,{href:"http://julialang.com",children:"Julia"})," for Monte-Carlo simulation of some exotic products."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:"using Gadfly\n"})}),"\n",(0,i.jsx)(n.h1,{id:"athenaphoenix-simulation",children:"Athena/Phoenix Simulation"}),"\n",(0,i.jsx)(n.h2,{id:"underlying-simulation",children:"Underlying simulation"}),"\n",(0,i.jsxs)(n.p,{children:["In order to price the autocallable bonds, we need to simulate the underlying assets. Let's go ahead and set up the simulation first, as this lays the foundation for what we're trying to do. We're going to use ",(0,i.jsx)(n.a,{href:"http://finance.yahoo.com/q?s=jnj",children:"JNJ"})," as the basis for our simulation. This implies the following parameters:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsxs)(n.msub,{children:[(0,i.jsx)(n.mi,{children:"S"}),(0,i.jsx)(n.mn,{children:"0"})]})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"S_0"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(n.span,{className:"mord",children:[(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.05764em"},children:"S"}),(0,i.jsx)(n.span,{className:"msupsub",children:(0,i.jsxs)(n.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(n.span,{className:"vlist-r",children:[(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.3011em"},children:(0,i.jsxs)(n.span,{style:{top:"-2.55em",marginLeft:"-0.0576em",marginRight:"0.05em"},children:[(0,i.jsx)(n.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(n.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(n.span,{className:"mord mtight",children:"0"})})]})}),(0,i.jsx)(n.span,{className:"vlist-s",children:"\u200B"})]}),(0,i.jsx)(n.span,{className:"vlist-r",children:(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(n.span,{})})})]})})]})]})})]})," = $102.2 (as of time of writing)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"q"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"q"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"q"})]})})]})," = 2.84%"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"r"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"r"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"})]})})]})," = [.49, .9, 1.21, 1.45, 1.69] (term structure as of time of writing, linear interpolation)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"\u03BC"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"\\mu"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"\u03BC"})]})})]})," = ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"r"}),(0,i.jsx)(n.mo,{children:"\u2212"}),(0,i.jsx)(n.mi,{children:"q"})]}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"r - q"})]})})}),(0,i.jsxs)(n.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.6667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(n.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"q"})]})]})]})," (note that this implies a negative drift because of current low rates)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"\u03C3"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"\\sigma"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C3"})]})})]})," = ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsxs)(n.msub,{children:[(0,i.jsx)(n.mi,{children:"\u03C3"}),(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"i"}),(0,i.jsx)(n.mi,{children:"m"}),(0,i.jsx)(n.mi,{children:"p"})]})]})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"\\sigma_{imp}"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.7167em",verticalAlign:"-0.2861em"}}),(0,i.jsxs)(n.span,{className:"mord",children:[(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C3"}),(0,i.jsx)(n.span,{className:"msupsub",children:(0,i.jsxs)(n.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(n.span,{className:"vlist-r",children:[(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.3117em"},children:(0,i.jsxs)(n.span,{style:{top:"-2.55em",marginLeft:"-0.0359em",marginRight:"0.05em"},children:[(0,i.jsx)(n.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(n.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(n.span,{className:"mord mtight",children:[(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"im"}),(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"p"})]})})]})}),(0,i.jsx)(n.span,{className:"vlist-s",children:"\u200B"})]}),(0,i.jsx)(n.span,{className:"vlist-r",children:(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.2861em"},children:(0,i.jsx)(n.span,{})})})]})})]})]})})]})," = 15.62% (from VIX implied volatility)"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"We additionally define some parameters for simulation:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"T"}),": The number of years to simulate"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"m"}),": The number of paths to simulate"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"n"}),": The number of steps to simulate in a year"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:"S0 = 102.2\nnominal = 100\nq = 2.84 / 100\n\u03C3 = 15.37 / 100\nterm = [0, .49, .9, 1.21, 1.45, 1.69] / 100 + 1\n\n###\n# Potential: Based on PEP\n# S0 = 100.6\n# \u03C3 = 14.86\n# q = 2.7\n###\n\n# Simulation parameters\nT = 5 # Using years as the unit of time\nn = 250 # simulations per year\nm = 100000 # paths\nnum_simulations = 5; # simulation rounds per price\n"})}),"\n",(0,i.jsx)(n.h3,{id:"defining-the-simulation",children:"Defining the simulation"}),"\n",(0,i.jsx)(n.p,{children:"To make things simpler, we simulate a single year at a time. This allows us to easily add in a dividend policy without too much difficulty, and update the simulation every year to match the term structure. The underlying uses GBM for simulation between years."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'simulate_gbm = function(S0, \u03BC, \u03C3, T, n)\n # Set the initial state\n m = length(S0)\n t = T / n\n motion = zeros(m, n)\n motion[:,1] = S0\n \n # Build out all states\n for i=1:(n-1)\n motion[:,i+1] = motion[:,i] .* exp((\u03BC - \u03C3^2/2)*t) .* exp(sqrt(t) * \u03C3 .* randn(m))\n end\n \n return motion\nend\n\nfunction display_motion(motion, T)\n # Given a matrix of paths, display the motion\n n = length(motion[1,:])\n m = length(motion[:,1])\n x = repmat(1:n, m)\n \n # Calculate the ticks we\'re going to use. We\'d like to\n # have an xtick every month, so calculate where those\n # ticks will actually be at.\n if (T > 3)\n num_ticks = T\n xlabel = "Years"\n else\n num_ticks = T * 12\n xlabel = "Months"\n end\n tick_width = n / num_ticks\n x_ticks = []\n for i=1:round(num_ticks)\n x_ticks = vcat(x_ticks, i*tick_width)\n end\n \n # Use one color for each path. I\'m not sure if there\'s\n # a better way to do this without going through DataFrames\n colors = []\n for i = 1:m\n colors = vcat(colors, ones(n)*i)\n end\n \n plot(x=x, y=motion\', color=colors, Geom.line,\n Guide.xticks(ticks=x_ticks, label=false),\n Guide.xlabel(xlabel),\n Guide.ylabel("Value"))\nend;\n'})}),"\n",(0,i.jsx)(n.h3,{id:"example-simulation",children:"Example simulation"}),"\n",(0,i.jsx)(n.p,{children:"Let's go ahead and run a sample simulation to see what the functions got us!"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:"initial = ones(5) * S0\n# Using \u03BC=0, T=.25 for now, we'll use the proper values later\nmotion = simulate_gbm(initial, 0, \u03C3, .25, 200) \n\ndisplay_motion(motion, .25)\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:s(1960).Z+"",width:"535",height:"378"})}),"\n",(0,i.jsx)(n.h3,{id:"computing-the-term-structure",children:"Computing the term structure"}),"\n",(0,i.jsx)(n.p,{children:"Now that we've got the basic motion set up, let's start making things a bit more sophisticated for the model. We're going to assume that the drift of the stock is the difference between the implied forward rate and the quarterly dividend rate."}),"\n",(0,i.jsx)(n.p,{children:"We're given the yearly term structure, and need to calculate the quarterly forward rate to match this structure. The term structure is assumed to follow:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"d"}),(0,i.jsx)(n.mo,{stretchy:"false",children:"("}),(0,i.jsx)(n.mn,{children:"0"}),(0,i.jsx)(n.mo,{separator:"true",children:","}),(0,i.jsx)(n.mi,{children:"t"}),(0,i.jsx)(n.mo,{stretchy:"false",children:")"}),(0,i.jsx)(n.mo,{children:"="}),(0,i.jsx)(n.mi,{children:"d"}),(0,i.jsx)(n.mo,{stretchy:"false",children:"("}),(0,i.jsx)(n.mn,{children:"0"}),(0,i.jsx)(n.mo,{separator:"true",children:","}),(0,i.jsx)(n.mi,{children:"t"}),(0,i.jsx)(n.mo,{children:"\u2212"}),(0,i.jsx)(n.mn,{children:"1"}),(0,i.jsx)(n.mo,{stretchy:"false",children:")"}),(0,i.jsx)(n.mo,{children:"\u22C5"}),(0,i.jsxs)(n.msub,{children:[(0,i.jsx)(n.mi,{children:"f"}),(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"i"}),(0,i.jsx)(n.mo,{children:"\u2212"}),(0,i.jsx)(n.mn,{children:"1"}),(0,i.jsx)(n.mo,{separator:"true",children:","}),(0,i.jsx)(n.mi,{children:"i"})]})]})]}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"d(0, t) = d(0,t-1)\\cdot f_{i-1, i}"})]})})}),(0,i.jsxs)(n.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"d"}),(0,i.jsx)(n.span,{className:"mopen",children:"("}),(0,i.jsx)(n.span,{className:"mord",children:"0"}),(0,i.jsx)(n.span,{className:"mpunct",children:","}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"t"}),(0,i.jsx)(n.span,{className:"mclose",children:")"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(n.span,{className:"mrel",children:"="}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"d"}),(0,i.jsx)(n.span,{className:"mopen",children:"("}),(0,i.jsx)(n.span,{className:"mord",children:"0"}),(0,i.jsx)(n.span,{className:"mpunct",children:","}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"t"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(n.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,i.jsx)(n.span,{className:"mord",children:"1"}),(0,i.jsx)(n.span,{className:"mclose",children:")"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(n.span,{className:"mbin",children:"\u22C5"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.9805em",verticalAlign:"-0.2861em"}}),(0,i.jsxs)(n.span,{className:"mord",children:[(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.10764em"},children:"f"}),(0,i.jsx)(n.span,{className:"msupsub",children:(0,i.jsxs)(n.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(n.span,{className:"vlist-r",children:[(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.3117em"},children:(0,i.jsxs)(n.span,{style:{top:"-2.55em",marginLeft:"-0.1076em",marginRight:"0.05em"},children:[(0,i.jsx)(n.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(n.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(n.span,{className:"mord mtight",children:[(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"i"}),(0,i.jsx)(n.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(n.span,{className:"mord mtight",children:"1"}),(0,i.jsx)(n.span,{className:"mpunct mtight",children:","}),(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"i"})]})})]})}),(0,i.jsx)(n.span,{className:"vlist-s",children:"\u200B"})]}),(0,i.jsx)(n.span,{className:"vlist-r",children:(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.2861em"},children:(0,i.jsx)(n.span,{})})})]})})]})]})]})]})}),"\n",(0,i.jsxs)(n.p,{children:["Where ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsxs)(n.msub,{children:[(0,i.jsx)(n.mi,{children:"f"}),(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"i"}),(0,i.jsx)(n.mo,{children:"\u2212"}),(0,i.jsx)(n.mn,{children:"1"}),(0,i.jsx)(n.mo,{separator:"true",children:","}),(0,i.jsx)(n.mi,{children:"i"})]})]})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"f_{i-1, i}"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.9805em",verticalAlign:"-0.2861em"}}),(0,i.jsxs)(n.span,{className:"mord",children:[(0,i.jsx)(n.span,{className:"mord mathnormal",style:{marginRight:"0.10764em"},children:"f"}),(0,i.jsx)(n.span,{className:"msupsub",children:(0,i.jsxs)(n.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(n.span,{className:"vlist-r",children:[(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.3117em"},children:(0,i.jsxs)(n.span,{style:{top:"-2.55em",marginLeft:"-0.1076em",marginRight:"0.05em"},children:[(0,i.jsx)(n.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(n.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(n.span,{className:"mord mtight",children:[(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"i"}),(0,i.jsx)(n.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(n.span,{className:"mord mtight",children:"1"}),(0,i.jsx)(n.span,{className:"mpunct mtight",children:","}),(0,i.jsx)(n.span,{className:"mord mathnormal mtight",children:"i"})]})})]})}),(0,i.jsx)(n.span,{className:"vlist-s",children:"\u200B"})]}),(0,i.jsx)(n.span,{className:"vlist-r",children:(0,i.jsx)(n.span,{className:"vlist",style:{height:"0.2861em"},children:(0,i.jsx)(n.span,{})})})]})})]})]})})]})," is the quarterly forward rate."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:"forward_term = function(yearly_term)\n # It is assumed that we have a yearly term structure passed in, and starts at year 0\n # This implies a nominal rate above 0 for the first year!\n years = length(term)-1 # because we start at 0\n structure = [(term[i+1] / term[i]) for i=1:years]\nend;\n"})}),"\n",(0,i.jsx)(n.h3,{id:"illustrating-the-term-structure",children:"Illustrating the term structure"}),"\n",(0,i.jsx)(n.p,{children:"Now that we've got our term structure, let's validate that we're getting the correct results! If we've done this correctly, then:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"term[2] == term[1] * structure[1]\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'# Example term structure taken from:\n# http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield\n# Linear interpolation used years in-between periods, assuming real-dollar\n# interest rates\nforward_yield = forward_term(term)\ncalculated_term2 = term[1] * forward_yield[1]\n\nprintln("Actual term[2]: $(term[2]); Calculated term[2]: $(calculated_term2)")\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:" Actual term[2]: 1.0049; Calculated term[2]: 1.0049\n"})}),"\n",(0,i.jsx)(n.h3,{id:"the-full-underlying-simulation",children:"The full underlying simulation"}),"\n",(0,i.jsx)(n.p,{children:"Now that we have the term structure set up, we can actually start doing some real simulation! Let's construct some paths through the full 5-year time frame. In order to do this, we will simulate 1 year at a time, and use the forward rates at those times to compute the drift. Thus, there will be 5 total simulations batched together."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:"full_motion = ones(5) * S0\nfull_term = vcat(term[1], forward_yield)\nfor i=1:T\n \u03BC = (full_term[i] - 1 - q)\n year_motion = simulate_gbm(full_motion[:,end], \u03BC, \u03C3, 1, n)\n full_motion = hcat(full_motion, year_motion)\nend\n\ndisplay_motion(full_motion, T)\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{src:s(7363).Z+"",width:"535",height:"378"})}),"\n",(0,i.jsx)(n.h3,{id:"final-simulation",children:"Final simulation"}),"\n",(0,i.jsx)(n.p,{children:"We're now going to actually build out the full motion that we'll use for computing the pricing of our autocallable products. It will be largely the same, but we will use far more sample paths for the simulation."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'full_simulation = function(S0, T, n, m, term)\n forward = vcat(term[1], forward_term(term))\n\n # And an S0 to kick things off.\n final_motion = ones(m) * S0\n for i=1:T\n \u03BC = (forward[i] - 1 - q)\n year_motion = simulate_gbm(final_motion[:,end], \u03BC, \u03C3, 1, n)\n final_motion = hcat(final_motion, year_motion)\n end\n return final_motion\nend\n\ntic()\nfull_simulation(S0, T, n, m, term)\ntime = toq()\n@printf("Time to run simulation: %.2fs", time)\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:" Time to run simulation: 5.34s\n"})}),"\n",(0,i.jsx)(n.h2,{id:"athena-simulation",children:"Athena Simulation"}),"\n",(0,i.jsx)(n.p,{children:"Now that we've defined our underlying simulation, let's actually try and price an Athena note. Athena has the following characteristics:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Automatically called if the underlying is above the ",(0,i.jsx)(n.strong,{children:"call barrier"})," at observation"]}),"\n",(0,i.jsxs)(n.li,{children:["Accelerated coupon paid if the underlying is above the ",(0,i.jsx)(n.strong,{children:"call barrier"})," at observation","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The coupon paid is ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsxs)(n.mrow,{children:[(0,i.jsx)(n.mi,{children:"c"}),(0,i.jsx)(n.mo,{children:"\u22C5"}),(0,i.jsx)(n.mi,{children:"i"})]}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"c \\cdot i"})]})})}),(0,i.jsxs)(n.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.4445em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"c"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(n.span,{className:"mbin",children:"\u22C5"}),(0,i.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.6595em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"i"})]})]})]})," with ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"i"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"i"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.6595em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"i"})]})})]})," as the current year, and ",(0,i.jsxs)(n.span,{className:"katex",children:[(0,i.jsx)(n.span,{className:"katex-mathml",children:(0,i.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(n.semantics,{children:[(0,i.jsx)(n.mrow,{children:(0,i.jsx)(n.mi,{children:"c"})}),(0,i.jsx)(n.annotation,{encoding:"application/x-tex",children:"c"})]})})}),(0,i.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(n.span,{className:"base",children:[(0,i.jsx)(n.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(n.span,{className:"mord mathnormal",children:"c"})]})})]})," the coupon rate"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Principle protection up until a ",(0,i.jsx)(n.strong,{children:"protection barrier"})," at observation; All principle at risk if this barrier not met"]}),"\n",(0,i.jsx)(n.li,{children:"Observed yearly"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'call_barrier = S0\nstrike = S0\nprotection_barrier = S0 * .6\ncoupon = nominal * .07\n\nprice_athena = function(initial_price, year_prices, call_barrier,\n protection_barrier, coupon, forward_structure)\n\n total_coupons = 0\n \n t = length(year_prices)\n\n for i=1:t\n price = year_prices[i]\n if price \u2265 call_barrier\n return (nominal + coupon*i) * exp((prod(forward_structure[i:end])-1)*(t-i))\n end\n end\n\n # We\'ve reached maturity, time to check capital protection\n if year_prices[end] > protection_barrier\n return nominal\n else\n put = (strike - year_prices[end]) / strike\n return nominal*(1-put)\n end\nend\n\nforward_structure = forward_term(term)\nprice_function = (year_prices) -> price_athena(S0, year_prices,\n call_barrier, protection_barrier, coupon, forward_structure)\n\nathena = function()\n year_indexes = [n*i for i=1:T]\n motion = full_simulation(S0, T, n, m, term)\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\n return mean(payoffs)\nend\n\nmean_payoffs = zeros(num_simulations)\nfor i=1:num_simulations\n tic()\n mean_payoffs[i] = athena()\n time = toq()\n @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time)\nend\n\nfinal_mean = mean(mean_payoffs)\nprintln("Mean over $num_simulations simulations: $(mean(mean_payoffs))")\npv = final_mean * (exp(-(prod(forward_structure)-1)*T))\n@printf("Present value of Athena note: \\$%.2f, notional: \\$%.2f", pv, nominal)\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:" Mean of simulation 1: $103.2805; Simulation time: 5.59s\n Mean of simulation 2: $103.3796; Simulation time: 5.05s\n Mean of simulation 3: $103.4752; Simulation time: 5.18s\n Mean of simulation 4: $103.4099; Simulation time: 5.37s\n Mean of simulation 5: $103.3260; Simulation time: 5.32s\n Mean over 5 simulations: 103.37421610015554\n Present value of Athena note: $95.00, notional: $100.00\n"})}),"\n",(0,i.jsx)(n.h2,{id:"phoenix-without-memory-simulation",children:"Phoenix without Memory Simulation"}),"\n",(0,i.jsx)(n.p,{children:"Let's move into pricing a Phoenix without memory. It's very similar to the Athena production, with the exception that we introduce a coupon barrier so coupons are paid even when the underlying is below the initial price."}),"\n",(0,i.jsxs)(n.p,{children:["The Phoenix product has the following characteristics (example ",(0,i.jsx)(n.a,{href:"https://www.rbccm.com/usstructurednotes/file-780079.pdf",children:"here"}),"):"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Automatically called if the underlying is above the ",(0,i.jsx)(n.strong,{children:"call barrier"})," at observation"]}),"\n",(0,i.jsxs)(n.li,{children:["Coupon paid if the underlying is above a ",(0,i.jsx)(n.strong,{children:"coupon barrier"})," at observation"]}),"\n",(0,i.jsxs)(n.li,{children:["Principle protection up until a ",(0,i.jsx)(n.strong,{children:"protection barrier"})," at observation; All principle at risk if this barrier not met"]}),"\n",(0,i.jsx)(n.li,{children:"Observed yearly"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Some example paths (all assume that a call barrier of the current price, and coupon barrier some level below that):"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"At the end of year 1, the stock is above the call barrier; the note is called and you receive the value of the stock plus the coupon being paid."}),"\n",(0,i.jsx)(n.li,{children:"At the end of year 1, the stock is above the coupon barrier, but not the call barrier; you receive the coupon. At the end of year 2, the stock is below the coupon barrier; you receive nothing. At the end of year 3, the stock is above the call barrier; the note is called and you receive the value of the stock plus a coupon for year 3."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"We're going to re-use the same simulation, with the following parameters:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Call barrier: 100%"}),"\n",(0,i.jsx)(n.li,{children:"Coupon barrier: 70%"}),"\n",(0,i.jsx)(n.li,{children:"Coupon: 6%"}),"\n",(0,i.jsx)(n.li,{children:"Capital protection until 70% (at maturity)"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'call_barrier = S0\ncoupon_barrier = S0 * .8\nprotection_barrier = S0 * .6\ncoupon = nominal * .06\n\nprice_phoenix_no_memory = function(initial_price, year_prices, call_barrier, coupon_barrier,\n protection_barrier, coupon, forward_structure)\n\n total_coupons = 0\n t = length(year_prices)\n\n for i=1:t\n price = year_prices[i]\n if price \u2265 call_barrier\n return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))\n elseif price \u2265 coupon_barrier\n total_coupons = total_coupons * exp(forward_structure[i]-1) + coupon\n else\n total_coupons *= exp(forward_structure[i]-1)\n end\n end\n\n # We\'ve reached maturity, time to check capital protection\n if year_prices[end] > protection_barrier\n return nominal + total_coupons\n else\n put = (strike - year_prices[end]) / strike\n return nominal*(1-put)\n end\nend\n\nforward_structure = forward_term(term)\nprice_function = (year_prices) -> price_phoenix_no_memory(S0, year_prices,\n call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)\n\nphoenix_no_memory = function()\n year_indexes = [n*i for i=1:T]\n motion = full_simulation(S0, T, n, m, term)\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\n return mean(payoffs)\nend\n\nmean_payoffs = zeros(num_simulations)\nfor i=1:num_simulations\n tic()\n mean_payoffs[i] = phoenix_no_memory()\n time = toq()\n @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time)\nend\n\nfinal_mean = mean(mean_payoffs)\nprintln("Mean over $num_simulations simulations: $(mean(mean_payoffs))")\npv = final_mean * exp(-(prod(forward_structure)-1)*(T))\n@printf("Present value of Phoenix without memory note: \\$%.2f", pv)\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:" Mean of simulation 1: $106.0562; Simulation time: 5.72s\n Mean of simulation 2: $106.0071; Simulation time: 5.85s\n Mean of simulation 3: $105.9959; Simulation time: 5.87s\n Mean of simulation 4: $106.0665; Simulation time: 5.93s\n Mean of simulation 5: $106.0168; Simulation time: 5.81s\n Mean over 5 simulations: 106.02850857209883\n Present value of Phoenix without memory note: $97.44\n"})}),"\n",(0,i.jsx)(n.h2,{id:"phoenix-with-memory-simulation",children:"Phoenix with Memory Simulation"}),"\n",(0,i.jsxs)(n.p,{children:['The Phoenix with Memory structure is very similar to the Phoenix, but as the name implies, has a special "memory" property: ',(0,i.jsx)(n.strong,{children:"It remembers any coupons that haven't been paid at prior observation times, and pays them all if the underlying crosses the coupon barrier"}),". For example:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Note issued with 100% call barrier, 70% coupon barrier. At year 1, the underlying is at 50%, so no coupons are paid. At year 2, the underlying is at 80%, so coupons for both year 1 and 2 are paid, resulting in a double coupon."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["You can also find an example ",(0,i.jsx)(n.a,{href:"https://www.rbccm.com/usstructurednotes/file-781232.pdf",children:"here"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Let's go ahead and set up the simulation! The parameters will be the same, but we can expect that the value will go up because of the memory attribute"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-julia",children:'call_barrier = S0\ncoupon_barrier = S0 * .8\nprotection_barrier = S0 * .6\ncoupon = nominal * .07\n\nprice_phoenix_with_memory = function(initial_price, year_prices, call_barrier,\n coupon_barrier, protection_barrier, coupon, forward_structure)\n\n last_coupon = 0\n total_coupons = 0\n \n t = length(year_prices)\n\n for i=1:t\n price = year_prices[i]\n if price > call_barrier\n return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))\n elseif price > coupon_barrier\n ####################################################################\n # The only difference between with/without memory is the below lines\n memory_coupons = (i - last_coupon) * coupon\n last_coupon = i\n total_coupons = total_coupons * exp(forward_structure[i]-1) + memory_coupons\n ####################################################################\n else\n total_coupons *= exp(forward_structure[i]-1)\n end\n end\n\n # We\'ve reached maturity, time to check capital protection\n if year_prices[end] > protection_barrier\n return nominal + total_coupons\n else\n put = (strike - year_prices[end]) / strike\n return nominal*(1-put)\n end\nend\n\nforward_structure = forward_term(term)\nprice_function = (year_prices) -> price_phoenix_with_memory(S0, year_prices,\n call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)\n\nphoenix_with_memory = function()\n year_indexes = [n*i for i=1:T]\n motion = full_simulation(S0, T, n, m, term)\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\n return mean(payoffs)\nend\n\nmean_payoffs = zeros(num_simulations)\nfor i=1:num_simulations\n tic()\n mean_payoffs[i] = phoenix_with_memory()\n time = toq()\n @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n",\n i, mean_payoffs[i], time)\nend\n\nfinal_mean = mean(mean_payoffs)\nprintln("Mean over $num_simulations simulations: $(mean(mean_payoffs))")\npv = final_mean * exp(-(prod(forward_structure)-1)*(T))\n@printf("Present value of Phoenix with memory note: \\$%.2f", pv)\n'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:" Mean of simulation 1: $108.8612; Simulation time: 5.89s\n Mean of simulation 2: $109.0226; Simulation time: 5.90s\n Mean of simulation 3: $108.9175; Simulation time: 5.92s\n Mean of simulation 4: $108.9426; Simulation time: 5.94s\n Mean of simulation 5: $108.8087; Simulation time: 6.06s\n Mean over 5 simulations: 108.91052564051816\n Present value of Phoenix with memory note: $100.09\n"})})]})}function h(e={}){let{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},7363:function(e,n,s){s.d(n,{Z:function(){return a}});let a=s.p+"assets/images/_notebook_12_0-1106bdfe947224ae55d7227b5a631d0e.svg"},1960:function(e,n,s){s.d(n,{Z:function(){return a}});let a=s.p+"assets/images/_notebook_6_0-46e660e38189a411644eac491e9b35ad.svg"},65:function(e,n,s){s.d(n,{Z:function(){return l},a:function(){return r}});var a=s(7294);let i={},t=a.createContext(i);function r(e){let n=a.useContext(t);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),a.createElement(t.Provider,{value:n},e.children)}},8279:function(e){e.exports=JSON.parse('{"permalink":"/2015/11/autocallable","source":"@site/blog/2015-11-27-autocallable/index.mdx","title":"Autocallable Bonds","description":"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.","date":"2015-11-27T12:00:00.000Z","tags":[],"readingTime":11.085,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/autocallable","title":"Autocallable Bonds","date":"2015-11-27T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"},"nextItem":{"title":"Welcome, and an algorithm","permalink":"/2015/11/welcome"}}')}}]); \ No newline at end of file diff --git a/assets/js/1a1424c7.9077c1c0.js b/assets/js/1a1424c7.9077c1c0.js new file mode 100644 index 0000000..376d288 --- /dev/null +++ b/assets/js/1a1424c7.9077c1c0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9763"],{829:function(e){e.exports=JSON.parse('{"metadata":{"permalink":"/","page":1,"postsPerPage":10,"totalPages":4,"totalCount":34,"nextPage":"/page/2","blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/1b190668.1a035f32.js b/assets/js/1b190668.1a035f32.js new file mode 100644 index 0000000..009e172 --- /dev/null +++ b/assets/js/1b190668.1a035f32.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5229"],{7897:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return o},default:function(){return l},frontMatter:function(){return a},metadata:function(){return i},toc:function(){return c}});var i=n(6749),r=n(5893),s=n(65);let a={slug:"2016/03/predicting-santander-customer-happiness",title:"Predicting Santander customer happiness",date:new Date("2016-03-05T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,u={authorsImageUrls:[void 0]},c=[];function p(e){let t={p:"p",...(0,s.a)(),...e.components};return(0,r.jsx)(t.p,{children:"My first Kaggle competition."})}function l(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return a}});var i=n(7294);let r={},s=i.createContext(r);function a(e){let t=i.useContext(s);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:t},e.children)}},6749:function(e){e.exports=JSON.parse('{"permalink":"/2016/03/predicting-santander-customer-happiness","source":"@site/blog/2016-03-05-predicting-santander-customer-happiness/index.mdx","title":"Predicting Santander customer happiness","description":"My first Kaggle competition.","date":"2016-03-05T12:00:00.000Z","tags":[],"readingTime":6.95,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/predicting-santander-customer-happiness","title":"Predicting Santander customer happiness","date":"2016-03-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"},"nextItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"}}')}}]); \ No newline at end of file diff --git a/assets/js/1d2da633.f724f156.js b/assets/js/1d2da633.f724f156.js new file mode 100644 index 0000000..bbc1ac9 --- /dev/null +++ b/assets/js/1d2da633.f724f156.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5373"],{695:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return p},frontMatter:function(){return o},metadata:function(){return a},toc:function(){return l}});var a=n(3628),i=n(5893),r=n(65);let o={slug:"2016/01/cloudy-in-seattle",title:"Cloudy in Seattle",date:new Date("2016-01-23T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,s={authorsImageUrls:[void 0]},l=[];function c(e){let t={p:"p",...(0,r.a)(),...e.components};return(0,i.jsx)(t.p,{children:"Building on prior analysis, is Seattle's reputation as a depressing city actually well-earned?"})}function p(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return o}});var a=n(7294);let i={},r=a.createContext(i);function o(e){let t=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(r.Provider,{value:t},e.children)}},3628:function(e){e.exports=JSON.parse('{"permalink":"/2016/01/cloudy-in-seattle","source":"@site/blog/2016-01-23-cloudy-in-seattle/index.mdx","title":"Cloudy in Seattle","description":"Building on prior analysis, is Seattle\'s reputation as a depressing city actually well-earned?","date":"2016-01-23T12:00:00.000Z","tags":[],"readingTime":3.965,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/cloudy-in-seattle","title":"Cloudy in Seattle","date":"2016-01-23T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730683607000,"prevItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"},"nextItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"}}')}}]); \ No newline at end of file diff --git a/assets/js/1e5192b9.9888c924.js b/assets/js/1e5192b9.9888c924.js new file mode 100644 index 0000000..825f389 --- /dev/null +++ b/assets/js/1e5192b9.9888c924.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5644"],{4092:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return r},default:function(){return u},frontMatter:function(){return s},metadata:function(){return i},toc:function(){return l}});var i=n(4729),o=n(5893),a=n(65);let s={slug:"2011/11/webpack-industrial-complex",title:"The webpack industrial complex",date:new Date("2022-11-20T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Starting strong",id:"starting-strong",level:2},{value:"Continuing on",id:"continuing-on",level:2},{value:"Floundering about",id:"floundering-about",level:2},{value:"Learning and reflecting",id:"learning-and-reflecting",level:2}];function d(e){let t={a:"a",code:"code",h2:"h2",img:"img",li:"li",p:"p",ul:"ul",...(0,a.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:'This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).'}),"\n",(0,o.jsx)(t.p,{children:"The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process."}),"\n",(0,o.jsx)(t.h2,{id:"starting-strong",children:"Starting strong"}),"\n",(0,o.jsx)(t.p,{children:'The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser."'}),"\n",(0,o.jsxs)(t.p,{children:["Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an ",(0,o.jsx)(t.code,{children:"onEvent"})," handler and a function easy."]}),"\n",(0,o.jsx)(t.p,{children:'Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical."'}),"\n",(0,o.jsx)(t.h2,{id:"continuing-on",children:"Continuing on"}),"\n",(0,o.jsx)(t.p,{children:'Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?'}),"\n",(0,o.jsxs)(t.p,{children:["The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API ",(0,o.jsx)(t.a,{href:"https://github.com/microsoft/TypeScript/issues/28308",children:"was missing"}),". After searching out Github issues and (unsuccessfully) tweaking the ",(0,o.jsx)(t.code,{children:".tsconfig"})," settings, I settled on installing a package and moving on."]}),"\n",(0,o.jsxs)(t.p,{children:['The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn\'t clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use ',(0,o.jsx)(t.code,{children:"new URL(, import.meta.url)"})," and it worked! Well, kind of:"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Browser error",src:n(4328).Z+"",width:"1279",height:"143"})}),"\n",(0,o.jsxs)(t.p,{children:["That file has the audio processor code, so why does it get served with ",(0,o.jsx)(t.code,{children:"Content-Type: video/mp2t"}),"?"]}),"\n",(0,o.jsx)(t.h2,{id:"floundering-about",children:"Floundering about"}),"\n",(0,o.jsxs)(t.p,{children:["Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to ",(0,o.jsx)(t.a,{href:"https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474",children:"just use JavaScript"})," and stuck by the original TypeScript requirement."]}),"\n",(0,o.jsx)(t.p,{children:"I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package."}),"\n",(0,o.jsxs)(t.p,{children:["I tried three different CRA tools - ",(0,o.jsx)(t.code,{children:"react-app-rewired"}),", ",(0,o.jsx)(t.code,{children:"craco"}),", ",(0,o.jsx)(t.code,{children:"customize-react-app"})," - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well."]}),"\n",(0,o.jsxs)(t.p,{children:["I tried changing the webpack configuration: using ",(0,o.jsx)(t.a,{href:"https://github.com/webpack/webpack/issues/11543#issuecomment-917673256",children:"new"})," ",(0,o.jsx)(t.a,{href:"https://github.com/popelenkow/worker-url",children:"loaders"}),", setting ",(0,o.jsx)(t.a,{href:"https://github.com/webpack/webpack/discussions/14093#discussioncomment-1257149",children:"asset rules"}),", even ",(0,o.jsx)(t.a,{href:"https://github.com/webpack/webpack/issues/11543#issuecomment-826897590",children:"changing how webpack detects worker resources"}),". In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up."]}),"\n",(0,o.jsxs)(t.p,{children:["I tried so many application frameworks. Next.js looked like a good candidate, but added its own ",(0,o.jsx)(t.a,{href:"https://github.com/vercel/next.js/issues/24907",children:"bespoke webpack complexity"})," to the existing confusion. Astro had the best \"getting started\" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work."]}),"\n",(0,o.jsx)(t.h2,{id:"learning-and-reflecting",children:"Learning and reflecting"}),"\n",(0,o.jsx)(t.p,{children:'I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn\'t important. Instead, the focus should be on lessons learned.'}),"\n",(0,o.jsx)(t.p,{children:"For myself:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:'I\'m obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work'}),"\n",(0,o.jsx)(t.li,{children:"I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts"}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"For the tools:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity"}),"\n",(0,o.jsx)(t.li,{children:'Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there\'s no path forward if something breaks'}),"\n",(0,o.jsx)(t.li,{children:"There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it"}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:'In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down.'})]})}function u(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},4328:function(e,t,n){n.d(t,{Z:function(){return i}});let i=n.p+"assets/images/video_mp2t-1decc5fbd88b54dadd06691ce4c629ec.png"},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return s}});var i=n(7294);let o={},a=i.createContext(o);function s(e){let t=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(a.Provider,{value:t},e.children)}},4729:function(e){e.exports=JSON.parse('{"permalink":"/2011/11/webpack-industrial-complex","source":"@site/blog/2022-11-20-webpack-industrial-complex/index.mdx","title":"The webpack industrial complex","description":"This started because I wanted to build a synthesizer. Setting a goal of \\"digital DX7\\" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).","date":"2022-11-20T12:00:00.000Z","tags":[],"readingTime":4.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2011/11/webpack-industrial-complex","title":"The webpack industrial complex","date":"2022-11-20T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731274898000,"nextItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"}}')}}]); \ No newline at end of file diff --git a/assets/js/1f1953c8.5837c39b.js b/assets/js/1f1953c8.5837c39b.js new file mode 100644 index 0000000..65555f7 --- /dev/null +++ b/assets/js/1f1953c8.5837c39b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2410"],{9959:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return p},frontMatter:function(){return o},metadata:function(){return r},toc:function(){return c}});var r=n(3303),i=n(5893),a=n(65);let o={slug:"2019/09/binary-format-shootout",title:"Binary format shootout",date:new Date("2019-09-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},c=[];function l(e){let t={a:"a",del:"del",p:"p",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["I've found that in many personal projects,\n",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Analysis_paralysis",children:"analysis paralysis"})," is particularly deadly.\nMaking good decisions in the beginning avoids pain and suffering later; if extra research prevents\nfuture problems, I'm happy to continue ",(0,i.jsx)(t.del,{children:"procrastinating"})," researching indefinitely."]}),"\n",(0,i.jsx)(t.p,{children:"So let's say you're in need of a binary serialization format. Data will be going over the network,\nnot just in memory, so having a schema document and code generation is a must. Performance is\ncrucial, so formats that support zero-copy de/serialization are given priority. And the more\nlanguages supported, the better; I use Rust, but can't predict what other languages this could\ninteract with."}),"\n",(0,i.jsx)(t.p,{children:"Given these requirements, the candidates I could find were:"})]})}function p(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return o}});var r=n(7294);let i={},a=r.createContext(i);function o(e){let t=r.useContext(a);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),r.createElement(a.Provider,{value:t},e.children)}},3303:function(e){e.exports=JSON.parse('{"permalink":"/2019/09/binary-format-shootout","source":"@site/blog/2019-09-28-binary-format-shootout/index.mdx","title":"Binary format shootout","description":"I\'ve found that in many personal projects,","date":"2019-09-28T12:00:00.000Z","tags":[],"readingTime":8.37,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/09/binary-format-shootout","title":"Binary format shootout","date":"2019-09-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"},"nextItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"}}')}}]); \ No newline at end of file diff --git a/assets/js/1fe257c0.d2e59b40.js b/assets/js/1fe257c0.d2e59b40.js new file mode 100644 index 0000000..bf20294 --- /dev/null +++ b/assets/js/1fe257c0.d2e59b40.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["3837"],{1883:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return i},metadata:function(){return o},toc:function(){return c}});var o=n(1915),a=n(5893),r=n(65);let i={slug:"2015/11/welcome",title:"Welcome, and an algorithm",date:new Date("2015-11-19T12:00:00.000Z"),last_update:{date:new Date("2015-12-05T12:00:00.000Z")},authors:["bspeice"],tags:[]},u=void 0,l={authorsImageUrls:[void 0]},c=[];function s(e){let t={p:"p",...(0,r.a)(),...e.components};return(0,a.jsx)(t.p,{children:"Hello! Glad to meet you. I'm currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I'm working on!"})}function d(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(s,{...e})}):s(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return i}});var o=n(7294);let a={},r=o.createContext(a);function i(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(r.Provider,{value:t},e.children)}},1915:function(e){e.exports=JSON.parse('{"permalink":"/2015/11/welcome","source":"@site/blog/2015-11-14-welcome/index.mdx","title":"Welcome, and an algorithm","description":"Hello! Glad to meet you. I\'m currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I\'m working on!","date":"2015-11-19T12:00:00.000Z","tags":[],"readingTime":4.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/welcome","title":"Welcome, and an algorithm","date":"2015-11-19T12:00:00.000Z","last_update":{"date":"2015-12-05T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1449316800000,"prevItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}}')}}]); \ No newline at end of file diff --git a/assets/js/2061.3bbdbc04.js b/assets/js/2061.3bbdbc04.js new file mode 100644 index 0000000..57c7dfb --- /dev/null +++ b/assets/js/2061.3bbdbc04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2061"],{8544:function(e,s,c){c.r(s)}}]); \ No newline at end of file diff --git a/assets/js/2062e753.bee6da1d.js b/assets/js/2062e753.bee6da1d.js new file mode 100644 index 0000000..e576d8c --- /dev/null +++ b/assets/js/2062e753.bee6da1d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8770"],{984:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return l},frontMatter:function(){return i},metadata:function(){return r},toc:function(){return c}});var r=n(1403),a=n(5893),o=n(65);let i={slug:"2019/06/high-performance-systems",title:"On building high performance systems",date:new Date("2019-07-01T12:00:00.000Z"),last_updated:{date:new Date("2019-09-21T12:00:00.000Z")},authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},c=[];function p(e){let t={p:"p",...(0,o.a)(),...e.components};return(0,a.jsx)(t.p,{children:"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is\nmade up of people who have access to secret techniques mortal developers could only dream of. There\nhad to be some secret art that could only be learned if one had an appropriately tragic backstory."})}function l(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return i}});var r=n(7294);let a={},o=r.createContext(a);function i(e){let t=r.useContext(o);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(o.Provider,{value:t},e.children)}},1403:function(e){e.exports=JSON.parse('{"permalink":"/2019/06/high-performance-systems","source":"@site/blog/2019-06-31-high-performance-systems/index.mdx","title":"On building high performance systems","description":"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is","date":"2019-07-01T12:00:00.000Z","tags":[],"readingTime":12.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/06/high-performance-systems","title":"On building high performance systems","date":"2019-07-01T12:00:00.000Z","last_updated":{"date":"2019-09-21T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"},"nextItem":{"title":"Making bread","permalink":"/2019/05/making-bread"}}')}}]); \ No newline at end of file diff --git a/assets/js/2519.06ba1bd0.js b/assets/js/2519.06ba1bd0.js new file mode 100644 index 0000000..414fd89 --- /dev/null +++ b/assets/js/2519.06ba1bd0.js @@ -0,0 +1,4 @@ +(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2519"],{7594:function(e,t){function n(e){let t,n=[];for(let r of e.split(",").map(e=>e.trim()))if(/^-?\d+$/.test(r))n.push(parseInt(r,10));else if(t=r.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,r,l,s]=t;if(r&&s){r=parseInt(r);let e=r<(s=parseInt(s))?1:-1;("-"===l||".."===l||"\u2025"===l)&&(s+=e);for(let t=r;t!==s;t+=e)n.push(t)}}return n}t.default=n,e.exports=n},5094:function(e,t,n){"use strict";n.d(t,{Z:()=>k});var r=n("5893"),l=n("7294"),s=n("7026"),a=n("6025"),o=n("4681");let i={admonition:"admonition_xJq3",admonitionHeading:"admonitionHeading_Gvgb",admonitionIcon:"admonitionIcon_Rf37",admonitionContent:"admonitionContent_BuS1"};function c(e){let{type:t,className:n,children:l}=e;return(0,r.jsx)("div",{className:(0,s.Z)(o.k.common.admonition,o.k.common.admonitionType(t),i.admonition,n),children:l})}function d(e){let{icon:t,title:n}=e;return(0,r.jsxs)("div",{className:i.admonitionHeading,children:[(0,r.jsx)("span",{className:i.admonitionIcon,children:t}),n]})}function u(e){let{children:t}=e;return t?(0,r.jsx)("div",{className:i.admonitionContent,children:t}):null}function m(e){let{type:t,icon:n,title:l,children:s,className:a}=e;return(0,r.jsxs)(c,{type:t,className:a,children:[l||n?(0,r.jsx)(d,{title:l,icon:n}):null,(0,r.jsx)(u,{children:s})]})}let h={icon:(0,r.jsx)(function(e){return(0,r.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})},{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function p(e){return(0,r.jsx)(m,{...h,...e,className:(0,s.Z)("alert alert--secondary",e.className),children:e.children})}let f={icon:(0,r.jsx)(function(e){return(0,r.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})},{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function g(e){return(0,r.jsx)(m,{...f,...e,className:(0,s.Z)("alert alert--success",e.className),children:e.children})}let x={icon:(0,r.jsx)(function(e){return(0,r.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})},{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function j(e){return(0,r.jsx)(m,{...x,...e,className:(0,s.Z)("alert alert--info",e.className),children:e.children})}function b(e){return(0,r.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}let v={icon:(0,r.jsx)(b,{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})},y={icon:(0,r.jsx)(function(e){return(0,r.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})},{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})},N={icon:(0,r.jsx)(b,{}),title:(0,r.jsx)(a.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})},w={note:p,tip:g,info:j,warning:function(e){return(0,r.jsx)(m,{...v,...e,className:(0,s.Z)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,r.jsx)(m,{...y,...e,className:(0,s.Z)("alert alert--danger",e.className),children:e.children})},secondary:e=>(0,r.jsx)(p,{title:"secondary",...e}),important:e=>(0,r.jsx)(j,{title:"important",...e}),success:e=>(0,r.jsx)(g,{title:"success",...e}),caution:function(e){return(0,r.jsx)(m,{...N,...e,className:(0,s.Z)("alert alert--warning",e.className),children:e.children})}};function k(e){let t=function(e){let{mdxAdmonitionTitle:t,rest:n}=function(e){let t=l.Children.toArray(e),n=t.find(e=>l.isValidElement(e)&&"mdxAdmonitionTitle"===e.type),s=t.filter(e=>e!==n);return{mdxAdmonitionTitle:n?.props.children,rest:s.length>0?(0,r.jsx)(r.Fragment,{children:s}):null}}(e.children),s=e.title??t;return{...e,...s&&{title:s},children:n}}(e),n=function(e){let t=w[e];return t?t:(console.warn(`No admonition component found for admonition type "${e}". Using Info as fallback.`),w.info)}(t.type);return(0,r.jsx)(n,{...t})}},2553:function(e,t,n){"use strict";n.d(t,{Z:()=>eO});var r=n("5893"),l=n("7294"),s=n("7026"),a=n("4183");function o(e){let{children:t,className:n}=e;return(0,r.jsx)("article",{className:n,children:t})}var i=n("3012");let c="title_f1Hy";function d(e){let{className:t}=e,{metadata:n,isBlogPostPage:l}=(0,a.nO)(),{permalink:o,title:d}=n;return(0,r.jsx)(l?"h1":"h2",{className:(0,s.Z)(c,t),children:l?d:(0,r.jsx)(i.Z,{to:o,children:d})})}var u=n("6025"),m=n("2933");let h=["zero","one","two","few","many","other"];function p(e){return h.filter(t=>e.includes(t))}let f={locale:"en",pluralForms:p(["one","other"]),select:e=>1===e?"one":"other"};var g=n("1437");let x="container_mt6G";function j(e){let{readingTime:t}=e,n=function(){let{selectMessage:e}=function(){let e=function(){let{i18n:{currentLocale:e}}=(0,m.Z)();return(0,l.useMemo)(()=>{try{return function(e){let t=new Intl.PluralRules(e);return{locale:e,pluralForms:p(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}". +Docusaurus will fallback to the default (English) implementation. +Error: ${t.message} +`),f}},[e])}();return{selectMessage:(t,n)=>(function(e,t,n){let r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);let l=n.select(t);return r[Math.min(n.pluralForms.indexOf(l),r.length-1)]})(n,t,e)}}();return t=>{let n=Math.ceil(t);return e(n,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:n}))}}();return(0,r.jsx)(r.Fragment,{children:n(t)})}function b(e){let{date:t,formattedDate:n}=e;return(0,r.jsx)("time",{dateTime:t,children:n})}function v(){return(0,r.jsx)(r.Fragment,{children:" \xb7 "})}function y(e){let t,{className:n}=e,{metadata:l}=(0,a.nO)(),{date:o,readingTime:i}=l,c=(0,g.P)({day:"numeric",month:"long",year:"numeric",timeZone:"UTC"});return(0,r.jsxs)("div",{className:(0,s.Z)(x,"margin-vert--md",n),children:[(0,r.jsx)(b,{date:o,formattedDate:(t=o,c.format(new Date(t)))}),void 0!==i&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(v,{}),(0,r.jsx)(j,{readingTime:i})]})]})}var N=n("1389");let w={authorCol:"authorCol_Hf19",imageOnlyAuthorRow:"imageOnlyAuthorRow_pa_O",imageOnlyAuthorCol:"imageOnlyAuthorCol_G86a"};function k(e){let{className:t}=e,{metadata:{authors:n},assets:l}=(0,a.nO)();if(0===n.length)return null;let o=n.every(e=>{let{name:t}=e;return!t}),i=1===n.length;return(0,r.jsx)("div",{className:(0,s.Z)("margin-top--md margin-bottom--sm",o?w.imageOnlyAuthorRow:"row",t),children:n.map((e,t)=>(0,r.jsx)("div",{className:(0,s.Z)(!o&&(i?"col col--12":"col col--6"),o?w.imageOnlyAuthorCol:w.authorCol),children:(0,r.jsx)(N.Z,{author:{...e,imageURL:l.authorsImageUrls[t]??e.imageURL}})},t))})}function C(){return(0,r.jsxs)("header",{children:[(0,r.jsx)(d,{}),(0,r.jsx)(y,{}),(0,r.jsx)(k,{})]})}var Z=n("8365"),B=n("65"),_=n("4819"),T=n("7227"),E=n("4239"),L=n("140");function A(){let{prism:e}=(0,L.L)(),{colorMode:t}=(0,E.I)(),n=e.theme,r=e.darkTheme||n;return"dark"===t?r:n}var I=n("4681"),M=n("7594"),R=n.n(M);let S=/title=(?["'])(?.*?)\1/,z=/\{(?<range>[\d,-]+)\}/,H={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},O={...H,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},U=Object.keys(H);function $(e,t){let n=e.map(e=>{let{start:n,end:r}=O[e];return`(?:${n}\\s*(${t.flatMap(e=>[e.line,e.block?.start,e.block?.end].filter(Boolean)).join("|")})\\s*${r})`}).join("|");return RegExp(`^\\s*(?:${n})\\s*$`)}let F="codeBlockContainer_Ckt0";function V(e){let{as:t,...n}=e,l=function(e){let t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach(e=>{let[r,l]=e,s=t[r];s&&"string"==typeof l&&(n[s]=l)}),n}(A());return(0,r.jsx)(t,{...n,style:l,className:(0,s.Z)(n.className,F,I.k.common.codeBlock)})}let D={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function P(e){let{children:t,className:n}=e;return(0,r.jsx)(V,{as:"pre",tabIndex:0,className:(0,s.Z)(D.codeBlockStandalone,"thin-scrollbar",n),children:(0,r.jsx)("code",{className:D.codeBlockLines,children:t})})}var W=n("5346");let q={attributes:!0,characterData:!0,childList:!0,subtree:!0};var G=n("3229");let J={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function Q(e){let{line:t,classNames:n,showLineNumbers:l,getLineProps:a,getTokenProps:o}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");let i=a({line:t,className:(0,s.Z)(n,l&&J.codeLine)}),c=t.map((e,t)=>(0,r.jsx)("span",{...o({token:e})},t));return(0,r.jsxs)("span",{...i,children:[l?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("span",{className:J.codeLineNumber}),(0,r.jsx)("span",{className:J.codeLineContent,children:c})]}):c,(0,r.jsx)("br",{})]})}function X(e){return(0,r.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,r.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function Y(e){return(0,r.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,r.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}let K={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function ee(e){let{code:t,className:n}=e,[a,o]=(0,l.useState)(!1),i=(0,l.useRef)(void 0),c=(0,l.useCallback)(()=>{!function(e){let{target:t=document.body}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if("string"!=typeof e)throw TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);let n=document.createElement("textarea"),r=document.activeElement;n.value=e,n.setAttribute("readonly",""),n.style.contain="strict",n.style.position="absolute",n.style.left="-9999px",n.style.fontSize="12pt";let l=document.getSelection(),s=l.rangeCount>0&&l.getRangeAt(0);t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let a=!1;try{a=document.execCommand("copy")}catch{}n.remove(),s&&(l.removeAllRanges(),l.addRange(s)),r&&r.focus()}(t),o(!0),i.current=window.setTimeout(()=>{o(!1)},1e3)},[t]);return(0,l.useEffect)(()=>()=>window.clearTimeout(i.current),[]),(0,r.jsx)("button",{type:"button","aria-label":a?(0,u.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,u.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,u.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,s.Z)("clean-btn",n,K.copyButton,a&&K.copyButtonCopied),onClick:c,children:(0,r.jsxs)("span",{className:K.copyButtonIcons,"aria-hidden":"true",children:[(0,r.jsx)(X,{className:K.copyButtonIcon}),(0,r.jsx)(Y,{className:K.copyButtonSuccessIcon})]})})}function et(e){return(0,r.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,r.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}let en={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function er(e){let{className:t,onClick:n,isEnabled:l}=e,a=(0,u.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,r.jsx)("button",{type:"button",onClick:n,className:(0,s.Z)("clean-btn",t,l&&en.wordWrapButtonEnabled),"aria-label":a,title:a,children:(0,r.jsx)(et,{className:en.wordWrapButtonIcon,"aria-hidden":"true"})})}function el(e){var t,n,a;let{children:o,className:i="",metastring:c,title:d,showLineNumbers:u,language:m}=e,{prism:{defaultLanguage:h,magicComments:p}}=(0,L.L)();let f=(t=m??function(e){let t=e.split(" ").find(e=>e.startsWith("language-"));return t?.replace(/language-/,"")}(i)??h,t?.toLowerCase()),g=A(),x=function(){let[e,t]=(0,l.useState)(!1),[n,r]=(0,l.useState)(!1),s=(0,l.useRef)(null),a=(0,l.useCallback)(()=>{let n=s.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t(e=>!e)},[s,e]),o=(0,l.useCallback)(()=>{let{scrollWidth:e,clientWidth:t}=s.current;r(e>t||s.current.querySelector("code").hasAttribute("style"))},[s]);return!function(e,t){let[n,r]=(0,l.useState)(),s=(0,l.useCallback)(()=>{r(e.current?.closest("[role=tabpanel][hidden]"))},[e,r]);(0,l.useEffect)(()=>{s()},[s]),!function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:q,r=(0,W.zX)(t),s=(0,W.Ql)(n);(0,l.useEffect)(()=>{let t=new MutationObserver(r);return e&&t.observe(e,s),()=>t.disconnect()},[e,r,s])}(n,e=>{e.forEach(e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),s())})},{attributes:!0,characterData:!1,childList:!1,subtree:!1})}(s,o),(0,l.useEffect)(()=>{o()},[e,o]),(0,l.useEffect)(()=>(window.addEventListener("resize",o,{passive:!0}),()=>{window.removeEventListener("resize",o)}),[o]),{codeBlockRef:s,isEnabled:e,isCodeScrollable:n,toggle:a}}();let j=(n=c,(n?.match(S)?.groups.title??"")||d),{lineClassNames:b,code:v}=function(e,t){let n=e.replace(/\n$/,""),{language:r,magicComments:l,metastring:s}=t;if(s&&z.test(s)){let e=s.match(z).groups.range;if(0===l.length)throw Error(`A highlight range has been given in code block's metastring (\`\`\` ${s}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);let t=l[0].className;return{lineClassNames:Object.fromEntries(R()(e).filter(e=>e>0).map(e=>[e-1,[t]])),code:n}}if(void 0===r)return{lineClassNames:{},code:n};let a=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return $(["js","jsBlock"],t);case"jsx":case"tsx":return $(["js","jsBlock","jsx"],t);case"html":return $(["js","jsBlock","html"],t);case"python":case"py":case"bash":return $(["bash"],t);case"markdown":case"md":return $(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return $(["tex"],t);case"lua":case"haskell":case"sql":return $(["lua"],t);case"wasm":return $(["wasm"],t);case"vb":case"vba":case"visual-basic":return $(["vb","rem"],t);case"vbnet":return $(["vbnet","rem"],t);case"batch":return $(["rem"],t);case"basic":return $(["rem","f90"],t);case"fsharp":return $(["js","ml"],t);case"ocaml":case"sml":return $(["ml"],t);case"fortran":return $(["f90"],t);case"cobol":return $(["cobol"],t);default:return $(U,t)}}(r,l),o=n.split("\n"),i=Object.fromEntries(l.map(e=>[e.className,{start:0,range:""}])),c=Object.fromEntries(l.filter(e=>e.line).map(e=>{let{className:t,line:n}=e;return[n,t]})),d=Object.fromEntries(l.filter(e=>e.block).map(e=>{let{className:t,block:n}=e;return[n.start,t]})),u=Object.fromEntries(l.filter(e=>e.block).map(e=>{let{className:t,block:n}=e;return[n.end,t]}));for(let e=0;e<o.length;){let t=o[e].match(a);if(!t){e+=1;continue}let n=t.slice(1).find(e=>void 0!==e);c[n]?i[c[n]].range+=`${e},`:d[n]?i[d[n]].start=e:u[n]&&(i[u[n]].range+=`${i[u[n]].start}-${e-1},`),o.splice(e,1)}n=o.join("\n");let m={};return Object.entries(i).forEach(e=>{let[t,{range:n}]=e;R()(n).forEach(e=>{m[e]??=[],m[e].push(t)})}),{lineClassNames:m,code:n}}(o,{metastring:c,language:f,magicComments:p});let y=u??(a=c,!!a?.includes("showLineNumbers"));return(0,r.jsxs)(V,{as:"div",className:(0,s.Z)(i,f&&!i.includes(`language-${f}`)&&`language-${f}`),children:[j&&(0,r.jsx)("div",{className:D.codeBlockTitle,children:j}),(0,r.jsxs)("div",{className:D.codeBlockContent,children:[(0,r.jsx)(G.y$,{theme:g,code:v,language:f??"text",children:e=>{let{className:t,style:n,tokens:l,getLineProps:a,getTokenProps:o}=e;return(0,r.jsx)("pre",{tabIndex:0,ref:x.codeBlockRef,className:(0,s.Z)(t,D.codeBlock,"thin-scrollbar"),style:n,children:(0,r.jsx)("code",{className:(0,s.Z)(D.codeBlockLines,y&&D.codeBlockLinesWithNumbering),children:l.map((e,t)=>(0,r.jsx)(Q,{line:e,getLineProps:a,getTokenProps:o,classNames:b[t],showLineNumbers:y},t))})})}}),(0,r.jsxs)("div",{className:D.buttonGroup,children:[(x.isEnabled||x.isCodeScrollable)&&(0,r.jsx)(er,{className:D.codeButton,onClick:()=>x.toggle(),isEnabled:x.isEnabled}),(0,r.jsx)(ee,{className:D.codeButton,code:v})]})]})]})}function es(e){var t;let{children:n,...s}=e,a=(0,T.Z)();let o=(t=n,l.Children.toArray(t).some(e=>(0,l.isValidElement)(e))?t:Array.isArray(t)?t.join(""):t);return(0,r.jsx)("string"==typeof o?el:P,{...s,children:o},String(a))}function ea(e){return(0,r.jsx)("code",{...e})}var eo=n("1065"),ei=n("1276");let ec={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function ed(e){return!!e&&("SUMMARY"===e.tagName||ed(e.parentElement))}function eu(e){let{summary:t,children:n,...a}=e;(0,eo.Z)().collectAnchor(a.id);let o=(0,T.Z)(),i=(0,l.useRef)(null),{collapsed:c,setCollapsed:d}=(0,ei.u)({initialState:!a.open}),[u,m]=(0,l.useState)(a.open),h=l.isValidElement(t)?t:(0,r.jsx)("summary",{children:t??"Details"});return(0,r.jsxs)("details",{...a,ref:i,open:u,"data-collapsed":c,className:(0,s.Z)(ec.details,o&&ec.isBrowser,a.className),onMouseDown:e=>{ed(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();let t=e.target;if(!!(ed(t)&&function e(t,n){return!!t&&(t===n||e(t.parentElement,n))}(t,i.current)))e.preventDefault(),c?(d(!1),m(!0)):d(!0)},children:[h,(0,r.jsx)(ei.z,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{d(e),m(!e)},children:(0,r.jsx)("div",{className:ec.collapsibleContent,children:n})})]})}let em="details_b_Ee";function eh(e){let{...t}=e;return(0,r.jsx)(eu,{...t,className:(0,s.Z)("alert alert--info",em,t.className)})}function ep(e){let t=l.Children.toArray(e.children),n=t.find(e=>l.isValidElement(e)&&"summary"===e.type),s=(0,r.jsx)(r.Fragment,{children:t.filter(e=>e!==n)});return(0,r.jsx)(eh,{...e,summary:n,children:s})}var ef=n("4403");function eg(e){return(0,r.jsx)(ef.Z,{...e})}let ex={containsTaskList:"containsTaskList_mC6p"},ej="img_ev3q";var eb=n("5094");let ev={Head:_.Z,details:ep,Details:ep,code:function(e){var t;return void 0!==(t=e).children&&l.Children.toArray(t.children).every(e=>"string"==typeof e&&!e.includes("\n"))?(0,r.jsx)(ea,{...e}):(0,r.jsx)(es,{...e})},a:function(e){return(0,r.jsx)(i.Z,{...e})},pre:function(e){return(0,r.jsx)(r.Fragment,{children:e.children})},ul:function(e){return(0,r.jsx)("ul",{...e,className:function(e){if(void 0!==e)return(0,s.Z)(e,e?.includes("contains-task-list")&&ex.containsTaskList)}(e.className)})},li:function(e){return(0,eo.Z)().collectAnchor(e.id),(0,r.jsx)("li",{...e})},img:function(e){var t;return(0,r.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,s.Z)(t,ej))})},h1:e=>(0,r.jsx)(eg,{as:"h1",...e}),h2:e=>(0,r.jsx)(eg,{as:"h2",...e}),h3:e=>(0,r.jsx)(eg,{as:"h3",...e}),h4:e=>(0,r.jsx)(eg,{as:"h4",...e}),h5:e=>(0,r.jsx)(eg,{as:"h5",...e}),h6:e=>(0,r.jsx)(eg,{as:"h6",...e}),admonition:eb.Z,mermaid:()=>null};function ey(e){let{children:t}=e;return(0,r.jsx)(B.Z,{components:ev,children:t})}function eN(e){let{children:t,className:n}=e,{isBlogPostPage:l}=(0,a.nO)();return(0,r.jsx)("div",{id:l?Z.blogPostContainerID:void 0,className:(0,s.Z)("markdown",n),children:(0,r.jsx)(ey,{children:t})})}let ew="iconEdit_Z9Sw";function ek(e){let{className:t,...n}=e;return(0,r.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,s.Z)(ew,t),"aria-hidden":"true",...n,children:(0,r.jsx)("g",{children:(0,r.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function eC(e){let{editUrl:t}=e;return(0,r.jsxs)(i.Z,{to:t,className:I.k.common.editThisPage,children:[(0,r.jsx)(ek,{}),(0,r.jsx)(u.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}function eZ(e){let{lastUpdatedAt:t}=e,n=new Date(t),l=(0,g.P)({day:"numeric",month:"short",year:"numeric",timeZone:"UTC"}).format(n);return(0,r.jsx)(u.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,r.jsx)("b",{children:(0,r.jsx)("time",{dateTime:n.toISOString(),itemProp:"dateModified",children:l})})},children:" on {date}"})}function eB(e){let{lastUpdatedBy:t}=e;return(0,r.jsx)(u.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,r.jsx)("b",{children:t})},children:" by {user}"})}function e_(e){let{lastUpdatedAt:t,lastUpdatedBy:n}=e;return(0,r.jsxs)("span",{className:I.k.common.lastUpdated,children:[(0,r.jsx)(u.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t?(0,r.jsx)(eZ,{lastUpdatedAt:t}):"",byUser:n?(0,r.jsx)(eB,{lastUpdatedBy:n}):""},children:"Last updated{atDate}{byUser}"}),!1]})}let eT="lastUpdated_JAkA";function eE(e){let{className:t,editUrl:n,lastUpdatedAt:l,lastUpdatedBy:a}=e;return(0,r.jsxs)("div",{className:(0,s.Z)("row",t),children:[(0,r.jsx)("div",{className:"col",children:n&&(0,r.jsx)(eC,{editUrl:n})}),(0,r.jsx)("div",{className:(0,s.Z)("col",eT),children:(l||a)&&(0,r.jsx)(e_,{lastUpdatedAt:l,lastUpdatedBy:a})})]})}let eL={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function eA(e){let{permalink:t,label:n,count:l,description:a}=e;return(0,r.jsxs)(i.Z,{href:t,title:a,className:(0,s.Z)(eL.tag,l?eL.tagWithCount:eL.tagRegular),children:[n,l&&(0,r.jsx)("span",{children:l})]})}let eI="tags_jXut",eM="tag_QGVx";function eR(e){let{tags:t}=e;return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("b",{children:(0,r.jsx)(u.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list",children:"Tags:"})}),(0,r.jsx)("ul",{className:(0,s.Z)(eI,"padding--none","margin-left--sm"),children:t.map(e=>(0,r.jsx)("li",{className:eM,children:(0,r.jsx)(eA,{...e})},e.permalink))})]})}function eS(){return(0,r.jsx)("b",{children:(0,r.jsx)(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts",children:"Read more"})})}function ez(e){let{blogPostTitle:t,...n}=e;return(0,r.jsx)(i.Z,{"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t}),...n,children:(0,r.jsx)(eS,{})})}function eH(){let{metadata:e,isBlogPostPage:t}=(0,a.nO)(),{tags:n,title:l,editUrl:o,hasTruncateMarker:i,lastUpdatedBy:c,lastUpdatedAt:d}=e,u=!t&&i,m=n.length>0;if(!(m||u||o))return null;if(!t)return(0,r.jsxs)("footer",{className:"row docusaurus-mt-lg",children:[m&&(0,r.jsx)("div",{className:(0,s.Z)("col",{"col--9":u}),children:(0,r.jsx)(eR,{tags:n})}),u&&(0,r.jsx)("div",{className:(0,s.Z)("col text--right",{"col--3":m}),children:(0,r.jsx)(ez,{blogPostTitle:l,to:e.permalink})})]});{let e=!!(o||d||c);return(0,r.jsxs)("footer",{className:"docusaurus-mt-lg",children:[m&&(0,r.jsx)("div",{className:(0,s.Z)("row","margin-top--sm",I.k.blog.blogFooterEditMetaRow),children:(0,r.jsx)("div",{className:"col",children:(0,r.jsx)(eR,{tags:n})})}),e&&(0,r.jsx)(eE,{className:(0,s.Z)("margin-top--sm",I.k.blog.blogFooterEditMetaRow),editUrl:o,lastUpdatedAt:d,lastUpdatedBy:c})]})}}function eO(e){let{children:t,className:n}=e,l=function(){let{isBlogPostPage:e}=(0,a.nO)();return e?void 0:"margin-bottom--xl"}();return(0,r.jsxs)(o,{className:(0,s.Z)(l,n),children:[(0,r.jsx)(C,{}),(0,r.jsx)(eN,{children:t}),(0,r.jsx)(eH,{})]})}},790:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});var r=n(5893);n(7294);var l=n(7026),s=n(3012);function a(e){let{permalink:t,title:n,subLabel:a,isNext:o}=e;return(0,r.jsxs)(s.Z,{className:(0,l.Z)("pagination-nav__link",o?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[a&&(0,r.jsx)("div",{className:"pagination-nav__sublabel",children:a}),(0,r.jsx)("div",{className:"pagination-nav__label",children:n})]})}},1437:function(e,t,n){"use strict";n.d(t,{P:function(){return l}});var r=n(2933);function l(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{i18n:{currentLocale:t}}=(0,r.Z)(),n=function(){let{i18n:{currentLocale:e,localeConfigs:t}}=(0,r.Z)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:n,...e})}},65:function(e,t,n){"use strict";n.d(t,{Z:function(){return o},a:function(){return a}});var r=n(7294);let l={},s=r.createContext(l);function a(e){let t=r.useContext(s);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:a(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/319b187a.06669ed5.js b/assets/js/319b187a.06669ed5.js new file mode 100644 index 0000000..0cfecd3 --- /dev/null +++ b/assets/js/319b187a.06669ed5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4809"],{3227:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return m},frontMatter:function(){return o},metadata:function(){return r},toc:function(){return c}});var r=n(4892),a=n(5893),i=n(65);let o={slug:"2016/02/guaranteed-money-maker",title:"Guaranteed money maker",date:new Date("2016-02-03T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,s={authorsImageUrls:[void 0]},c=[];function l(e){let t={p:"p",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Developing an investment strategy based on the Martingale betting strategy"}),"\n",(0,a.jsx)(t.p,{children:"If you can see into the future, that is."})]})}function m(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return o}});var r=n(7294);let a={},i=r.createContext(a);function o(e){let t=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),r.createElement(i.Provider,{value:t},e.children)}},4892:function(e){e.exports=JSON.parse('{"permalink":"/2016/02/guaranteed-money-maker","source":"@site/blog/2016-02-03-guaranteed-money-maker/index.mdx","title":"Guaranteed money maker","description":"Developing an investment strategy based on the Martingale betting strategy","date":"2016-02-03T12:00:00.000Z","tags":[],"readingTime":7.695,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/guaranteed-money-maker","title":"Guaranteed money maker","date":"2016-02-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"},"nextItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"}}')}}]); \ No newline at end of file diff --git a/assets/js/33496f92.dec736d4.js b/assets/js/33496f92.dec736d4.js new file mode 100644 index 0000000..4698115 --- /dev/null +++ b/assets/js/33496f92.dec736d4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1680"],{2187:function(e){e.exports=JSON.parse('{"metadata":{"permalink":"/page/3","page":3,"postsPerPage":10,"totalPages":4,"totalCount":34,"previousPage":"/page/2","nextPage":"/page/4","blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/35b21e3d.3e3cc712.js b/assets/js/35b21e3d.3e3cc712.js new file mode 100644 index 0000000..6edb701 --- /dev/null +++ b/assets/js/35b21e3d.3e3cc712.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4833"],{6171:function(e,s,t){t.r(s),t.d(s,{assets:function(){return o},contentTitle:function(){return r},default:function(){return m},frontMatter:function(){return l},metadata:function(){return n},toc:function(){return c}});var n=t(3071),a=t(5893),i=t(65);let l={slug:"2016/02/profitability-using-the-investment-formula",title:"Profitability using the investment formula",date:new Date("2016-02-26T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,o={authorsImageUrls:[void 0]},c=[{value:"Theoretical Justification",id:"theoretical-justification",level:2},{value:"Running a simulation",id:"running-a-simulation",level:2},{value:"And now the interesting part",id:"and-now-the-interesting-part",level:2},{value:"Summary and plans for the next post",id:"summary-and-plans-for-the-next-post",level:2}];function h(e){let s={a:"a",annotation:"annotation",code:"code",h2:"h2",img:"img",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.p,{children:"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?"}),"\n",(0,a.jsxs)(s.p,{children:["I've previously talked about crafting an ",(0,a.jsx)(s.a,{href:"/2016/02/guaranteed-money-maker",children:"Investment Formula"})," that would guarantee making money if you could predict which direction the stock market was going to go. This is going to be the first in a series of posts trying to flesh out what an actual investment strategy based on this formula would look like."]}),"\n",(0,a.jsxs)(s.p,{children:["But first, the formula doesn't take into account two very important things: ",(0,a.jsx)(s.strong,{children:"leverage"}),", and the ",(0,a.jsx)(s.strong,{children:"number of days invested"}),". That's why I want to set up what I'm going to call the ",(0,a.jsx)(s.strong,{children:"Profitability Score"}),"."]}),"\n",(0,a.jsx)(s.p,{children:"The definition is going to be very simple:"}),"\n",(0,a.jsxs)(s.ul,{children:["\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsx)(s.mrow,{children:(0,a.jsx)(s.mi,{children:"p"})}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"p"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"p"})]})})]}),": Profit made once you exit the investment"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsx)(s.mrow,{children:(0,a.jsx)(s.mi,{children:"i"})}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"i"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.6595em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"i"})]})})]}),": Initial investment into the asset"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsx)(s.mrow,{children:(0,a.jsx)(s.mi,{children:"m"})}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"m"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"m"})]})})]}),": Maximum investment in the asset"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mi,{children:"l"}),(0,a.jsx)(s.mo,{children:"="}),(0,a.jsx)(s.mi,{children:"m"}),(0,a.jsx)(s.mi,{mathvariant:"normal",children:"/"}),(0,a.jsx)(s.mi,{children:"i"})]}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"l = m / i"})]})})}),(0,a.jsxs)(s.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.6944em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.01968em"},children:"l"}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(s.span,{className:"mrel",children:"="}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"m"}),(0,a.jsx)(s.span,{className:"mord",children:"/"}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"i"})]})]})]}),": The maximum leverage of an investment, as the ratio of maximum invested to initial investment"]}),"\n",(0,a.jsxs)(s.li,{children:[(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsx)(s.mrow,{children:(0,a.jsx)(s.mi,{children:"d"})}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"d"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.6944em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"d"})]})})]}),": The number of days it takes to turn a profit"]}),"\n"]}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mi,{children:"s"}),(0,a.jsx)(s.mo,{children:"="}),(0,a.jsxs)(s.mfrac,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mn,{children:"1000"}),(0,a.jsx)(s.mi,{children:"p"})]}),(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mi,{children:"i"}),(0,a.jsx)(s.mo,{stretchy:"false",children:"("}),(0,a.jsx)(s.mi,{children:"l"}),(0,a.jsx)(s.mo,{children:"+"}),(0,a.jsx)(s.mi,{children:"d"}),(0,a.jsx)(s.mo,{stretchy:"false",children:")"})]})]}),(0,a.jsx)(s.mo,{children:"="}),(0,a.jsxs)(s.mfrac,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mn,{children:"1000"}),(0,a.jsx)(s.mi,{children:"p"})]}),(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mi,{children:"m"}),(0,a.jsx)(s.mo,{children:"+"}),(0,a.jsx)(s.mi,{children:"i"}),(0,a.jsx)(s.mo,{children:"\u22C5"}),(0,a.jsx)(s.mi,{children:"d"})]})]})]}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"s = \\frac{1000 p}{i(l + d)} = \\frac{1000 p}{m + i\\cdot d}"})]})})}),(0,a.jsxs)(s.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"s"}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(s.span,{className:"mrel",children:"="}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"1.4172em",verticalAlign:"-0.52em"}}),(0,a.jsxs)(s.span,{className:"mord",children:[(0,a.jsx)(s.span,{className:"mopen nulldelimiter"}),(0,a.jsx)(s.span,{className:"mfrac",children:(0,a.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(s.span,{className:"vlist-r",children:[(0,a.jsxs)(s.span,{className:"vlist",style:{height:"0.8972em"},children:[(0,a.jsxs)(s.span,{style:{top:"-2.655em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(s.span,{className:"mord mtight",children:[(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"i"}),(0,a.jsx)(s.span,{className:"mopen mtight",children:"("}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",style:{marginRight:"0.01968em"},children:"l"}),(0,a.jsx)(s.span,{className:"mbin mtight",children:"+"}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"}),(0,a.jsx)(s.span,{className:"mclose mtight",children:")"})]})})]}),(0,a.jsxs)(s.span,{style:{top:"-3.23em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,a.jsxs)(s.span,{style:{top:"-3.4461em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(s.span,{className:"mord mtight",children:[(0,a.jsx)(s.span,{className:"mord mtight",children:"1000"}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"p"})]})})]})]}),(0,a.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,a.jsx)(s.span,{className:"vlist-r",children:(0,a.jsx)(s.span,{className:"vlist",style:{height:"0.52em"},children:(0,a.jsx)(s.span,{})})})]})}),(0,a.jsx)(s.span,{className:"mclose nulldelimiter"})]}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,a.jsx)(s.span,{className:"mrel",children:"="}),(0,a.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"1.3005em",verticalAlign:"-0.4033em"}}),(0,a.jsxs)(s.span,{className:"mord",children:[(0,a.jsx)(s.span,{className:"mopen nulldelimiter"}),(0,a.jsx)(s.span,{className:"mfrac",children:(0,a.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,a.jsxs)(s.span,{className:"vlist-r",children:[(0,a.jsxs)(s.span,{className:"vlist",style:{height:"0.8972em"},children:[(0,a.jsxs)(s.span,{style:{top:"-2.655em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(s.span,{className:"mord mtight",children:[(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"m"}),(0,a.jsx)(s.span,{className:"mbin mtight",children:"+"}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"i"}),(0,a.jsx)(s.span,{className:"mbin mtight",children:"\u22C5"}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"})]})})]}),(0,a.jsxs)(s.span,{style:{top:"-3.23em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,a.jsxs)(s.span,{style:{top:"-3.4461em"},children:[(0,a.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,a.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,a.jsxs)(s.span,{className:"mord mtight",children:[(0,a.jsx)(s.span,{className:"mord mtight",children:"1000"}),(0,a.jsx)(s.span,{className:"mord mathnormal mtight",children:"p"})]})})]})]}),(0,a.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,a.jsx)(s.span,{className:"vlist-r",children:(0,a.jsx)(s.span,{className:"vlist",style:{height:"0.4033em"},children:(0,a.jsx)(s.span,{})})})]})}),(0,a.jsx)(s.span,{className:"mclose nulldelimiter"})]})]})]})]})}),"\n",(0,a.jsxs)(s.p,{children:["Crazy, right? The score is simply the (normalized) profit you made divided by the leverage plus days invested. The ",(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mo,{children:"\u22C5"}),(0,a.jsx)(s.mn,{children:"1000"})]}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"\\cdot 1000"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"0.6444em"}}),(0,a.jsx)(s.span,{className:"mord",children:"\u22C5"}),(0,a.jsx)(s.span,{className:"mord",children:"1000"})]})})]})," is just to turn the number into something more reasonable - people don't like hearing something with a profitability score of .001 for example."]}),"\n",(0,a.jsx)(s.h2,{id:"theoretical-justification",children:"Theoretical Justification"}),"\n",(0,a.jsx)(s.p,{children:"The formula itself is designed to be simple in principle: I like making a profit, and I want to penalize the leverage you incur and days you have to invest. Ideally, we want to have a stock that goes up all the time. However, the investment formula takes advantage of a different case: trying to profit from highly volatile assets. If we can make money when the investment only has one day up, let's do it!"}),"\n",(0,a.jsxs)(s.p,{children:["Even so, there are two potential issues: First, stocks that trend upward will have a higher profitability score - both leverage and days invested will be 1. To protect against only investing in this trend, I can do things like taking ",(0,a.jsxs)(s.span,{className:"katex",children:[(0,a.jsx)(s.span,{className:"katex-mathml",children:(0,a.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(s.semantics,{children:[(0,a.jsxs)(s.mrow,{children:[(0,a.jsx)(s.mi,{children:"log"}),(0,a.jsx)(s.mo,{children:"\u2061"}),(0,a.jsx)(s.mo,{stretchy:"false",children:"("}),(0,a.jsx)(s.mi,{children:"d"}),(0,a.jsx)(s.mo,{stretchy:"false",children:")"})]}),(0,a.jsx)(s.annotation,{encoding:"application/x-tex",children:"\\log(d)"})]})})}),(0,a.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(s.span,{className:"base",children:[(0,a.jsx)(s.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,a.jsxs)(s.span,{className:"mop",children:["lo",(0,a.jsx)(s.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,a.jsx)(s.span,{className:"mopen",children:"("}),(0,a.jsx)(s.span,{className:"mord mathnormal",children:"d"}),(0,a.jsx)(s.span,{className:"mclose",children:")"})]})})]}),". I don't want to start biasing the scoring function until I have a practical reason to do so, so right now I'll leave it standing."]}),"\n",(0,a.jsx)(s.p,{children:"The second issue is how to penalize leverage and days invested relative to each other. As it currently stands, a leverage of 6x with only 1 day invested is the same as leveraging 2x with 3 days invested. In the future, I'd again want to look at making the impact of days invested smaller - I can get over an extra 3 days in the market if it means that I don't have to incur a highly leveraged position."}),"\n",(0,a.jsx)(s.p,{children:"So there could be things about the scoring function we change in the future, but I want to run some actual tests before we start worrying about things like that!"}),"\n",(0,a.jsx)(s.h2,{id:"running-a-simulation",children:"Running a simulation"}),"\n",(0,a.jsxs)(s.p,{children:["This won't be an incredibly rigorous backtest, I just want to see some results from the work so far. Let's set up the simulation code again, and start looking into some random stocks. ",(0,a.jsx)(s.strong,{children:"If you've read the last blog post, you can skip over the code."})," The only difference is that it's been ported to python to make the data-wrangling easier. Julia doesn't yet support some of the multi-index things I'm trying to do."]}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:'import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom Quandl import get as qget\n%matplotlib inline\napi_key = \'\'\n\nprofitability = lambda p, i, m, d: 1000*p / (m + i*d)\n\ndef is_profitable(current_price, purchase_history, open_history):\n shares = (purchase_history / open_history).sum()\n return current_price * shares > sum(purchase_history)\n\ndef daily_investment(current_open, current_close, purchase_history, open_history):\n t1 = current_close / current_open - 1\n t2 = (purchase_history - purchase_history * current_close / open_history).sum()\n return t2 / t1\n\ndef simulate_day(open_vals, close_vals, init, expected, bias):\n invested = np.array([init])\n \n day = 1\n profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\\n or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])\n\n while not profitable:\n expected_close = open_vals[day] * expected\n todays_purchase = daily_investment(open_vals[day], expected_close, invested, open_vals[0:day])\n invested = np.append(invested, todays_purchase + bias)\n # expected_profit = expected_close * (invested / open_vals[0:len(invested)]).sum() - invested.sum()\n day += 1\n profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\\n or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])\n \n shares = (invested / open_vals[0:len(invested)]).sum()\n \n # Make sure we can\'t see into the future - we know either today\'s close or tomorrow\'s open\n # will be profitable, but we need to check which one.\n if is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]):\n ending_price = close_vals[day-1]\n else:\n ending_price = open_vals[day]\n \n profit = shares * ending_price - sum(invested)\n return invested, profit\n\ndef simulate_ts(name, start, end, initial, expected, bias):\n ticker_info = qget(name, trim_start=start, api_key=api_key)\n evaluation_times = ticker_info[:end].index\n \n # Handle Google vs. YFinance data\n if "Adjusted Close" in ticker_info.columns:\n close_column = "Adjusted Close"\n else:\n close_column = "Close"\n \n sim = {d: simulate_day(ticker_info[d:]["Open"], ticker_info[d:][close_column],\n 100, 1.02, 10) for d in evaluation_times}\n sim_series = pd.Series(sim)\n result = pd.DataFrame()\n result["profit"] = sim_series.apply(lambda x: x[1])\n result["max"] = sim_series.apply(lambda x: max(x[0]))\n result["days"] = sim_series.apply(lambda x: len(x[0]))\n result["score"] = sim_series.apply(lambda x: profitability(x[1], x[0][0], max(x[0]), len(x[0])))\n result["investments"] = sim_series.apply(lambda x: x[0])\n \n return result\n\ndef simulate_tickers(tickers):\n from datetime import datetime\n results = {}\n for ticker in tickers:\n start = datetime(2015, 1, 1)\n results_df = simulate_ts(ticker, start, datetime(2016, 1, 1), 100, 1.01, 10)\n results[ticker] = results_df\n \n return pd.concat(list(results.values()), keys=list(results.keys()), axis=1)\n'})}),"\n",(0,a.jsx)(s.h2,{id:"and-now-the-interesting-part",children:"And now the interesting part"}),"\n",(0,a.jsx)(s.p,{children:"Let's start looking into the data! FANG stocks have been big over the past year, let's see how they look:"}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:'fang_df = simulate_tickers(["YAHOO/FB", "YAHOO/AAPL", "YAHOO/NFLX", "YAHOO/GOOG"])\n'})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"fang_df.xs('days', axis=1, level=1).hist()\nplt.gcf().set_size_inches(18, 8);\nplt.gcf().suptitle(\"Distribution of Days Until Profitability\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(8222).Z+"",width:"1048",height:"520"})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"fang_df.xs('score', axis=1, level=1).plot()\nplt.gcf().set_size_inches(18, 6)\nplt.gcf().suptitle(\"Profitability score over time\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(1122).Z+"",width:"1041",height:"388"})}),"\n",(0,a.jsx)(s.p,{children:"Let's think about these graphs. First, the histogram. What we like seeing is a lot of 1's - that means there were a lot of days that the stock went up and we didn't have to worry about actually implementing the strategy - we were able to close the trade at a profit."}),"\n",(0,a.jsx)(s.p,{children:"Looking at the profitability score over time though is a bit more interesting. First off, stocks that are more volatile will tend to have a higher profitability score, no two ways about that. However, Netflix consistently outperformed on this metric. We know that 2015 was a good year for Netflix, so that's a (small) sign the strategy is performing as expected."}),"\n",(0,a.jsx)(s.p,{children:"The final interesting note happens around the end of August 2015. Around this period, the markets were selling off in a big way due to issues in China (not unlike what's happening now). Even so, all of the FANG stocks saw an uptick in profitability around this time. This is another sign that the strategy being developed performs better during periods of volatility, rather than from riding markets up or down."}),"\n",(0,a.jsx)(s.p,{children:"What about FANG vs. some cyclicals?"}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:'cyclic_df = simulate_tickers(["YAHOO/X", "YAHOO/CAT", "YAHOO/NFLX", "YAHOO/GOOG"])\n'})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"cyclic_df.xs('days', axis=1, level=1).hist()\nplt.gcf().set_size_inches(18, 8);\nplt.gcf().suptitle(\"Distribution of Days Until Profitability\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(6991).Z+"",width:"1048",height:"520"})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"cyclic_df.xs('score', axis=1, level=1).plot()\nplt.gcf().set_size_inches(18, 6)\nplt.gcf().suptitle(\"Profitability score over time\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(598).Z+"",width:"1041",height:"388"})}),"\n",(0,a.jsx)(s.p,{children:"Some more interesting results come from this as well. First off, US Steel (X) has a much smoother distribution of days until profitability - it doesn't have a huge number of values at 1 and then drop off. Intuitively, we're not terribly large fans of this, we want a stock to go up! However, on the profitability score it is the only serious contender to Netflix."}),"\n",(0,a.jsx)(s.p,{children:"Second, we see the same trend around August - the algorithm performs well in volatile markets."}),"\n",(0,a.jsx)(s.p,{children:"For a final test, let's try some biotech and ETFs!"}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"biotech_df = simulate_tickers(['YAHOO/REGN', 'YAHOO/CELG', 'GOOG/NASDAQ_BIB', 'GOOG/NASDAQ_IBB'])\n"})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"biotech_df.xs('days', axis=1, level=1).hist()\nplt.gcf().set_size_inches(18, 8);\nplt.gcf().suptitle(\"Distribution of Days Until Profitability\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(7742).Z+"",width:"1048",height:"520"})}),"\n",(0,a.jsx)(s.pre,{children:(0,a.jsx)(s.code,{className:"language-python",children:"biotech_df.xs('score', axis=1, level=1).plot()\nplt.gcf().set_size_inches(18, 6)\nplt.gcf().suptitle(\"Profitability score over time\", fontsize=18);\n"})}),"\n",(0,a.jsx)(s.p,{children:(0,a.jsx)(s.img,{alt:"png",src:t(7168).Z+"",width:"1041",height:"388"})}),"\n",(0,a.jsx)(s.p,{children:"In this example, we don't see a whole lot of interesting things: the scores are all fairly close together with notable exceptions in late August, and mid-October."}),"\n",(0,a.jsx)(s.p,{children:"What is interesting is that during the volatile period, the ETF's performed significantly better than the stocks did in terms of profitability. The leveraged ETF (BIB) performed far above anyone else, and it appears that indeed, it is most profitable during volatile periods. Even so, it was far more likely to take multiple days to give a return. Its count of 1-day investments trails the other ETF and both stocks by a decent margin."}),"\n",(0,a.jsx)(s.p,{children:"And consider me an OCD freak, but I just really like Celgene's distribution - it looks nice and smooth."}),"\n",(0,a.jsx)(s.h2,{id:"summary-and-plans-for-the-next-post",children:"Summary and plans for the next post"}),"\n",(0,a.jsx)(s.p,{children:"So far I'm really enjoying playing with this strategy - there's a lot of depth here to understand, though the preliminary results seem to indicate that it profits mostly from taking the other side of a volatile trade. I'd be interested to run results later on data from January - It's been a particularly volatile start to the year so it would be neat to see whether this strategy would work then."}),"\n",(0,a.jsx)(s.p,{children:"For the next post, I want to start playing with some of the parameters: How do the bias and expected close influence the process? The values have been fairly conservative so far, it will be interesting to see how the simulations respond afterward."})]})}function m(e={}){let{wrapper:s}={...(0,i.a)(),...e.components};return s?(0,a.jsx)(s,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},7742:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_12_0-78c0e39ab1b402672551d197e388d2ba.png"},7168:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_13_0-d109b38c5db52ca12be209a2a268c6eb.png"},8222:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_4_0-46068cab7ea025b2c7ee79ad91eaf317.png"},1122:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_5_0-85416fdde3eb77aa133be1e7dab17d9f.png"},6991:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_8_0-f511f25f81b5b7b1baeaef267dd1a2b4.png"},598:function(e,s,t){t.d(s,{Z:function(){return n}});let n=t.p+"assets/images/_notebook_9_0-1bd353a1fa4f84f07d0964b59b00be1e.png"},65:function(e,s,t){t.d(s,{Z:function(){return r},a:function(){return l}});var n=t(7294);let a={},i=n.createContext(a);function l(e){let s=n.useContext(i);return n.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),n.createElement(i.Provider,{value:s},e.children)}},3071:function(e){e.exports=JSON.parse('{"permalink":"/2016/02/profitability-using-the-investment-formula","source":"@site/blog/2016-02-26-profitability-using-the-investment-formula/index.mdx","title":"Profitability using the investment formula","description":"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?","date":"2016-02-26T12:00:00.000Z","tags":[],"readingTime":7.675,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/profitability-using-the-investment-formula","title":"Profitability using the investment formula","date":"2016-02-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"},"nextItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"}}')}}]); \ No newline at end of file diff --git a/assets/js/36994c47.0c1ebe43.js b/assets/js/36994c47.0c1ebe43.js new file mode 100644 index 0000000..d0628d6 --- /dev/null +++ b/assets/js/36994c47.0c1ebe43.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2792"],{7934:function(e){e.exports=JSON.parse('{"name":"docusaurus-plugin-content-blog","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/39c8d8a0.ee5aa2e0.js b/assets/js/39c8d8a0.ee5aa2e0.js new file mode 100644 index 0000000..ac408b1 --- /dev/null +++ b/assets/js/39c8d8a0.ee5aa2e0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["156"],{5100:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return o},default:function(){return d},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return h}});var s=n(3303),i=n(5893),a=n(65);let r={slug:"2019/09/binary-format-shootout",title:"Binary format shootout",date:new Date("2019-09-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},h=[{value:"Prologue: Binary Parsing with Nom",id:"prologue-binary-parsing-with-nom",level:2},{value:"Cap'n Proto",id:"capn-proto",level:2},{value:"Flatbuffers",id:"flatbuffers",level:2},{value:"Simple Binary Encoding",id:"simple-binary-encoding",level:2},{value:"Results",id:"results",level:2},{value:"Serialization",id:"serialization",level:3},{value:"Deserialization",id:"deserialization",level:3},{value:"Conclusion",id:"conclusion",level:2}];function c(e){let t={a:"a",code:"code",del:"del",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["I've found that in many personal projects,\n",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Analysis_paralysis",children:"analysis paralysis"})," is particularly deadly.\nMaking good decisions in the beginning avoids pain and suffering later; if extra research prevents\nfuture problems, I'm happy to continue ",(0,i.jsx)(t.del,{children:"procrastinating"})," researching indefinitely."]}),"\n",(0,i.jsx)(t.p,{children:"So let's say you're in need of a binary serialization format. Data will be going over the network,\nnot just in memory, so having a schema document and code generation is a must. Performance is\ncrucial, so formats that support zero-copy de/serialization are given priority. And the more\nlanguages supported, the better; I use Rust, but can't predict what other languages this could\ninteract with."}),"\n",(0,i.jsx)(t.p,{children:"Given these requirements, the candidates I could find were:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://capnproto.org/",children:"Cap'n Proto"})," has been around the longest, and is the most established"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://google.github.io/flatbuffers/",children:"Flatbuffers"})," is the newest, and claims to have a simpler\nencoding"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://github.com/real-logic/simple-binary-encoding",children:"Simple Binary Encoding"})," has the simplest\nencoding, but the Rust implementation is unmaintained"]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably\nfast, and polyglot support. But how do you actually pick one? It's impossible to know what issues\nwill follow that choice, so I tend to avoid commitment until the last possible moment."}),"\n",(0,i.jsxs)(t.p,{children:['Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a\nsmall proof-of-concept system in each format and pit them against each other. All code can be found\nin the ',(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout",children:"repository"})," for this post."]}),"\n",(0,i.jsx)(t.p,{children:"We'll discuss more in detail, but a quick preview of the results:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Cap'n Proto: Theoretically performs incredibly well, the implementation had issues"}),"\n",(0,i.jsx)(t.li,{children:'Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises'}),"\n",(0,i.jsx)(t.li,{children:"SBE: Best median and worst-case performance, but the message structure has a limited feature set"}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"prologue-binary-parsing-with-nom",children:"Prologue: Binary Parsing with Nom"}),"\n",(0,i.jsxs)(t.p,{children:["Our benchmark system will be a simple data processor; given depth-of-book market data from\n",(0,i.jsx)(t.a,{href:"https://iextrading.com/trading/market-data/#deep",children:"IEX"}),", serialize each message into the schema\nformat, read it back, and calculate total size of stock traded and the lowest/highest quoted prices.\nThis test isn't complex, but is representative of the project I need a binary format for."]}),"\n",(0,i.jsxs)(t.p,{children:["But before we make it to that point, we have to actually read in the market data. To do so, I'm\nusing a library called ",(0,i.jsx)(t.a,{href:"https://github.com/Geal/nom",children:(0,i.jsx)(t.code,{children:"nom"})}),". Version 5.0 was recently released and\nbrought some big changes, so this was an opportunity to build a non-trivial program and get\nfamiliar."]}),"\n",(0,i.jsxs)(t.p,{children:["If you don't already know about ",(0,i.jsx)(t.code,{children:"nom"}),', it\'s a "parser generator". By combining different smaller\nparsers, you can assemble a parser to handle complex structures without writing tedious code by\nhand. For example, when parsing\n',(0,i.jsx)(t.a,{href:"https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#rfc.section.3.3",children:"PCAP files"}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" 0 1 2 3\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n +---------------------------------------------------------------+\n 0 | Block Type = 0x00000006 |\n +---------------------------------------------------------------+\n 4 | Block Total Length |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n 8 | Interface ID |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n12 | Timestamp (High) |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n16 | Timestamp (Low) |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n20 | Captured Len |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n24 | Packet Len |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n | Packet Data |\n | ... |\n"})}),"\n",(0,i.jsxs)(t.p,{children:["...you can build a parser in ",(0,i.jsx)(t.code,{children:"nom"})," that looks like\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/parsers.rs#L59-L93",children:"this"}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-rust",children:"const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];\npub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> {\n let (\n remaining,\n (\n block_type,\n block_len,\n interface_id,\n timestamp_high,\n timestamp_low,\n captured_len,\n packet_len,\n ),\n ) = tuple((\n tag(ENHANCED_PACKET),\n le_u32,\n le_u32,\n le_u32,\n le_u32,\n le_u32,\n le_u32,\n ))(input)?;\n\n let (remaining, packet_data) = take(captured_len)(remaining)?;\n Ok((remaining, packet_data))\n}\n"})}),"\n",(0,i.jsxs)(t.p,{children:["While this example isn't too interesting, more complex formats (like IEX market data) are where\n",(0,i.jsxs)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/iex.rs",children:[(0,i.jsx)(t.code,{children:"nom"})," really shines"]}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Ultimately, because the ",(0,i.jsx)(t.code,{children:"nom"})," code in this shootout was the same for all formats, we're not too\ninterested in its performance. Still, it's worth mentioning that building the market data parser was\nactually fun; I didn't have to write tons of boring code by hand."]}),"\n",(0,i.jsx)(t.h2,{id:"capn-proto",children:"Cap'n Proto"}),"\n",(0,i.jsxs)(t.p,{children:["Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried\nbecause of how long it has supported Rust (thanks to ",(0,i.jsx)(t.a,{href:"https://github.com/dwrensha",children:"dwrensha"})," for\nmaintaining the Rust port since\n",(0,i.jsx)(t.a,{href:"https://github.com/capnproto/capnproto-rust/releases/tag/rustc-0.10",children:"2014!"}),"). However, I had a ton\nof performance concerns once I started using it."]}),"\n",(0,i.jsxs)(t.p,{children:['To serialize new messages, Cap\'n Proto uses a "builder" object. This builder allocates memory on the\nheap to hold the message content, but because builders\n',(0,i.jsx)(t.a,{href:"https://github.com/capnproto/capnproto-rust/issues/111",children:"can't be re-used"}),", we have to allocate a\nnew buffer for every single message. I was able to work around this with a\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/capnp_runner.rs#L17-L51",children:"special builder"}),"\nthat could re-use the buffer, but it required reading through Cap'n Proto's\n",(0,i.jsx)(t.a,{href:"https://github.com/capnproto/capnproto-rust/blob/master/benchmark/benchmark.rs#L124-L156",children:"benchmarks"}),"\nto find an example, and used\n",(0,i.jsx)(t.a,{href:"https://doc.rust-lang.org/std/mem/fn.transmute.html",children:(0,i.jsx)(t.code,{children:"std::mem::transmute"})})," to bypass Rust's borrow\nchecker."]}),"\n",(0,i.jsxs)(t.p,{children:["The process of reading messages was better, but still had issues. Cap'n Proto has two message\nencodings: a ",(0,i.jsx)(t.a,{href:"https://capnproto.org/encoding.html#packing",children:'"packed"'})," representation, and an\n\"unpacked\" version. When reading \"packed\" messages, we need a buffer to unpack the message into\nbefore we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't\nable to figure out a way around that. In contrast, the unpacked message format should be where Cap'n\nProto shines; its main selling point is that there's ",(0,i.jsx)(t.a,{href:"https://capnproto.org/",children:"no decoding step"}),".\nHowever, accomplishing zero-copy deserialization required code in the private API\n(",(0,i.jsx)(t.a,{href:"https://github.com/capnproto/capnproto-rust/issues/148",children:"since fixed"}),"), and we allocate a vector on\nevery read for the segment table."]}),"\n",(0,i.jsx)(t.p,{children:"In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too\nmany issues for me to feel comfortable using it long-term."}),"\n",(0,i.jsx)(t.h2,{id:"flatbuffers",children:"Flatbuffers"}),"\n",(0,i.jsxs)(t.p,{children:["This is the new kid on the block. After a\n",(0,i.jsx)(t.a,{href:"https://github.com/google/flatbuffers/pull/3894",children:"first attempt"})," didn't pan out, official support\nwas ",(0,i.jsx)(t.a,{href:"https://github.com/google/flatbuffers/pull/4898",children:"recently launched"}),". Flatbuffers intends to\naddress the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The\ndifference is that Flatbuffers claims to have a simpler wire format and\n",(0,i.jsx)(t.a,{href:"https://google.github.io/flatbuffers/flatbuffers_benchmarks.html",children:"more flexibility"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["On the whole, I enjoyed using Flatbuffers; the ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/flatc-rust",children:"tooling"})," is\nnice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However,\nthere were still some issues."]}),"\n",(0,i.jsx)(t.p,{children:"First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats\nlike the following:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"table Message {\n symbol: string;\n}\ntable MultiMessage {\n messages:[Message];\n}\n"})}),"\n",(0,i.jsxs)(t.p,{children:["We want to create a ",(0,i.jsx)(t.code,{children:"MultiMessage"})," which contains a vector of ",(0,i.jsx)(t.code,{children:"Message"}),", and each ",(0,i.jsx)(t.code,{children:"Message"})," itself\ncontains a vector (the ",(0,i.jsx)(t.code,{children:"string"})," type). I was able to work around this by\n",(0,i.jsxs)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/e9d07d148bf36a211a6f86802b313c4918377d1b/src/flatbuffers_runner.rs#L83",children:["caching ",(0,i.jsx)(t.code,{children:"Message"})," elements"]}),"\nin a ",(0,i.jsx)(t.code,{children:"SmallVec"})," before building the final ",(0,i.jsx)(t.code,{children:"MultiMessage"}),", but it was a painful process that I\nbelieve contributed to poor serialization performance."]}),"\n",(0,i.jsxs)(t.p,{children:["Second, streaming support in Flatbuffers seems to be something of an\n",(0,i.jsx)(t.a,{href:"https://github.com/google/flatbuffers/issues/3898",children:"afterthought"}),". Where Cap'n Proto in Rust handles\nreading messages from a stream as part of the API, Flatbuffers just sticks a ",(0,i.jsx)(t.code,{children:"u32"})," at the front of\neach message to indicate the size. Not specifically a problem, but calculating message size without\nthat tag is nigh on impossible."]}),"\n",(0,i.jsx)(t.p,{children:"Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform\nwell."}),"\n",(0,i.jsx)(t.h2,{id:"simple-binary-encoding",children:"Simple Binary Encoding"}),"\n",(0,i.jsxs)(t.p,{children:["Support for SBE was added by the author of one of my favorite\n",(0,i.jsx)(t.a,{href:"https://web.archive.org/web/20190427124806/https://polysync.io/blog/session-types-for-hearty-codecs/",children:"Rust blog posts"}),".\nI've ",(0,i.jsx)(t.a,{href:"/2019/06/high-performance-systems",children:"talked previously"})," about how important\nvariance is in high-performance systems, so it was encouraging to read about a format that\n",(0,i.jsx)(t.a,{href:"https://github.com/real-logic/simple-binary-encoding/wiki/Why-Low-Latency",children:"directly addressed"})," my\nconcerns. SBE has by far the simplest binary format, but it does make some tradeoffs."]}),"\n",(0,i.jsxs)(t.p,{children:["Both Cap'n Proto and Flatbuffers use ",(0,i.jsx)(t.a,{href:"https://capnproto.org/encoding.html#structs",children:"message offsets"}),"\nto handle variable-length data, ",(0,i.jsx)(t.a,{href:"https://capnproto.org/language.html#unions",children:"unions"}),", and various\nother features. In contrast, messages in SBE are essentially\n",(0,i.jsx)(t.a,{href:"https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-samples/src/main/resources/example-schema.xml",children:"just structs"}),";\nvariable-length data is supported, but there's no union type."]}),"\n",(0,i.jsxs)(t.p,{children:["As mentioned in the beginning, the Rust port of SBE works well, but is\n",(0,i.jsx)(t.a,{href:"https://users.rust-lang.org/t/zero-cost-abstraction-frontier-no-copy-low-allocation-ordered-decoding/11515/9",children:"essentially unmaintained"}),".\nHowever, if you don't need union types, and can accept that schemas are XML documents, it's still\nworth using. SBE's implementation had the best streaming support of all formats I tested, and\ndoesn't trigger allocation during de/serialization."]}),"\n",(0,i.jsx)(t.h2,{id:"results",children:"Results"}),"\n",(0,i.jsxs)(t.p,{children:["After building a test harness\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/src/capnp_runner.rs",children:"for"}),"\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/src/flatbuffers_runner.rs",children:"each"}),"\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/src/sbe_runner.rs",children:"format"}),", it was\ntime to actually take them for a spin. I used\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/run_shootout.sh",children:"this script"})," to run\nthe benchmarks, and the raw results are\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/shootout.csv",children:"here"}),". All data reported\nbelow is the average of 10 runs on a single day of IEX data. Results were validated to make sure\nthat each format parsed the data correctly."]}),"\n",(0,i.jsx)(t.h3,{id:"serialization",children:"Serialization"}),"\n",(0,i.jsxs)(t.p,{children:["This test measures, on a\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L268-L272",children:"per-message basis"}),",\nhow long it takes to serialize the IEX message into the desired format and write to a pre-allocated\nbuffer."]}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Schema"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Median"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"99th Pctl"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"99.9th Pctl"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Total"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Cap'n Proto Packed"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"413ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1751ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"2943ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"14.80s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Cap'n Proto Unpacked"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"273ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1828ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"2836ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"10.65s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Flatbuffers"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"355ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"2185ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"3497ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"14.31s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"SBE"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"91ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1535ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"2423ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"3.91s"})]})]})]}),"\n",(0,i.jsx)(t.h3,{id:"deserialization",children:"Deserialization"}),"\n",(0,i.jsxs)(t.p,{children:["This test measures, on a\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L294-L298",children:"per-message basis"}),",\nhow long it takes to read the previously-serialized message and perform some basic aggregation. The\naggregation code is the same for each format, so any performance differences are due solely to the\nformat implementation."]}),"\n",(0,i.jsxs)(t.table,{children:[(0,i.jsx)(t.thead,{children:(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Schema"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Median"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"99th Pctl"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"99.9th Pctl"}),(0,i.jsx)(t.th,{style:{textAlign:"left"},children:"Total"})]})}),(0,i.jsxs)(t.tbody,{children:[(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Cap'n Proto Packed"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"539ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1216ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"2599ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"18.92s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Cap'n Proto Unpacked"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"366ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"737ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1583ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"12.32s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"Flatbuffers"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"173ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"421ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"1007ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"6.00s"})]}),(0,i.jsxs)(t.tr,{children:[(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"SBE"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"116ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"286ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"659ns"}),(0,i.jsx)(t.td,{style:{textAlign:"left"},children:"4.05s"})]})]})]}),"\n",(0,i.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,i.jsx)(t.p,{children:'Building a benchmark turned out to be incredibly helpful in making a decision; because a "union"\ntype isn\'t important to me, I can be confident that SBE best addresses my needs.'}),"\n",(0,i.jsx)(t.p,{children:"While SBE was the fastest in terms of both median and worst-case performance, its worst case\nperformance was proportionately far higher than any other format. It seems to be that\nde/serialization time scales with message size, but I'll need to do some more research to understand\nwhat exactly is going on."})]})}function d(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return r}});var s=n(7294);let i={},a=s.createContext(i);function r(e){let t=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(a.Provider,{value:t},e.children)}},3303:function(e){e.exports=JSON.parse('{"permalink":"/2019/09/binary-format-shootout","source":"@site/blog/2019-09-28-binary-format-shootout/index.mdx","title":"Binary format shootout","description":"I\'ve found that in many personal projects,","date":"2019-09-28T12:00:00.000Z","tags":[],"readingTime":8.37,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/09/binary-format-shootout","title":"Binary format shootout","date":"2019-09-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"},"nextItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"}}')}}]); \ No newline at end of file diff --git a/assets/js/3a2ddf2f.21bbad76.js b/assets/js/3a2ddf2f.21bbad76.js new file mode 100644 index 0000000..adabf17 --- /dev/null +++ b/assets/js/3a2ddf2f.21bbad76.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4844"],{531:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return i},default:function(){return p},frontMatter:function(){return r},metadata:function(){return a},toc:function(){return u}});var a=n(5288),o=n(5893),s=n(65);let r={slug:"2018/12/what-small-business-really-means",title:'More "what companies really mean"',date:new Date("2018-12-04T12:00:00.000Z"),authors:["bspeice"],tags:[]},i=void 0,l={authorsImageUrls:[void 0]},u=[{value:"How do you feel about production support?",id:"how-do-you-feel-about-production-support",level:2}];function c(e){let t={a:"a",em:"em",h2:"h2",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["I recently stumbled across a phenomenal small article entitled\n",(0,o.jsx)(t.a,{href:"https://angel.co/blog/what-startups-really-mean-by-why-should-we-hire-you",children:'What Startups Really Mean By "Why Should We Hire You?"'}),".\nHaving been interviewed by smaller companies (though not exactly startups), the questions and\nsubtexts are the same. There's often a question behind the question that you're actually trying to\nanswer, and I wish I spotted the nuance earlier in my career."]}),"\n",(0,o.jsx)(t.p,{children:"Let me also make note of one more question/euphemism I've come across:"}),"\n",(0,o.jsx)(t.h2,{id:"how-do-you-feel-about-production-support",children:"How do you feel about production support?"}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Translation"}),": ",(0,o.jsx)(t.em,{children:"We're a fairly small team, and when things break on an evening/weekend/Christmas\nDay, can we call on you to be there?"})]}),"\n",(0,o.jsx)(t.p,{children:'I\'ve met decidedly few people in my life who truly enjoy the "ops" side of "devops". They\'re\nincredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning\nthat into a functioning system at the end. And if they all left for lunch, we probably wouldn\'t make\nit out the door before the zombie apocalypse.'}),"\n",(0,o.jsx)(t.p,{children:"Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people\nwho either enjoy that, or play along nicely enough that our systems keep working."}),"\n",(0,o.jsx)(t.p,{children:'Small teams have no such luck. If you\'re interviewing at a small company, especially as a "data\nscientist" or other somesuch position, be aware that systems can and do spontaneously combust at the\nmost inopportune moments.'}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Terrible-but-popular answers include"}),": ",(0,o.jsx)(t.em,{children:"It's a part of the job, and I'm happy to contribute."})]})]})}function p(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return i},a:function(){return r}});var a=n(7294);let o={},s=a.createContext(o);function r(e){let t=a.useContext(s);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),a.createElement(s.Provider,{value:t},e.children)}},5288:function(e){e.exports=JSON.parse('{"permalink":"/2018/12/what-small-business-really-means","source":"@site/blog/2018-12-04-what-small-business-really-means/index.mdx","title":"More \\"what companies really mean\\"","description":"I recently stumbled across a phenomenal small article entitled","date":"2018-12-04T12:00:00.000Z","tags":[],"readingTime":1.205,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/what-small-business-really-means","title":"More \\"what companies really mean\\"","date":"2018-12-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731190109000,"prevItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"},"nextItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"}}')}}]); \ No newline at end of file diff --git a/assets/js/3aab746c.9a48ca86.js b/assets/js/3aab746c.9a48ca86.js new file mode 100644 index 0000000..03b3aee --- /dev/null +++ b/assets/js/3aab746c.9a48ca86.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1672"],{8204:function(e,n,t){t.r(n),t.d(n,{assets:function(){return h},contentTitle:function(){return o},default:function(){return d},frontMatter:function(){return i},metadata:function(){return a},toc:function(){return c}});var a=t(1403),r=t(5893),s=t(65);let i={slug:"2019/06/high-performance-systems",title:"On building high performance systems",date:new Date("2019-07-01T12:00:00.000Z"),last_updated:{date:new Date("2019-09-21T12:00:00.000Z")},authors:["bspeice"],tags:[]},o=void 0,h={authorsImageUrls:[void 0]},c=[{value:"Language-specific",id:"language-specific",level:2},{value:"Kernel",id:"kernel",level:2},{value:"Hardware",id:"hardware",level:2},{value:"Networks",id:"networks",level:2},{value:"Final Thoughts",id:"final-thoughts",level:2}];function l(e){let n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is\nmade up of people who have access to secret techniques mortal developers could only dream of. There\nhad to be some secret art that could only be learned if one had an appropriately tragic backstory."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Kung Fu fight",src:t(7743).Z+"",width:"426",height:"240"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:"How I assumed HFT people learn their secret techniques"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["How else do you explain people working on systems that complete the round trip of market data in to\norders out (a.k.a. tick-to-trade) consistently within\n",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/a/22082528/1454178",children:"750-800 nanoseconds"}),"? In roughly the time it takes a\ncomputer to access\n",(0,r.jsx)(n.a,{href:"https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html",children:"main memory 8 times"}),",\ntrading systems are capable of reading the market data packets, deciding what orders to send, doing\nrisk checks, creating new packets for exchange-specific protocols, and putting those packets on the\nwire."]}),"\n",(0,r.jsx)(n.p,{children:"Having now worked in the trading industry, I can confirm the developers aren't super-human; I've\nmade some simple mistakes at the very least. Instead, what shows up in public discussions is that\nphilosophy, not technique, separates high-performance systems from everything else.\nPerformance-critical systems don't rely on \"this one cool C++ optimization trick\" to make code fast\n(though micro-optimizations have their place); there's a lot more to worry about than just the code\nwritten for the project."}),"\n",(0,r.jsxs)(n.p,{children:["The framework I'd propose is this: ",(0,r.jsx)(n.strong,{children:"If you want to build high-performance systems, focus first on\nreducing performance variance"})," (reducing the gap between the fastest and slowest runs of the same\ncode), ",(0,r.jsx)(n.strong,{children:"and only look at average latency once variance is at an acceptable level"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20\nseconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes\na full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a\nweek is the same in each situation, but you're painfully aware of that minute when it happens. When\nit comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds\ndoesn't mean much if there's a 100ms difference between your fastest and slowest runs. When\nperformance matters, you need to respond quickly ",(0,r.jsx)(n.em,{children:"every time"}),", not just in aggregate.\nHigh-performance systems should first optimize for time variance. Once you're consistent at the time\nscale you care about, then focus on improving average time."]}),"\n",(0,r.jsx)(n.p,{children:"This focus on variance shows up all the time in industry too (emphasis added in all quotes below):"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["In ",(0,r.jsx)(n.a,{href:"https://business.nasdaq.com/market-tech/marketplaces/trading",children:"marketing materials"})," for\nNASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability\nis highlighted in addition to instantaneous metrics:"]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["Able to ",(0,r.jsx)(n.strong,{children:"consistently sustain"})," an order rate of over 100,000 orders per second at sub-40\nmicrosecond average latency"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.a,{href:"https://github.com/real-logic/aeron",children:"Aeron"})," message bus has this to say about performance:"]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and\n",(0,r.jsx)(n.strong,{children:"most predictable latency possible"})," of any messaging system"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["The company PolySync, which is working on autonomous vehicles,\n",(0,r.jsx)(n.a,{href:"https://polysync.io/blog/session-types-for-hearty-codecs/",children:"mentions why"})," they picked their\nspecific messaging format:"]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["In general, high performance is almost always desirable for serialization. But in the world of\nautonomous vehicles, ",(0,r.jsx)(n.strong,{children:"steady timing performance is even more important"})," than peak throughput.\nThis is because safe operation is sensitive to timing outliers. Nobody wants the system that\ndecides when to slam on the brakes to occasionally take 100 times longer than usual to encode\nits commands."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://solarflare.com/",children:"Solarflare"}),", which makes highly-specialized network hardware, points out\nvariance (jitter) as a big concern for\n",(0,r.jsx)(n.a,{href:"https://solarflare.com/electronic-trading/",children:"electronic trading"}),":"]}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:["The high stakes world of electronic trading, investment banks, market makers, hedge funds and\nexchanges demand the ",(0,r.jsx)(n.strong,{children:"lowest possible latency and jitter"})," while utilizing the highest\nbandwidth and return on their investment."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["And to further clarify: we're not discussing ",(0,r.jsx)(n.em,{children:"total run-time"}),", but variance of total run-time. There\nare situations where it's not reasonably possible to make things faster, and you'd much rather be\nconsistent. For example, trading firms use\n",(0,r.jsx)(n.a,{href:"https://sniperinmahwah.wordpress.com/2017/06/07/network-effects-part-i/",children:"wireless networks"})," because\nthe speed of light through air is faster than through fiber-optic cables. There's still at ",(0,r.jsx)(n.em,{children:"absolute\nminimum"})," a ",(0,r.jsx)(n.a,{href:"http://tinyurl.com/y2vd7tn8",children:"~33.76 millisecond"})," delay required to send data between,\nsay,\n",(0,r.jsx)(n.a,{href:"https://www.theice.com/market-data/connectivity-and-feeds/wireless/tokyo-chicago",children:"Chicago and Tokyo"}),'.\nIf a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a\ntrade occurs, there\'s a physical limit to how long that will take. In this situation, the focus is\non keeping variance of ',(0,r.jsx)(n.em,{children:"additional processing"})," to a minimum, since speed of light is the limiting\nfactor."]}),"\n",(0,r.jsxs)(n.p,{children:["So how does one go about looking for and eliminating performance variance? To tell the truth, I\ndon't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep\nunderstanding of the entire technology stack, and (B) actually measuring system performance (though\n(C) watching a lot of ",(0,r.jsx)(n.a,{href:"https://www.youtube.com/channel/UCMlGfpWw-RUdWX_JbLCukXg",children:"CppCon"})," videos for\ninspiration never hurt). Even then, every project cares about performance to a different degree; you\nmay need to build an entire\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=3015",children:"replica production system"})," to\naccurately benchmark at nanosecond precision, or you may be content to simply\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=BD9cRbxWQx8&feature=youtu.be&t=1335",children:"avoid garbage collection"})," in\nyour Java code."]}),"\n",(0,r.jsx)(n.p,{children:"Even though everyone has different needs, there are still common things to look for when trying to\nisolate and eliminate variance. In no particular order, these are my focus areas when thinking about\nhigh-performance systems:"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Update 2019-09-21"}),": Added notes on ",(0,r.jsx)(n.code,{children:"isolcpus"})," and ",(0,r.jsx)(n.code,{children:"systemd"})," affinity."]}),"\n",(0,r.jsx)(n.h2,{id:"language-specific",children:"Language-specific"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Garbage Collection"}),": How often does garbage collection happen? When is it triggered? What are the\nimpacts?"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://rushter.com/blog/python-garbage-collector/",children:"In Python"}),", individual objects are collected\nif the reference count reaches 0, and each generation is collected if\n",(0,r.jsx)(n.code,{children:"num_alloc - num_dealloc > gc_threshold"})," whenever an allocation happens. The GIL is acquired for\nthe duration of generational collection."]}),"\n",(0,r.jsxs)(n.li,{children:["Java has\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/en/java/javase/12/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE",children:"many"}),"\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573",children:"different"}),"\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector-tuning.html#GUID-90E30ACA-8040-432E-B3A0-1E0440AB556A",children:"collection"}),"\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/en/java/javase/12/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0",children:"algorithms"}),"\nto choose from, each with different characteristics. The default algorithms (Parallel GC in Java\n8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms\n(",(0,r.jsx)(n.a,{href:"https://wiki.openjdk.java.net/display/zgc",children:"ZGC"})," and\n",(0,r.jsx)(n.a,{href:"https://wiki.openjdk.java.net/display/shenandoah",children:"Shenandoah"}),') are designed to keep "stop the\nworld" to a minimum by doing collection work in parallel.']}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Allocation"}),': Every language has a different way of interacting with "heap" memory, but the\nprinciple is the same: running the allocator to allocate/deallocate memory takes time that can often\nbe put to better use. Understanding when your language interacts with the allocator is crucial, and\nnot always obvious. For example: C++ and Rust don\'t allocate heap memory for iterators, but Java\ndoes (meaning potential GC pauses). Take time to understand heap behavior (I made a\n',(0,r.jsx)(n.a,{href:"/2019/02/understanding-allocations-in-rust",children:"a guide for Rust"}),"), and look into alternative\nallocators (",(0,r.jsx)(n.a,{href:"http://jemalloc.net/",children:"jemalloc"}),",\n",(0,r.jsx)(n.a,{href:"https://gperftools.github.io/gperftools/tcmalloc.html",children:"tcmalloc"}),") that might run faster than the\noperating system default."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Data Layout"}),": How your data is arranged in memory matters;\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=yy8jQgmhbAU",children:"data-oriented design"})," and\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=1185",children:"cache locality"})," can have huge\nimpacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have\nguarantees about the shape every object takes in memory that others (e.g. Java and Python) can't\nmake. ",(0,r.jsx)(n.a,{href:"http://valgrind.org/docs/manual/cg-manual.html",children:"Cachegrind"})," and kernel\n",(0,r.jsx)(n.a,{href:"https://perf.wiki.kernel.org/index.php/Main_Page",children:"perf"})," counters are both great for understanding\nhow performance relates to memory layout."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Just-In-Time Compilation"}),": Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are\ngreat because they optimize your program for how it's actually being used, rather than how a\ncompiler expects it to be used. However, there's a variance problem if the program stops executing\nwhile waiting for translation from VM bytecode to native code. As a remedy, many languages support\nahead-of-time compilation in addition to the JIT versions\n(",(0,r.jsx)(n.a,{href:"https://github.com/dotnet/corert",children:"CoreRT"})," in C# and ",(0,r.jsx)(n.a,{href:"https://www.graalvm.org/",children:"GraalVM"})," in Java).\nOn the other hand, LLVM supports\n",(0,r.jsx)(n.a,{href:"https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization",children:"Profile Guided Optimization"}),",\nwhich theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing\napples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT\ncompiler kicked in."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Programming Tricks"}),": These won't make or break performance, but can be useful in specific\ncircumstances. For example, C++ can use\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=1206",children:"templates instead of branches"}),"\nin critical sections."]}),"\n",(0,r.jsx)(n.h2,{id:"kernel",children:"Kernel"}),"\n",(0,r.jsxs)(n.p,{children:["Code you wrote is almost certainly not the ",(0,r.jsx)(n.em,{children:"only"})," code running on your hardware. There are many ways\nthe operating system interacts with your program, from interrupts to system calls, that are\nimportant to watch for. These are written from a Linux perspective, but Windows does typically have\nequivalent functionality."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Scheduling"}),": The kernel is normally free to schedule any process on any core, so it's important\nto reserve CPU cores exclusively for the important programs. There are a few parts to this: first,\nlimit the CPU cores that non-critical processes are allowed to run on by excluding cores from\nscheduling\n(",(0,r.jsx)(n.a,{href:"https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re46.html",children:(0,r.jsx)(n.code,{children:"isolcpus"})}),"\nkernel command-line option), or by setting the ",(0,r.jsx)(n.code,{children:"init"})," process CPU affinity\n(",(0,r.jsxs)(n.a,{href:"https://access.redhat.com/solutions/2884991",children:[(0,r.jsx)(n.code,{children:"systemd"})," example"]}),"). Second, set critical processes\nto run on the isolated cores by setting the\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Processor_affinity",children:"processor affinity"})," using\n",(0,r.jsx)(n.a,{href:"https://linux.die.net/man/1/taskset",children:"taskset"}),". Finally, use\n",(0,r.jsx)(n.a,{href:"https://github.com/torvalds/linux/blob/master/Documentation/timers/NO_HZ.txt",children:(0,r.jsx)(n.code,{children:"NO_HZ"})})," or\n",(0,r.jsx)(n.a,{href:"https://linux.die.net/man/1/chrt",children:(0,r.jsx)(n.code,{children:"chrt"})})," to disable scheduling interrupts. Turning off\nhyper-threading is also likely beneficial."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"System calls"}),": Reading from a UNIX socket? Writing to a file? In addition to not knowing how long\nthe I/O operation takes, these all trigger expensive\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/System_call",children:"system calls (syscalls)"}),". To handle these, the CPU must\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Context_switch",children:"context switch"})," to the kernel, let the kernel\noperation complete, then context switch back to your program. We'd rather keep these\n",(0,r.jsx)(n.a,{href:"https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript",children:"to a minimum"})," (see\ntimestamp 18:20). ",(0,r.jsx)(n.a,{href:"https://linux.die.net/man/1/strace",children:"Strace"})," is your friend for understanding when\nand where syscalls happen."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Signal Handling"}),": Far less likely to be an issue, but signals do trigger a context switch if your\ncode has a handler registered. This will be highly dependent on the application, but you can\n",(0,r.jsx)(n.a,{href:"https://www.linuxprogrammingblog.com/all-about-linux-signals?page=show#Blocking_signals",children:"block signals"}),"\nif it's an issue."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Interrupts"}),": System interrupts are how devices connected to your computer notify the CPU that\nsomething has happened. The CPU will then choose a processor core to pause and context switch to the\nOS to handle the interrupt. Make sure that\n",(0,r.jsx)(n.a,{href:"http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux",children:"SMP affinity"})," is\nset so that interrupts are handled on a CPU core not running the program you care about."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.a,{href:"https://www.kernel.org/doc/html/latest/vm/numa.html",children:"NUMA"})}),": While NUMA is good at making\nmulti-cell systems transparent, there are variance implications; if the kernel moves a process\nacross nodes, future memory accesses must wait for the controller on the original node. Use\n",(0,r.jsx)(n.a,{href:"https://linux.die.net/man/8/numactl",children:"numactl"})," to handle memory-/cpu-cell pinning so this doesn't\nhappen."]}),"\n",(0,r.jsx)(n.h2,{id:"hardware",children:"Hardware"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"CPU Pipelining/Speculation"}),": Speculative execution in modern processors gave us vulnerabilities\nlike Spectre, but it also gave us performance improvements like\n",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/a/11227902/1454178",children:"branch prediction"}),". And if the CPU mis-speculates\nyour code, there's variance associated with rewind and replay. While the compiler knows a lot about\nhow your CPU ",(0,r.jsx)(n.a,{href:"https://youtu.be/nAbCKa0FzjQ?t=4467",children:"pipelines instructions"}),", code can be\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=755",children:"structured to help"})," the branch\npredictor."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Paging"}),": For most systems, virtual memory is incredible. Applications live in their own worlds,\nand the CPU/",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Memory_management_unit",children:"MMU"})," figures out the details.\nHowever, there's a variance penalty associated with memory paging and caching; if you access more\nmemory pages than the ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Translation_lookaside_buffer",children:"TLB"})," can store,\nyou'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an\nissue, but using ",(0,r.jsx)(n.a,{href:"https://blog.pythian.com/performance-tuning-hugepages-in-linux/",children:"huge pages"})," can\nreduce TLB burdens. Alternately, running applications in a hypervisor like\n",(0,r.jsx)(n.a,{href:"https://github.com/siemens/jailhouse",children:"Jailhouse"})," allows one to skip virtual memory entirely, but\nthis is probably more work than the benefits are worth."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Network Interfaces"}),": When more than one computer is involved, variance can go up dramatically.\nTuning kernel\n",(0,r.jsx)(n.a,{href:"https://github.com/leandromoreira/linux-network-performance-parameters",children:"network parameters"})," may be\nhelpful, but modern systems more frequently opt to skip the kernel altogether with a technique\ncalled ",(0,r.jsx)(n.a,{href:"https://blog.cloudflare.com/kernel-bypass/",children:"kernel bypass"}),". This typically requires\nspecialized hardware and ",(0,r.jsx)(n.a,{href:"https://www.openonload.org/",children:"drivers"}),", but even industries like\n",(0,r.jsx)(n.a,{href:"https://www.bbc.co.uk/rd/blog/2018-04-high-speed-networking-open-source-kernel-bypass",children:"telecom"})," are\nfinding the benefits."]}),"\n",(0,r.jsx)(n.h2,{id:"networks",children:"Networks"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Routing"}),": There's a reason financial firms are willing to pay\n",(0,r.jsx)(n.a,{href:"https://sniperinmahwah.wordpress.com/2019/03/26/4-les-moeres-english-version/",children:"millions of euros"}),"\nfor rights to a small plot of land - having a straight-line connection from point A to point B means\nthe path their data takes is the shortest possible. In contrast, there are currently 6 computers in\nbetween me and Google, but that may change at any moment if my ISP realizes a\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Border_Gateway_Protocol",children:"more efficient route"})," is available. Whether\nit's using\n",(0,r.jsx)(n.a,{href:"https://sniperinmahwah.wordpress.com/2018/05/07/shortwave-trading-part-i-the-west-chicago-tower-mystery/",children:"research-quality equipment"}),"\nfor shortwave radio, or just making sure there's no data inadvertently going between data centers,\nrouting matters."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Protocol"}),": TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control,\nand congestion control all built in. But these attributes make the most sense when networking\ninfrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the\nsetup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may\nmake sense in these contexts as it avoids the chatter needed to track connection state, and\n",(0,r.jsx)(n.a,{href:"https://iextrading.com/docs/IEX%20Transport%20Specification.pdf",children:"gap-fill"}),"\n",(0,r.jsx)(n.a,{href:"http://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/moldudp64.pdf",children:"strategies"}),"\ncan handle the rest."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Switching"}),': Many routers/switches handle packets using "store-and-forward" behavior: wait for the\nwhole packet, validate checksums, and then send to the next device. In variance terms, the time\nneeded to move data between two nodes is proportional to the size of that data; the switch must\n"store" all data before it can calculate checksums and "forward" to the next node. With\n',(0,r.jsx)(n.a,{href:"https://www.networkworld.com/article/2241573/latency-and-jitter--cut-through-design-pays-off-for-arista--blade.html",children:'"cut-through"'}),"\ndesigns, switches will begin forwarding data as soon as they know where the destination is,\nchecksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter\nthe size."]}),"\n",(0,r.jsx)(n.h2,{id:"final-thoughts",children:"Final Thoughts"}),"\n",(0,r.jsxs)(n.p,{children:["High-performance systems, regardless of industry, are not magical. They do require extreme precision\nand attention to detail, but they're designed, built, and operated by regular people, using a lot of\ntools that are publicly available. Interested in seeing how context switching affects performance of\nyour benchmarks? ",(0,r.jsx)(n.code,{children:"taskset"})," should be installed in all modern Linux distributions, and can be used to\nmake sure the OS never migrates your process. Curious how often garbage collection triggers during a\ncrucial operation? Your language of choice will typically expose details of its operations\n(",(0,r.jsx)(n.a,{href:"https://docs.python.org/3/library/gc.html",children:"Python"}),",\n",(0,r.jsx)(n.a,{href:"https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#DebuggingOptions",children:"Java"}),").\nWant to know how hard your program is stressing the TLB? Use ",(0,r.jsx)(n.code,{children:"perf record"})," and look for\n",(0,r.jsx)(n.code,{children:"dtlb_load_misses.miss_causes_a_walk"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Two final guiding questions, then: first, before attempting to apply some of the technology above to\nyour own systems, can you first identify\n",(0,r.jsx)(n.a,{href:"http://wiki.c2.com/?PrematureOptimization",children:"where/when you care"})," about \"high-performance\"? As an\nexample, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable\neffect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are\nthey being designed in a way that's actually helpful? Tools like\n",(0,r.jsx)(n.a,{href:"http://www.serpentine.com/criterion/",children:"Criterion"})," (also in\n",(0,r.jsx)(n.a,{href:"https://github.com/bheisler/criterion.rs",children:"Rust"}),") and Google's\n",(0,r.jsx)(n.a,{href:"https://github.com/google/benchmark",children:"Benchmark"})," output not only average run time, but variance as\nwell; your benchmarking environment is subject to the same concerns your production environment is."]}),"\n",(0,r.jsx)(n.p,{children:"Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique.\nRigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate\nit; once that's at an acceptable level, then optimize for speed."})]})}function d(e={}){let{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},7743:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/kung-fu-5715f30eef7bf3aaa26770b1247024dc.webp"},65:function(e,n,t){t.d(n,{Z:function(){return o},a:function(){return i}});var a=t(7294);let r={},s=a.createContext(r);function i(e){let n=a.useContext(s);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),a.createElement(s.Provider,{value:n},e.children)}},1403:function(e){e.exports=JSON.parse('{"permalink":"/2019/06/high-performance-systems","source":"@site/blog/2019-06-31-high-performance-systems/index.mdx","title":"On building high performance systems","description":"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is","date":"2019-07-01T12:00:00.000Z","tags":[],"readingTime":12.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/06/high-performance-systems","title":"On building high performance systems","date":"2019-07-01T12:00:00.000Z","last_updated":{"date":"2019-09-21T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"},"nextItem":{"title":"Making bread","permalink":"/2019/05/making-bread"}}')}}]); \ No newline at end of file diff --git a/assets/js/3cafba32.27890503.js b/assets/js/3cafba32.27890503.js new file mode 100644 index 0000000..470fc28 --- /dev/null +++ b/assets/js/3cafba32.27890503.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6267"],{6376:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return o},default:function(){return h},frontMatter:function(){return s},metadata:function(){return a},toc:function(){return l}});var a=n(3628),i=n(5893),r=n(65);let s={slug:"2016/01/cloudy-in-seattle",title:"Cloudy in Seattle",date:new Date("2016-01-23T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Examining other cities",id:"examining-other-cities",level:2},{value:"Conclusion",id:"conclusion",level:2}];function d(e){let t={code:"code",h2:"h2",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Building on prior analysis, is Seattle's reputation as a depressing city actually well-earned?"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import pickle\nimport pandas as pd\nimport numpy as np\nfrom bokeh.plotting import output_notebook, figure, show\nfrom bokeh.palettes import RdBu4 as Palette\nfrom datetime import datetime\nimport warnings\n\noutput_notebook()\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"BokehJS successfully loaded.\n"})}),"\n",(0,i.jsx)(t.h2,{id:"examining-other-cities",children:"Examining other cities"}),"\n",(0,i.jsx)(t.p,{children:"After taking some time to explore how the weather in North Carolina stacked up over the past years, I was interested in doing the same analysis for other cities. Growing up with family from Binghamton, NY I was always told it was very cloudy there. And Seattle has a nasty reputation for being very depressing and cloudy. All said, the cities I want to examine are:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Binghamton, NY"}),"\n",(0,i.jsx)(t.li,{children:"Cary, NC"}),"\n",(0,i.jsx)(t.li,{children:"Seattle, WA"}),"\n",(0,i.jsx)(t.li,{children:"New York City, NY"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"I'd be interested to try this analysis worldwide at some point - comparing London and Seattle might be an interesting analysis. For now though, we'll stick with trying out the US data."}),"\n",(0,i.jsxs)(t.p,{children:["There will be plenty of charts. I want to know: ",(0,i.jsx)(t.strong,{children:"How has average cloud cover and precipitation chance changed over the years for each city mentioned?"})," This will hopefully tell us whether Seattle has actually earned its reputation for being a depressing city."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"city_forecasts = pickle.load(open('city_forecasts.p', 'rb'))\nforecasts_df = pd.DataFrame.from_dict(city_forecasts)\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"cities = ['binghamton', 'cary', 'nyc', 'seattle']\ncity_colors = {cities[i]: Palette[i] for i in range(0, 4)}\n\ndef safe_cover(frame):\n if frame and 'cloudCover' in frame:\n return frame['cloudCover']\n else:\n return np.NaN\n\ndef monthly_avg_cloudcover(city, year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n cloud_cover_vals = list(map(lambda x: safe_cover(forecasts_df[city][x]['currently']), dates))\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\n # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below.\n with warnings.catch_warnings():\n warnings.simplefilter('ignore')\n return np.nanmean(cloud_cover_vals), cloud_cover_samples\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"years = range(1990, 2016)\ndef city_avg_cc(city, month):\n return [monthly_avg_cloudcover(city, y, month) for y in years]\n\nmonths = [\n ('July', 7),\n ('August', 8),\n ('September', 9),\n ('October', 10),\n ('November', 11)\n]\n\nfor month, month_id in months:\n month_averages = {city: city_avg_cc(city, month_id) for city in cities}\n f = figure(title=\"{} Average Cloud Cover\".format(month),\n x_axis_label='Year',\n y_axis_label='Cloud Cover Percentage')\n for city in cities:\n f.line(years, [x[0] for x in month_averages[city]],\n legend=city, color=city_colors[city])\n show(f)\n"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.img,{alt:"July average cloud cover chart",src:n(4326).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"August average cloud cover chart",src:n(6529).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"September average cloud cover chart",src:n(731).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"October average cloud cover chart",src:n(5716).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"November average cloud cover chart",src:n(8564).Z+"",width:"600",height:"600"})]}),"\n",(0,i.jsx)(t.p,{children:"Well, as it so happens it looks like there are some data issues. July's data is a bit sporadic, and 2013 seems to be missing from most months as well. I think really only two things can really be confirmed here:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Seattle, specifically for the months of October and November, is in fact significantly more cloudy on average than are other cities"}),"\n",(0,i.jsx)(t.li,{children:"All cities surveyed have seen average cloud cover decline over the months studied. There are data issues, but the trend seems clear."}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Let's now move from cloud cover data to looking at average rainfall chance."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"def safe_precip(frame):\n if frame and 'precipProbability' in frame:\n return frame['precipProbability']\n else:\n return np.NaN\n\ndef monthly_avg_precip(city, year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n precip_vals = list(map(lambda x: safe_precip(forecasts_df[city][x]['currently']), dates))\n precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))\n # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below.\n with warnings.catch_warnings():\n warnings.simplefilter('ignore')\n return np.nanmean(precip_vals), precip_samples\n\ndef city_avg_precip(city, month):\n return [monthly_avg_precip(city, y, month) for y in years]\n\nfor month, month_id in months:\n month_averages = {city: city_avg_cc(city, month_id) for city in cities}\n f = figure(title=\"{} Average Precipitation Chance\".format(month),\n x_axis_label='Year',\n y_axis_label='Precipitation Chance Percentage')\n for city in cities:\n f.line(years, [x[0] for x in month_averages[city]],\n legend=city, color=city_colors[city])\n show(f)\n"})}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.img,{alt:"July average precipitation chance chart",src:n(5074).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"August average precipitation chance chart",src:n(6856).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"September average precipitation chance chart",src:n(619).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"October average precipitation chance chart",src:n(6071).Z+"",width:"600",height:"600"}),"\n",(0,i.jsx)(t.img,{alt:"November average precipitation chance chart",src:n(1340).Z+"",width:"600",height:"600"})]}),"\n",(0,i.jsx)(t.p,{children:"The same data issue caveats apply here: 2013 seems to be missing some data, and July has some issues as well. However, this seems to confirm the trends we saw with cloud cover:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Seattle, specifically for the months of August, October, and November has had a consistently higher chance of rain than other cities surveyed."}),"\n",(0,i.jsx)(t.li,{children:"Average precipitation chance, just like average cloud cover, has been trending down over time."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,i.jsx)(t.p,{children:"I have to admit I was a bit surprised after doing this analysis. Seattle showed a higher average cloud cover and average precipitation chance than did the other cities surveyed. Maybe Seattle is actually an objectively more depressing city to live in."}),"\n",(0,i.jsx)(t.p,{children:"Well that's all for weather data at the moment. It's been a great experiment, but I think this is about as far as I'll be able to get with weather data without some domain knowledge. Talk again soon!"})]})}function h(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},4326:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/1-2d6670430a11b01011e4c231ea594db1.png"},1340:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/10-b7987a0ff93705d5045057cbdaa2ede9.png"},6529:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/2-46bb7cc9cf739d97050c199eedced1a7.png"},731:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/3-2f5c483659f81d741809de6d095bd577.png"},5716:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/4-63dc81954b1604cfa91f4c789da144a5.png"},8564:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/5-ae210d26729cea1700924579adf2c44c.png"},5074:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/6-f07e72ff0b4639453034c75b2e62faba.png"},6856:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/7-e0793eed6c42845d8ce4e3e79c1d44d8.png"},619:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/8-3eb2ad63e4c40b6717ee4516223d73ed.png"},6071:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/9-630bd32c43e654f068e3c3bea79810e5.png"},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return s}});var a=n(7294);let i={},r=a.createContext(i);function s(e){let t=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:t},e.children)}},3628:function(e){e.exports=JSON.parse('{"permalink":"/2016/01/cloudy-in-seattle","source":"@site/blog/2016-01-23-cloudy-in-seattle/index.mdx","title":"Cloudy in Seattle","description":"Building on prior analysis, is Seattle\'s reputation as a depressing city actually well-earned?","date":"2016-01-23T12:00:00.000Z","tags":[],"readingTime":3.965,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/cloudy-in-seattle","title":"Cloudy in Seattle","date":"2016-01-23T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730683607000,"prevItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"},"nextItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"}}')}}]); \ No newline at end of file diff --git a/assets/js/3d0fb9fd.94683b2b.js b/assets/js/3d0fb9fd.94683b2b.js new file mode 100644 index 0000000..bb671bd --- /dev/null +++ b/assets/js/3d0fb9fd.94683b2b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4384"],{2736:function(e,t,n){n.r(t),n.d(t,{assets:function(){return h},contentTitle:function(){return a},default:function(){return d},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return c}});var s=n(8595),i=n(5893),o=n(65);let r={slug:"2018/09/isomorphic-apps",title:"Isomorphic desktop apps with Rust",date:new Date("2018-09-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},a="Setting the Stage",h={authorsImageUrls:[void 0]},c=[];function l(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["I both despise Javascript and am stunned by its success doing some really cool things. It's\n",(0,i.jsx)(t.a,{href:"https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript",children:"this duality"})," that's\nled me to a couple of (very) late nights over the past weeks trying to reconcile myself as I\nbootstrap a simple desktop application."]}),"\n",(0,i.jsxs)(t.p,{children:["See, as much as\n",(0,i.jsx)(t.a,{href:"https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript",children:"Webassembly isn't trying to replace Javascript"}),",\n",(0,i.jsx)(t.strong,{children:"I want Javascript gone"}),". There are plenty of people who don't share my views, and they are\nprobably nicer and more fun at parties. But I cringe every time \"Webpack\" is mentioned, and I think\nit's hilarious that the\n",(0,i.jsx)(t.a,{href:"https://ecma-international.org/publications/standards/Ecma-402.htm",children:"language specification"}),"\ndramatically outpaces anyone's\n",(0,i.jsx)(t.a,{href:"https://kangax.github.io/compat-table/es2016plus/",children:"actual implementation"}),". The answer to this\nconundrum is of course to recompile code from newer versions of the language to older versions ",(0,i.jsx)(t.em,{children:"of\nthe same language"})," before running. At least ",(0,i.jsx)(t.a,{href:"https://babeljs.io/",children:"Babel"})," is a nice tongue-in-cheek reference."]}),"\n",(0,i.jsxs)(t.p,{children:["Yet for as much hate as ",(0,i.jsx)(t.a,{href:"https://electronjs.org/",children:"Electron"})," receives, it does a stunningly good job at solving a really hard\nproblem: ",(0,i.jsx)(t.em,{children:"how the hell do I put a button on the screen and react when the user clicks it"}),"? GUI\nprogramming is hard, straight up. But if browsers are already able to run everywhere, why don't we\ntake advantage of someone else solving the hard problems for us? I don't like that I have to use\nJavascript for it, but I really don't feel inclined to whip out good ol' ",(0,i.jsx)(t.a,{href:"https://wxwidgets.org/",children:"wxWidgets"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Now there are other native solutions (",(0,i.jsx)(t.a,{href:"https://github.com/LeoTindall/libui-rs/",children:"libui-rs"}),", ",(0,i.jsx)(t.a,{href:"https://github.com/PistonDevelopers/conrod",children:"conrod"}),", ",(0,i.jsx)(t.a,{href:"https://github.com/kenz-gelsoft/wxRust",children:"oh hey wxWdidgets again!"}),"), but\nthose also have their own issues with distribution, styling, etc. With Electron, I can\n",(0,i.jsx)(t.code,{children:"yarn create electron-app my-app"})," and just get going, knowing that packaging/upgrades/etc. are built\nin."]}),"\n",(0,i.jsxs)(t.p,{children:["My question is: given recent innovations with WASM, ",(0,i.jsx)(t.em,{children:"are we Electron yet"}),"?"]}),"\n",(0,i.jsx)(t.p,{children:"No, not really."}),"\n",(0,i.jsxs)(t.p,{children:["Instead, ",(0,i.jsx)(t.strong,{children:"what would it take to get to a point where we can skip Javascript in Electron apps?"})]}),"\n",(0,i.jsx)(t.p,{children:"Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There\nmay already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to\ntry and organize what I did manage to discover."}),"\n",(0,i.jsxs)(t.p,{children:["I should also mention that the content and things I'm talking about here are not intended to be\nprescriptive, but more \"if someone else is interested, what do we already know doesn't work?\" ",(0,i.jsx)(t.em,{children:"I\nexpect everything in this post to be obsolete within two months."})," Even over the course of writing\nthis, ",(0,i.jsx)(t.a,{href:"https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/",children:"a separate blog post"})," had\nto be modified because ",(0,i.jsx)(t.a,{href:"https://github.com/WebAssembly/binaryen/pull/1642",children:"upstream changes"})," broke a\n",(0,i.jsx)(t.a,{href:"https://github.com/rustwasm/wasm-bindgen/pull/787",children:"Rust tool"})," the post tried to use. The post\nultimately\n",(0,i.jsx)(t.a,{href:"https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477",children:"got updated"}),", ",(0,i.jsx)(t.strong,{children:"but\nall this happened within the span of a week."})," Things are moving quickly."]}),"\n",(0,i.jsxs)(t.p,{children:["I'll also note that we're going to skip ",(0,i.jsx)(t.a,{href:"http://asmjs.org/",children:"asm.js"})," and ",(0,i.jsx)(t.a,{href:"https://kripken.github.io/emscripten-site/",children:"emscripten"}),". Truth be told, I couldn't get\neither of these to output anything, and so I'm just going to say\n",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Here_be_dragons",children:"here be dragons."})," Everything I'm discussing here\nuses the ",(0,i.jsx)(t.code,{children:"wasm32-unknown-unknown"})," target."]}),"\n",(0,i.jsxs)(t.p,{children:["The code that I ",(0,i.jsx)(t.em,{children:"did"})," get running is available\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust",children:"over here"}),". Feel free to use it as a starting point,\nbut I'm mostly including the link as a reference for the things that were attempted."]}),"\n",(0,i.jsx)(t.h1,{id:"an-example-running-application",children:"An Example Running Application"}),"\n",(0,i.jsxs)(t.p,{children:["So, I did ",(0,i.jsx)(t.em,{children:"technically"})," get a running application:"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Electron app using WASM",src:n(9012).Z+"",width:"800",height:"319"})}),"\n",(0,i.jsx)(t.p,{children:"...which you can also try out if you want:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-sh",children:"git clone https://github.com/speice-io/isomorphic-rust.git\ncd isomorphic_rust/percy\nyarn install && yarn start\n"})}),"\n",(0,i.jsx)(t.p,{children:"...but I wouldn't really call it a \"high quality\" starting point to base future work on. It's mostly\nthere to prove this is possible in the first place. And that's something to be proud of! There's a\nhuge amount of engineering that went into showing a window with the text \"It's alive!\"."}),"\n",(0,i.jsx)(t.p,{children:"There's also a lot of usability issues that prevent me from recommending anyone try Electron and\nWASM apps at the moment, and I think that's the more important thing to discuss."}),"\n",(0,i.jsx)(t.h1,{id:"issue-the-first-complicated-toolchains",children:"Issue the First: Complicated Toolchains"}),"\n",(0,i.jsxs)(t.p,{children:["I quickly established that ",(0,i.jsx)(t.a,{href:"https://github.com/rustwasm/wasm-bindgen",children:"wasm-bindgen"}),' was necessary to "link" my Rust code to Javascript. At\nthat point you\'ve got an Electron app that starts an HTML page which ultimately fetches your WASM\nblob. To keep things simple, the goal was to package everything using ',(0,i.jsx)(t.a,{href:"https://webpack.js.org/",children:"webpack"})," so that I could just\nload a ",(0,i.jsx)(t.code,{children:"bundle.js"})," file on the page. That decision was to be the last thing that kinda worked in\nthis process."]}),"\n",(0,i.jsxs)(t.p,{children:["The first issue\n",(0,i.jsx)(t.a,{href:"https://www.reddit.com/r/rust/comments/98lpun/unable_to_load_wasm_for_electron_application/",children:"I ran into"}),"\nwhile attempting to bundle everything via ",(0,i.jsx)(t.code,{children:"webpack"})," is a detail in the WASM spec:"]}),"\n",(0,i.jsxs)(t.blockquote,{children:["\n",(0,i.jsxs)(t.p,{children:["This function accepts a Response object, or a promise for one, and ... ",(0,i.jsxs)(t.strong,{children:["[if > it] does not match\nthe ",(0,i.jsx)(t.code,{children:"application/wasm"})," MIME type"]}),", the returned promise will be rejected with a TypeError;"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.a,{href:"https://webassembly.org/docs/web/#additional-web-embedding-api",children:"WebAssembly - Additional Web Embedding API"})}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the\nweb this isn't a huge issue, as the server can set MIME types when delivering the blob. With\nElectron, you're resolving things with a ",(0,i.jsx)(t.code,{children:"file://"})," URL and thus can't control the MIME type:"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"TypeError: Incorrect response MIME type. Expected 'application/wasm'.",src:n(363).Z+"",width:"795",height:"301"})}),"\n",(0,i.jsx)(t.p,{children:"There are a couple of solutions depending on how far into the deep end you care to venture:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Embed a static file server in your Electron application"}),"\n",(0,i.jsxs)(t.li,{children:["Use a ",(0,i.jsx)(t.a,{href:"https://electronjs.org/docs/api/protocol",children:"custom protocol"})," and custom protocol handler"]}),"\n",(0,i.jsx)(t.li,{children:"Host your WASM blob on a website that you resolve at runtime"}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["But all these are pretty bad solutions and defeat the purpose of using WASM in the first place.\nInstead, my workaround was to\n",(0,i.jsxs)(t.a,{href:"https://github.com/webpack/webpack/issues/7918",children:["open a PR with ",(0,i.jsx)(t.code,{children:"webpack"})]})," and use regex to remove\ncalls to ",(0,i.jsx)(t.code,{children:"instantiateStreaming"})," in the\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/blob/master/percy/build.sh#L21-L25",children:"build script"}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-sh",children:'cargo +nightly build --target=wasm32-unknown-unknown && \\\n wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\\n # Have to use --mode=development so we can patch out the call to instantiateStreaming\n "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \\\n sed -i \'s/.*instantiateStreaming.*//g\' "$APP_DIR/bundle.js"\n'})}),"\n",(0,i.jsxs)(t.p,{children:["Once that lands, the\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/blob/master/percy_patched_webpack/build.sh#L24-L27",children:"build process"}),"\nbecomes much simpler:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-sh",children:'\ncargo +nightly build --target=wasm32-unknown-unknown && \\\n wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\\n "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js"\n'})}),"\n",(0,i.jsxs)(t.p,{children:["But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via\n",(0,i.jsx)(t.code,{children:"wasm-bindgen"})," and ",(0,i.jsx)(t.code,{children:"webpack"}),"), we still have to make an Electron app. For this purpose I used a\nstarter app from ",(0,i.jsx)(t.a,{href:"https://electronforge.io/",children:"Electron Forge"}),", and then a\n",(0,i.jsxs)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8",children:[(0,i.jsx)(t.code,{children:"prestart"})," script"]}),"\nto actually handle starting the application."]}),"\n",(0,i.jsxs)(t.p,{children:["The\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8",children:"final toolchain"}),"\nlooks something like this:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"yarn start"})," triggers the ",(0,i.jsx)(t.code,{children:"prestart"})," script"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"prestart"})," checks for missing tools (",(0,i.jsx)(t.code,{children:"wasm-bindgen-cli"}),", etc.) and then:","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Uses ",(0,i.jsx)(t.code,{children:"cargo"})," to compile the Rust code into WASM"]}),"\n",(0,i.jsxs)(t.li,{children:["Uses ",(0,i.jsx)(t.code,{children:"wasm-bindgen"})," to link the WASM blob into a Javascript file with exported symbols"]}),"\n",(0,i.jsxs)(t.li,{children:["Uses ",(0,i.jsx)(t.code,{children:"webpack"})," to bundle the page start script with the Javascript we just generated","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Uses ",(0,i.jsx)(t.code,{children:"babel"})," under the hood to compile the ",(0,i.jsx)(t.code,{children:"wasm-bindgen"})," code down from ES6 into something\nbrowser-compatible"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["The ",(0,i.jsx)(t.code,{children:"start"})," script runs an Electron Forge handler to do some sanity checks"]}),"\n",(0,i.jsx)(t.li,{children:"Electron actually starts"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:'...which is complicated. I think more work needs to be done to either build a high-quality starter\napp that can manage these steps, or another tool that "just handles" the complexity of linking a\ncompiled WASM file into something the Electron browser can run.'}),"\n",(0,i.jsx)(t.h1,{id:"issue-the-second-wasm-tools-in-rust",children:"Issue the Second: WASM tools in Rust"}),"\n",(0,i.jsx)(t.p,{children:"For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only\nbits aren't any better at the moment. I get it, a lot of projects are just starting off, and that\nleads to a fragmented ecosystem. Here's what I can recommend as a starting point:"}),"\n",(0,i.jsxs)(t.p,{children:["Don't check in your ",(0,i.jsx)(t.code,{children:"Cargo.lock"})," files to version control. If there's a disagreement between the\nversion of ",(0,i.jsx)(t.code,{children:"wasm-bindgen-cli"})," you have installed and the ",(0,i.jsx)(t.code,{children:"wasm-bindgen"})," you're compiling with in\n",(0,i.jsx)(t.code,{children:"Cargo.lock"}),", you get a nasty error:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"it looks like the Rust project used to create this wasm file was linked against\na different version of wasm-bindgen than this binary:\n\nrust wasm file: 0.2.21\n this binary: 0.2.17\n\nCurrently the bindgen format is unstable enough that these two version must\nexactly match, so it's required that these two version are kept in sync by\neither updating the wasm-bindgen dependency or this binary.\n"})}),"\n",(0,i.jsxs)(t.p,{children:["Not that I ever managed to run into this myself (",(0,i.jsx)(t.em,{children:"coughs nervously"}),")."]}),"\n",(0,i.jsxs)(t.p,{children:['There are two projects attempting to be "application frameworks": ',(0,i.jsx)(t.a,{href:"https://chinedufn.github.io/percy/",children:"percy"})," and ",(0,i.jsx)(t.a,{href:"https://github.com/DenisKolodin/yew",children:"yew"}),". Between those,\nI managed to get ",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/tree/master/percy",children:"two"}),"\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/tree/master/percy_patched_webpack",children:"examples"})," running\nusing ",(0,i.jsx)(t.code,{children:"percy"}),", but was unable to get an\n",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/tree/master/yew",children:"example"})," running with ",(0,i.jsx)(t.code,{children:"yew"}),' because\nof issues with "missing modules" during the ',(0,i.jsx)(t.code,{children:"webpack"})," step:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-sh",children:"ERROR in ./dist/electron_yew_wasm_bg.wasm\nModule not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist'\n @ ./dist/electron_yew_wasm_bg.wasm\n @ ./dist/electron_yew_wasm.js\n @ ./dist/app.js\n @ ./dist/app_loader.js\n"})}),"\n",(0,i.jsxs)(t.p,{children:["If you want to work with the browser APIs directly, your choices are ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/percy-webapis",children:"percy-webapis"})," or ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/stdweb",children:"stdweb"})," (or\neventually ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/web-sys",children:"web-sys"}),"). See above for my ",(0,i.jsx)(t.code,{children:"percy"})," examples, but when I tried\n",(0,i.jsxs)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/tree/master/stdweb",children:["an example with ",(0,i.jsx)(t.code,{children:"stdweb"})]}),", I was\nunable to get it running:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-sh",children:"ERROR in ./dist/stdweb_electron_bg.wasm\nModule not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist'\n @ ./dist/stdweb_electron_bg.wasm\n @ ./dist/stdweb_electron.js\n @ ./dist/app_loader.js\n"})}),"\n",(0,i.jsxs)(t.p,{children:["At this point I'm pretty convinced that ",(0,i.jsx)(t.code,{children:"stdweb"})," is causing issues for ",(0,i.jsx)(t.code,{children:"yew"})," as well, but can't\nprove it."]}),"\n",(0,i.jsxs)(t.p,{children:["I did also get a ",(0,i.jsx)(t.a,{href:"https://github.com/speice-io/isomorphic-rust/tree/master/minimal",children:"minimal example"}),"\nrunning that doesn't depend on any tools besides ",(0,i.jsx)(t.code,{children:"wasm-bindgen"}),'. However, it requires manually\nwriting "',(0,i.jsx)(t.code,{children:"extern C"}),'" blocks for everything you need from the browser. Es no bueno.']}),"\n",(0,i.jsxs)(t.p,{children:["Finally, from a tools and platform view, there are two up-and-coming packages that should be\nmentioned: ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/js-sys",children:"js-sys"})," and ",(0,i.jsx)(t.a,{href:"https://crates.io/crates/web-sys",children:"web-sys"}),". Their purpose is to be fundamental building blocks that exposes\nthe browser's APIs to Rust. If you're interested in building an app framework from scratch, these\nshould give you the most flexibility. I didn't touch either in my research, though I expect them to\nbe essential long-term."]}),"\n",(0,i.jsx)(t.p,{children:"So there's a lot in play from the Rust side of things, and it's just going to take some time to\nfigure out what works and what doesn't."}),"\n",(0,i.jsx)(t.h1,{id:"issue-the-third-known-unknowns",children:"Issue the Third: Known Unknowns"}),"\n",(0,i.jsxs)(t.p,{children:["Alright, so after I managed to get an application started, I stopped there. It was a good deal of\neffort to chain together even a proof of concept, and at this point I'd rather learn ",(0,i.jsx)(t.a,{href:"https://www.typescriptlang.org/",children:"Typescript"}),"\nthan keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know..."]}),"\n",(0,i.jsx)(t.p,{children:"The important point I want to make is that there's a lot unknown about how any of this holds up\noutside proofs of concept. Things I didn't attempt:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Testing"}),"\n",(0,i.jsx)(t.li,{children:"Packaging"}),"\n",(0,i.jsx)(t.li,{children:"Updates"}),"\n",(0,i.jsx)(t.li,{children:"Literally anything related to why I wanted to use Electron in the first place"}),"\n"]}),"\n",(0,i.jsx)(t.h1,{id:"what-it-would-take",children:"What it Would Take"}),"\n",(0,i.jsx)(t.p,{children:"Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and\nWASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an\napplication in production a couple months from now. But at the moment, I'm personally going to stay\naway."}),"\n",(0,i.jsx)(t.p,{children:"Let's finish with a wishlist then - here are the things that I think need to happen before\nElectron/WASM/Rust can become a thing:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet\n(",(0,i.jsx)(t.a,{href:"https://github.com/webpack/webpack/pull/7983",children:"#7983"}),")"]}),"\n",(0,i.jsxs)(t.li,{children:["Browser API libraries (",(0,i.jsx)(t.code,{children:"web-sys"})," and ",(0,i.jsx)(t.code,{children:"stdweb"}),") need to make sure they can support running in\nElectron (see module error above)"]}),"\n",(0,i.jsxs)(t.li,{children:["Projects need to stabilize. There's talk of ",(0,i.jsx)(t.code,{children:"stdweb"})," being turned into a Rust API\n",(0,i.jsx)(t.a,{href:"https://github.com/rustwasm/team/issues/226#issuecomment-418475778",children:"on top of web-sys"}),", and percy\n",(0,i.jsx)(t.a,{href:"https://github.com/chinedufn/percy/issues/24",children:"moving to web-sys"}),", both of which are big changes"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"wasm-bindgen"}),' is great, but still in the "move fast and break things" phase']}),"\n",(0,i.jsxs)(t.li,{children:['A good "boilerplate" app would dramatically simplify the start-up costs;\n',(0,i.jsx)(t.a,{href:"https://github.com/chentsulin/electron-react-boilerplate",children:"electron-react-boilerplate"})," comes to\nmind as a good project to imitate"]}),"\n",(0,i.jsx)(t.li,{children:"More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm\ndoing"}),"\n"]})]})}function d(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},9012:function(e,t,n){n.d(t,{Z:function(){return s}});let s=n.p+"assets/images/electron-percy-wasm-9ccb2be15a9bed6da44486afc266bad5.png"},363:function(e,t,n){n.d(t,{Z:function(){return s}});let s=n.p+"assets/images/incorrect-MIME-type-a977835e8dcbfdb20fdda3c67ee4f76c.png"},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return r}});var s=n(7294);let i={},o=s.createContext(i);function r(e){let t=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:t},e.children)}},8595:function(e){e.exports=JSON.parse('{"permalink":"/2018/09/isomorphic-apps","source":"@site/blog/2018-09-15-isomorphic-apps/index.mdx","title":"Isomorphic desktop apps with Rust","description":"I both despise Javascript and am stunned by its success doing some really cool things. It\'s","date":"2018-09-15T12:00:00.000Z","tags":[],"readingTime":9.905,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/isomorphic-apps","title":"Isomorphic desktop apps with Rust","date":"2018-09-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731188450000,"prevItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"},"nextItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"}}')}}]); \ No newline at end of file diff --git a/assets/js/3f9ae9f6.2800ab67.js b/assets/js/3f9ae9f6.2800ab67.js new file mode 100644 index 0000000..77b7144 --- /dev/null +++ b/assets/js/3f9ae9f6.2800ab67.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7109"],{9948:function(e){e.exports=JSON.parse('{"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null,"count":33}]}')}}]); \ No newline at end of file diff --git a/assets/js/4294.a7567dcb.js b/assets/js/4294.a7567dcb.js new file mode 100644 index 0000000..0bd4f0c --- /dev/null +++ b/assets/js/4294.a7567dcb.js @@ -0,0 +1,101 @@ +(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4294"],{1639:function(e,t,n){"use strict";e.exports=n(9281)},7114:function(e,t,n){"use strict";var i=n(5670),r={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none",opacity:"1"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:"0"},defaultClasses:{root:"algolia-autocomplete",prefix:"aa",noPrefix:!1,dropdownMenu:"dropdown-menu",input:"input",hint:"hint",suggestions:"suggestions",suggestion:"suggestion",cursor:"cursor",dataset:"dataset",empty:"empty"},appendTo:{wrapper:{position:"absolute",zIndex:"100",display:"none"},input:{},inputWithNoHint:{},dropdown:{display:"block"}}};i.isMsie()&&i.mixin(r.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),i.isMsie()&&7>=i.isMsie()&&i.mixin(r.input,{marginTop:"-1px"}),e.exports=r},3312:function(e,t,n){"use strict";var i="aaDataset",r="aaValue",s="aaDatum",o=n(5670),a=n(3855),u=n(6619),c=n(7114),l=n(6823);function h(e){(e=e||{}).templates=e.templates||{},!e.source&&o.error("missing source"),e.name&&!function(e){return/^[_a-zA-Z0-9-]+$/.test(e)}(e.name)&&o.error("invalid dataset name: "+e.name),this.query=null,this._isEmpty=!0,this.highlight=!!e.highlight,this.name=void 0===e.name||null===e.name?o.getUniqueId():e.name,this.source=e.source,this.displayFn=function(e){return e=e||"value",o.isFunction(e)?e:function(t){return t[e]}}(e.display||e.displayKey),this.debounce=e.debounce,this.cache=!1!==e.cache,this.templates=function(e,t){return{empty:e.empty&&o.templatify(e.empty),header:e.header&&o.templatify(e.header),footer:e.footer&&o.templatify(e.footer),suggestion:e.suggestion||function(e){return"<p>"+t(e)+"</p>"}}}(e.templates,this.displayFn),this.css=o.mixin({},c,e.appendTo?c.appendTo:{}),this.cssClasses=e.cssClasses=o.mixin({},c.defaultClasses,e.cssClasses||{}),this.cssClasses.prefix=e.cssClasses.formattedPrefix||o.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix);var t=o.className(this.cssClasses.prefix,this.cssClasses.dataset);this.$el=e.$menu&&e.$menu.find(t+"-"+this.name).length>0?a.element(e.$menu.find(t+"-"+this.name)[0]):a.element(u.dataset.replace("%CLASS%",this.name).replace("%PREFIX%",this.cssClasses.prefix).replace("%DATASET%",this.cssClasses.dataset)),this.$menu=e.$menu,this.clearCachedSuggestions()}h.extractDatasetName=function(e){return a.element(e).data(i)},h.extractValue=function(e){return a.element(e).data(r)},h.extractDatum=function(e){var t=a.element(e).data(s);return"string"==typeof t&&(t=JSON.parse(t)),t},o.mixin(h.prototype,l,{_render:function(e,t){if(!!this.$el){var n,c=this,l=[].slice.call(arguments,2);if(this.$el.empty(),n=t&&t.length,this._isEmpty=!n,!n&&this.templates.empty)this.$el.html((function(){var t=[].slice.call(arguments,0);return t=[{query:e,isEmpty:!0}].concat(t),c.templates.empty.apply(this,t)}).apply(this,l)).prepend(c.templates.header?h.apply(this,l):null).append(c.templates.footer?p.apply(this,l):null);else if(n)this.$el.html((function(){var e,n,l=[].slice.call(arguments,0),h=this,p=u.suggestions.replace("%PREFIX%",this.cssClasses.prefix).replace("%SUGGESTIONS%",this.cssClasses.suggestions);return e=a.element(p).css(this.css.suggestions),n=o.map(t,function(e){var t,n=u.suggestion.replace("%PREFIX%",h.cssClasses.prefix).replace("%SUGGESTION%",h.cssClasses.suggestion);return(t=a.element(n).attr({role:"option",id:["option",Math.floor(1e8*Math.random())].join("-")}).append(c.templates.suggestion.apply(this,[e].concat(l)))).data(i,c.name),t.data(r,c.displayFn(e)||void 0),t.data(s,JSON.stringify(e)),t.children().each(function(){a.element(this).css(h.css.suggestionChild)}),t}),e.append.apply(e,n),e}).apply(this,l)).prepend(c.templates.header?h.apply(this,l):null).append(c.templates.footer?p.apply(this,l):null);else if(t&&!Array.isArray(t))throw TypeError("suggestions must be an array");this.$menu&&this.$menu.addClass(this.cssClasses.prefix+(n?"with":"without")+"-"+this.name).removeClass(this.cssClasses.prefix+(n?"without":"with")+"-"+this.name),this.trigger("rendered",e)}function h(){var t=[].slice.call(arguments,0);return t=[{query:e,isEmpty:!n}].concat(t),c.templates.header.apply(this,t)}function p(){var t=[].slice.call(arguments,0);return t=[{query:e,isEmpty:!n}].concat(t),c.templates.footer.apply(this,t)}},getRoot:function(){return this.$el},update:function(e){function t(t){if(!this.canceled&&e===this.query){var n=[].slice.call(arguments,1);this.cacheSuggestions(e,t,n),this._render.apply(this,[e,t].concat(n))}}if(this.query=e,this.canceled=!1,this.shouldFetchFromCache(e))t.apply(this,[this.cachedSuggestions].concat(this.cachedRenderExtraArgs));else{var n=this,i=function(){!n.canceled&&n.source(e,t.bind(n))};this.debounce?(clearTimeout(this.debounceTimeout),this.debounceTimeout=setTimeout(function(){n.debounceTimeout=null,i()},this.debounce)):i()}},cacheSuggestions:function(e,t,n){this.cachedQuery=e,this.cachedSuggestions=t,this.cachedRenderExtraArgs=n},shouldFetchFromCache:function(e){return this.cache&&this.cachedQuery===e&&this.cachedSuggestions&&this.cachedSuggestions.length},clearCachedSuggestions:function(){delete this.cachedQuery,delete this.cachedSuggestions,delete this.cachedRenderExtraArgs},cancel:function(){this.canceled=!0},clear:function(){this.$el&&(this.cancel(),this.$el.empty(),this.trigger("rendered",""))},isEmpty:function(){return this._isEmpty},destroy:function(){this.clearCachedSuggestions(),this.$el=null}});e.exports=h},5445:function(e,t,n){"use strict";var i=n(5670),r=n(3855),s=n(6823),o=n(3312),a=n(7114);function u(e){var t,n,s,o=this;!(e=e||{}).menu&&i.error("menu is required"),!i.isArray(e.datasets)&&!i.isObject(e.datasets)&&i.error("1 or more datasets required"),!e.datasets&&i.error("datasets is required"),this.isOpen=!1,this.isEmpty=!0,this.minLength=e.minLength||0,this.templates={},this.appendTo=e.appendTo||!1,this.css=i.mixin({},a,e.appendTo?a.appendTo:{}),this.cssClasses=e.cssClasses=i.mixin({},a.defaultClasses,e.cssClasses||{}),this.cssClasses.prefix=e.cssClasses.formattedPrefix||i.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix),t=i.bind(this._onSuggestionClick,this),n=i.bind(this._onSuggestionMouseEnter,this),s=i.bind(this._onSuggestionMouseLeave,this);var c=i.className(this.cssClasses.prefix,this.cssClasses.suggestion);this.$menu=r.element(e.menu).on("mouseenter.aa",c,n).on("mouseleave.aa",c,s).on("click.aa",c,t),this.$container=e.appendTo?e.wrapper:this.$menu,e.templates&&e.templates.header&&(this.templates.header=i.templatify(e.templates.header),this.$menu.prepend(this.templates.header())),e.templates&&e.templates.empty&&(this.templates.empty=i.templatify(e.templates.empty),this.$empty=r.element('<div class="'+i.className(this.cssClasses.prefix,this.cssClasses.empty,!0)+'"></div>'),this.$menu.append(this.$empty),this.$empty.hide()),this.datasets=i.map(e.datasets,function(t){return function(e,t,n){return new u.Dataset(i.mixin({$menu:e,cssClasses:n},t))}(o.$menu,t,e.cssClasses)}),i.each(this.datasets,function(e){var t=e.getRoot();t&&0===t.parent().length&&o.$menu.append(t),e.onSync("rendered",o._onRendered,o)}),e.templates&&e.templates.footer&&(this.templates.footer=i.templatify(e.templates.footer),this.$menu.append(this.templates.footer()));var l=this;r.element(window).resize(function(){l._redraw()})}i.mixin(u.prototype,s,{_onSuggestionClick:function(e){this.trigger("suggestionClicked",r.element(e.currentTarget))},_onSuggestionMouseEnter:function(e){var t=r.element(e.currentTarget);if(!t.hasClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0))){this._removeCursor();var n=this;setTimeout(function(){n._setCursor(t,!1)},0)}},_onSuggestionMouseLeave:function(e){if(!e.relatedTarget||!(r.element(e.relatedTarget).closest("."+i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).length>0))this._removeCursor(),this.trigger("cursorRemoved")},_onRendered:function(e,t){if(this.isEmpty=i.every(this.datasets,function(e){return e.isEmpty()}),this.isEmpty){if(t.length>=this.minLength&&this.trigger("empty"),this.$empty){if(t.length<this.minLength)this._hide();else{var n=this.templates.empty({query:this.datasets[0]&&this.datasets[0].query});this.$empty.html(n),this.$empty.show(),this._show()}}else i.any(this.datasets,function(e){return e.templates&&e.templates.empty})?t.length<this.minLength?this._hide():this._show():this._hide()}else this.isOpen&&(this.$empty&&(this.$empty.empty(),this.$empty.hide()),t.length>=this.minLength?this._show():this._hide());this.trigger("datasetRendered")},_hide:function(){this.$container.hide()},_show:function(){this.$container.css("display","block"),this._redraw(),this.trigger("shown")},_redraw:function(){this.isOpen&&this.appendTo&&this.trigger("redrawn")},_getSuggestions:function(){return this.$menu.find(i.className(this.cssClasses.prefix,this.cssClasses.suggestion))},_getCursor:function(){return this.$menu.find(i.className(this.cssClasses.prefix,this.cssClasses.cursor)).first()},_setCursor:function(e,t){e.first().addClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).attr("aria-selected","true"),this.trigger("cursorMoved",t)},_removeCursor:function(){this._getCursor().removeClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).removeAttr("aria-selected")},_moveCursor:function(e){var t,n,i,r;if(!!this.isOpen){if(n=this._getCursor(),t=this._getSuggestions(),this._removeCursor(),-1==(i=((i=t.index(n)+e)+1)%(t.length+1)-1)){this.trigger("cursorRemoved");return}i<-1&&(i=t.length-1);this._setCursor(r=t.eq(i),!0),this._ensureVisible(r)}},_ensureVisible:function(e){var t,n,i,r;n=(t=e.position().top)+e.height()+parseInt(e.css("margin-top"),10)+parseInt(e.css("margin-bottom"),10),i=this.$menu.scrollTop(),r=this.$menu.height()+parseInt(this.$menu.css("padding-top"),10)+parseInt(this.$menu.css("padding-bottom"),10),t<0?this.$menu.scrollTop(i+t):r<n&&this.$menu.scrollTop(i+(n-r))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){!this.isOpen&&(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(e){this.$menu.css("ltr"===e?this.css.ltr:this.css.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(e){var t=null;return e.length&&(t={raw:o.extractDatum(e),value:o.extractValue(e),datasetName:o.extractDatasetName(e)}),t},getCurrentCursor:function(){return this._getCursor().first()},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},cursorTopSuggestion:function(){this._setCursor(this._getSuggestions().first(),!1)},update:function(e){i.each(this.datasets,function(t){t.update(e)})},empty:function(){i.each(this.datasets,function(e){e.clear()}),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){this.$menu.off(".aa"),this.$menu=null,i.each(this.datasets,function(e){e.destroy()})}}),u.Dataset=o;e.exports=u},7368:function(e,t,n){"use strict";var i=n(5670),r=n(3855);function s(e){(!e||!e.el)&&i.error("EventBus initialized without el"),this.$el=r.element(e.el)}i.mixin(s.prototype,{trigger:function(e,t,n,r){var s=i.Event("autocomplete:"+e);return this.$el.trigger(s,[t,n,r]),s}}),e.exports=s},6823:function(e,t,n){"use strict";var i=n(624),r=/\s+/;function s(e,t,n,i){var s;if(!n)return this;for(t=t.split(r),n=i?function(e,t){return e.bind?e.bind(t):function(){e.apply(t,[].slice.call(arguments,0))}}(n,i):n,this._callbacks=this._callbacks||{};s=t.shift();)this._callbacks[s]=this._callbacks[s]||{sync:[],async:[]},this._callbacks[s][e].push(n);return this}e.exports={onSync:function(e,t,n){return s.call(this,"sync",e,t,n)},onAsync:function(e,t,n){return s.call(this,"async",e,t,n)},off:function(e){var t;if(!this._callbacks)return this;for(e=e.split(r);t=e.shift();)delete this._callbacks[t];return this},trigger:function(e){var t,n,s,a,u;if(!this._callbacks)return this;for(e=e.split(r),s=[].slice.call(arguments,1);(t=e.shift())&&(n=this._callbacks[t]);)a=o(n.sync,this,[t].concat(s)),u=o(n.async,this,[t].concat(s)),a()&&i(u);return this}};function o(e,t,n){return function(){for(var i,r=0,s=e.length;!i&&r<s;r+=1)i=!1===e[r].apply(t,n);return!i}}},6619:function(e){"use strict";e.exports={wrapper:'<span class="%ROOT%"></span>',dropdown:'<span class="%PREFIX%%DROPDOWN_MENU%"></span>',dataset:'<div class="%PREFIX%%DATASET%-%CLASS%"></div>',suggestions:'<span class="%PREFIX%%SUGGESTIONS%"></span>',suggestion:'<div class="%PREFIX%%SUGGESTION%"></div>'}},1286:function(e,t,n){"use strict";i={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"};var i,r=n(5670),s=n(3855),o=n(6823);function a(e){var t,n,o,a,u=this;!(e=e||{}).input&&r.error("input is missing"),t=r.bind(this._onBlur,this),n=r.bind(this._onFocus,this),o=r.bind(this._onKeydown,this),a=r.bind(this._onInput,this),this.$hint=s.element(e.hint),this.$input=s.element(e.input).on("blur.aa",t).on("focus.aa",n).on("keydown.aa",o),0===this.$hint.length&&(this.setHint=this.getHint=this.clearHint=this.clearHintIfInvalid=r.noop),r.isMsie()?this.$input.on("keydown.aa keypress.aa cut.aa paste.aa",function(e){if(!i[e.which||e.keyCode])r.defer(r.bind(u._onInput,u,e))}):this.$input.on("input.aa",a),this.query=this.$input.val(),this.$overflowHelper=function(e){return s.element('<pre aria-hidden="true"></pre>').css({position:"absolute",visibility:"hidden",whiteSpace:"pre",fontFamily:e.css("font-family"),fontSize:e.css("font-size"),fontStyle:e.css("font-style"),fontVariant:e.css("font-variant"),fontWeight:e.css("font-weight"),wordSpacing:e.css("word-spacing"),letterSpacing:e.css("letter-spacing"),textIndent:e.css("text-indent"),textRendering:e.css("text-rendering"),textTransform:e.css("text-transform")}).insertAfter(e)}(this.$input)}a.normalizeQuery=function(e){return(e||"").replace(/^\s*/g,"").replace(/\s{2,}/g," ")},r.mixin(a.prototype,o,{_onBlur:function(){this.resetInputValue(),this.$input.removeAttr("aria-activedescendant"),this.trigger("blurred")},_onFocus:function(){this.trigger("focused")},_onKeydown:function(e){var t=i[e.which||e.keyCode];this._managePreventDefault(t,e),t&&this._shouldTrigger(t,e)&&this.trigger(t+"Keyed",e)},_onInput:function(){this._checkInputValue()},_managePreventDefault:function(e,t){var n,i,r;switch(e){case"tab":i=this.getHint(),r=this.getInputValue(),n=i&&i!==r&&!u(t);break;case"up":case"down":n=!u(t);break;default:n=!1}n&&t.preventDefault()},_shouldTrigger:function(e,t){var n;if("tab"===e)n=!u(t);else n=!0;return n},_checkInputValue:function(){var e,t,n;n=!!(t=function(e,t){return a.normalizeQuery(e)===a.normalizeQuery(t)}(e=this.getInputValue(),this.query))&&!!this.query&&this.query.length!==e.length,this.query=e,t?n&&this.trigger("whitespaceChanged",this.query):this.trigger("queryChanged",this.query)},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(e){this.query=e},getInputValue:function(){return this.$input.val()},setInputValue:function(e,t){void 0===e&&(e=this.query),this.$input.val(e),t?this.clearHint():this._checkInputValue()},expand:function(){this.$input.attr("aria-expanded","true")},collapse:function(){this.$input.attr("aria-expanded","false")},setActiveDescendant:function(e){this.$input.attr("aria-activedescendant",e)},removeActiveDescendant:function(){this.$input.removeAttr("aria-activedescendant")},resetInputValue:function(){this.setInputValue(this.query,!0)},getHint:function(){return this.$hint.val()},setHint:function(e){this.$hint.val(e)},clearHint:function(){this.setHint("")},clearHintIfInvalid:function(){var e,t,n;e=this.getInputValue(),n=e!==(t=this.getHint())&&0===t.indexOf(e),!(""!==e&&n&&!this.hasOverflow())&&this.clearHint()},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},hasOverflow:function(){var e=this.$input.width()-2;return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>=e},isCursorAtEnd:function(){var e,t,n;return(e=this.$input.val().length,t=this.$input[0].selectionStart,r.isNumber(t))?t===e:!document.selection||((n=document.selection.createRange()).moveStart("character",-e),e===n.text.length)},destroy:function(){this.$hint.off(".aa"),this.$input.off(".aa"),this.$hint=this.$input=this.$overflowHelper=null}});function u(e){return e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}e.exports=a},4520:function(e,t,n){"use strict";var i="aaAttrs",r=n(5670),s=n(3855),o=n(7368),a=n(1286),u=n(5445),c=n(6619),l=n(7114);function h(e){if(!(e=e||{}).input&&r.error("missing input"),this.isActivated=!1,this.debug=!!e.debug,this.autoselect=!!e.autoselect,this.autoselectOnBlur=!!e.autoselectOnBlur,this.openOnFocus=!!e.openOnFocus,this.minLength=r.isNumber(e.minLength)?e.minLength:1,this.autoWidth=void 0===e.autoWidth||!!e.autoWidth,this.clearOnSelected=!!e.clearOnSelected,this.tabAutocomplete=void 0===e.tabAutocomplete||!!e.tabAutocomplete,e.hint=!!e.hint,e.hint&&e.appendTo)throw Error("[autocomplete.js] hint and appendTo options can't be used at the same time");this.css=e.css=r.mixin({},l,e.appendTo?l.appendTo:{}),this.cssClasses=e.cssClasses=r.mixin({},l.defaultClasses,e.cssClasses||{}),this.cssClasses.prefix=e.cssClasses.formattedPrefix=r.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix),this.listboxId=e.listboxId=[this.cssClasses.root,"listbox",r.getUniqueId()].join("-");var t,n,a=function(e){t=s.element(e.input),n=s.element(c.wrapper.replace("%ROOT%",e.cssClasses.root)).css(e.css.wrapper),!e.appendTo&&"block"===t.css("display")&&"table"===t.parent().css("display")&&n.css("display","table-cell");var t,n,o,a,u=c.dropdown.replace("%PREFIX%",e.cssClasses.prefix).replace("%DROPDOWN_MENU%",e.cssClasses.dropdownMenu);o=s.element(u).css(e.css.dropdown).attr({role:"listbox",id:e.listboxId}),e.templates&&e.templates.dropdownMenu&&o.html(r.templatify(e.templates.dropdownMenu)()),(a=t.clone().css(e.css.hint).css(function(e){return{backgroundAttachment:e.css("background-attachment"),backgroundClip:e.css("background-clip"),backgroundColor:e.css("background-color"),backgroundImage:e.css("background-image"),backgroundOrigin:e.css("background-origin"),backgroundPosition:e.css("background-position"),backgroundRepeat:e.css("background-repeat"),backgroundSize:e.css("background-size")}}(t))).val("").addClass(r.className(e.cssClasses.prefix,e.cssClasses.hint,!0)).removeAttr("id name placeholder required").prop("readonly",!0).attr({"aria-hidden":"true",autocomplete:"off",spellcheck:"false",tabindex:-1}),a.removeData&&a.removeData(),t.data(i,{"aria-autocomplete":t.attr("aria-autocomplete"),"aria-expanded":t.attr("aria-expanded"),"aria-owns":t.attr("aria-owns"),autocomplete:t.attr("autocomplete"),dir:t.attr("dir"),role:t.attr("role"),spellcheck:t.attr("spellcheck"),style:t.attr("style"),type:t.attr("type")}),t.addClass(r.className(e.cssClasses.prefix,e.cssClasses.input,!0)).attr({autocomplete:"off",spellcheck:!1,role:"combobox","aria-autocomplete":e.datasets&&e.datasets[0]&&e.datasets[0].displayKey?"both":"list","aria-expanded":"false","aria-label":e.ariaLabel,"aria-owns":e.listboxId}).css(e.hint?e.css.input:e.css.inputWithNoHint);try{!t.attr("dir")&&t.attr("dir","auto")}catch(e){}return(n=e.appendTo?n.appendTo(s.element(e.appendTo).eq(0)).eq(0):t.wrap(n).parent()).prepend(e.hint?a:null).append(o),{wrapper:n,input:t,hint:a,menu:o}}(e);this.$node=a.wrapper;var u=this.$input=a.input;t=a.menu,n=a.hint,e.dropdownMenuContainer&&s.element(e.dropdownMenuContainer).css("position","relative").append(t.css("top","0")),u.on("blur.aa",function(e){var n=document.activeElement;r.isMsie()&&(t[0]===n||t[0].contains(n))&&(e.preventDefault(),e.stopImmediatePropagation(),r.defer(function(){u.focus()}))}),t.on("mousedown.aa",function(e){e.preventDefault()}),this.eventBus=e.eventBus||new o({el:u}),this.dropdown=new h.Dropdown({appendTo:e.appendTo,wrapper:this.$node,menu:t,datasets:e.datasets,templates:e.templates,cssClasses:e.cssClasses,minLength:this.minLength}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onSync("shown",this._onShown,this).onSync("empty",this._onEmpty,this).onSync("redrawn",this._onRedrawn,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new h.Input({input:u,hint:n}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._bindKeyboardShortcuts(e),this._setLanguageDirection()}r.mixin(h.prototype,{_bindKeyboardShortcuts:function(e){if(!!e.keyboardShortcuts){var t=this.$input,n=[];r.each(e.keyboardShortcuts,function(e){"string"==typeof e&&(e=e.toUpperCase().charCodeAt(0)),n.push(e)}),s.element(document).keydown(function(e){var i=e.target||e.srcElement,r=i.tagName;if(i.isContentEditable||"INPUT"===r||"SELECT"===r||"TEXTAREA"===r)return;var s=e.which||e.keyCode;if(-1!==n.indexOf(s))t.focus(),e.stopPropagation(),e.preventDefault()})}},_onSuggestionClicked:function(e,t){var n;(n=this.dropdown.getDatumForSuggestion(t))&&this._select(n,{selectionMethod:"click"})},_onCursorMoved:function(e,t){var n=this.dropdown.getDatumForCursor(),i=this.dropdown.getCurrentCursor().attr("id");this.input.setActiveDescendant(i),n&&(t&&this.input.setInputValue(n.value,!0),this.eventBus.trigger("cursorchanged",n.raw,n.datasetName))},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint(),this.eventBus.trigger("cursorremoved")},_onDatasetRendered:function(){this._updateHint(),this.eventBus.trigger("updated")},_onOpened:function(){this._updateHint(),this.input.expand(),this.eventBus.trigger("opened")},_onEmpty:function(){this.eventBus.trigger("empty")},_onRedrawn:function(){this.$node.css("top","0px"),this.$node.css("left","0px");var e=this.$input[0].getBoundingClientRect();this.autoWidth&&this.$node.css("width",e.width+"px");var t=this.$node[0].getBoundingClientRect(),n=e.bottom-t.top;this.$node.css("top",n+"px");var i=e.left-t.left;this.$node.css("left",i+"px"),this.eventBus.trigger("redrawn")},_onShown:function(){this.eventBus.trigger("shown"),this.autoselect&&this.dropdown.cursorTopSuggestion()},_onClosed:function(){this.input.clearHint(),this.input.removeActiveDescendant(),this.input.collapse(),this.eventBus.trigger("closed")},_onFocused:function(){if(this.isActivated=!0,this.openOnFocus){var e=this.input.getQuery();e.length>=this.minLength?this.dropdown.update(e):this.dropdown.empty(),this.dropdown.open()}},_onBlurred:function(){e=this.dropdown.getDatumForCursor(),t=this.dropdown.getDatumForTopSuggestion();var e,t,n={selectionMethod:"blur"};!this.debug&&(this.autoselectOnBlur&&e?this._select(e,n):this.autoselectOnBlur&&t?this._select(t,n):(this.isActivated=!1,this.dropdown.empty(),this.dropdown.close()))},_onEnterKeyed:function(e,t){n=this.dropdown.getDatumForCursor(),i=this.dropdown.getDatumForTopSuggestion();var n,i,r={selectionMethod:"enterKey"};n?(this._select(n,r),t.preventDefault()):this.autoselect&&i&&(this._select(i,r),t.preventDefault())},_onTabKeyed:function(e,t){var n;if(!this.tabAutocomplete){this.dropdown.close();return}(n=this.dropdown.getDatumForCursor())?(this._select(n,{selectionMethod:"tabKey"}),t.preventDefault()):this._autocomplete(!0)},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var e=this.input.getQuery();this.dropdown.isEmpty&&e.length>=this.minLength?this.dropdown.update(e):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var e=this.input.getQuery();this.dropdown.isEmpty&&e.length>=this.minLength?this.dropdown.update(e):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(e,t){this.input.clearHintIfInvalid(),t.length>=this.minLength?this.dropdown.update(t):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var e=this.input.getLanguageDirection();this.dir!==e&&(this.dir=e,this.$node.css("direction",e),this.dropdown.setLanguageDirection(e))},_updateHint:function(){var e,t,n,i;(e=this.dropdown.getDatumForTopSuggestion())&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(t=this.input.getInputValue(),n=a.normalizeQuery(t),(i=RegExp("^(?:"+r.escapeRegExChars(n)+")(.+$)","i").exec(e.value))?this.input.setHint(t+i[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(e){var t,n,i,r;t=this.input.getHint(),n=this.input.getQuery(),i=e||this.input.isCursorAtEnd(),t&&n!==t&&i&&((r=this.dropdown.getDatumForTopSuggestion())&&this.input.setInputValue(r.value),this.eventBus.trigger("autocompleted",r.raw,r.datasetName))},_select:function(e,t){void 0!==e.value&&this.input.setQuery(e.value),this.clearOnSelected?this.setVal(""):this.input.setInputValue(e.value,!0),this._setLanguageDirection(),!1===this.eventBus.trigger("selected",e.raw,e.datasetName,t).isDefaultPrevented()&&(this.dropdown.close(),r.defer(r.bind(this.dropdown.empty,this.dropdown)))},open:function(){if(!this.isActivated){var e=this.input.getInputValue();e.length>=this.minLength?this.dropdown.update(e):this.dropdown.empty()}this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(e){e=r.toStr(e),this.isActivated?this.input.setInputValue(e):(this.input.setQuery(e),this.input.setInputValue(e,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),function(e,t){var n=e.find(r.className(t.prefix,t.input));r.each(n.data(i),function(e,t){void 0===e?n.removeAttr(t):n.attr(t,e)}),n.detach().removeClass(r.className(t.prefix,t.input,!0)).insertAfter(e),n.removeData&&n.removeData(i),e.remove()}(this.$node,this.cssClasses),this.$node=null},getWrapper:function(){return this.dropdown.$container[0]}});h.Dropdown=u,h.Input=a,h.sources=n(6331),e.exports=h},3855:function(e){"use strict";e.exports={element:null}},2926:function(e){"use strict";e.exports=function(e){var t=e.match(/Algolia for JavaScript \((\d+\.)(\d+\.)(\d+)\)/)||e.match(/Algolia for vanilla JavaScript (\d+\.)(\d+\.)(\d+)/);if(t)return[t[1],t[2],t[3]]}},5670:function(e,t,n){"use strict";var i,r=n(3855);function s(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}e.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(e){if(void 0===e&&(e=navigator.userAgent),/(msie|trident)/i.test(e)){var t=e.match(/(msie |rv:)(\d+(.\d+)?)/i);if(t)return t[2]}return!1},escapeRegExChars:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(e){return"number"==typeof e},toStr:function(e){return null==e?"":e+""},cloneDeep:function(e){var t=this.mixin({},e),n=this;return this.each(t,function(e,i){e&&(n.isArray(e)?t[i]=[].concat(e):n.isObject(e)&&(t[i]=n.cloneDeep(e)))}),t},error:function(e){throw Error(e)},every:function(e,t){var n=!0;return e?(this.each(e,function(i,r){n&&(n=t.call(null,i,r,e)&&n)}),!!n):n},any:function(e,t){var n=!1;return e?(this.each(e,function(i,r){if(t.call(null,i,r,e))return n=!0,!1}),n):n},getUniqueId:(i=0,function(){return i++}),templatify:function(e){if(this.isFunction(e))return e;var t=r.element(e);return"SCRIPT"===t.prop("tagName")?function(){return t.text()}:function(){return String(e)}},defer:function(e){setTimeout(e,0)},noop:function(){},formatPrefix:function(e,t){return t?"":e+"-"},className:function(e,t,n){return(n?"":".")+e+t},escapeHighlightedString:function(e,t,n){t=t||"<em>";var i=document.createElement("div");i.appendChild(document.createTextNode(t)),n=n||"</em>";var r=document.createElement("div");r.appendChild(document.createTextNode(n));var o=document.createElement("div");return o.appendChild(document.createTextNode(e)),o.innerHTML.replace(RegExp(s(i.innerHTML),"g"),t).replace(RegExp(s(r.innerHTML),"g"),n)}}},2683:function(e,t,n){"use strict";var i=n(5670),r=n(3489),s=n(2926);e.exports=function(e,t){var n=s(e.as._ua);return n&&n[0]>=3&&n[1]>20&&((t=t||{}).additionalUA="autocomplete.js "+r),function(n,r){e.search(n,t,function(e,t){if(e){i.error(e.message);return}r(t.hits,t)})}}},6331:function(e,t,n){"use strict";e.exports={hits:n(2683),popularIn:n(2226)}},2226:function(e,t,n){"use strict";var i=n(5670),r=n(3489),s=n(2926);e.exports=function(e,t,n,o){var a=s(e.as._ua);if(a&&a[0]>=3&&a[1]>20&&((t=t||{}).additionalUA="autocomplete.js "+r),!n.source)return i.error("Missing 'source' key");var u=i.isFunction(n.source)?n.source:function(e){return e[n.source]};if(!n.index)return i.error("Missing 'index' key");var c=n.index;return o=o||{},function(a,l){e.search(a,t,function(e,a){if(e){i.error(e.message);return}if(a.hits.length>0){var h=a.hits[0],p=i.mixin({hitsPerPage:0},n);delete p.source,delete p.index;var d=s(c.as._ua);d&&d[0]>=3&&d[1]>20&&(t.additionalUA="autocomplete.js "+r),c.search(u(h),p,function(e,t){if(e){i.error(e.message);return}var n=[];if(o.includeAll){var r=o.allTitle||"All departments";n.push(i.mixin({facet:{value:r,count:t.nbHits}},i.cloneDeep(h)))}i.each(t.facets,function(e,t){i.each(e,function(e,r){n.push(i.mixin({facet:{facet:t,value:r,count:e}},i.cloneDeep(h)))})});for(var s=1;s<a.hits.length;++s)n.push(a.hits[s]);l(n,a)});return}l([])})}}},9281:function(e,t,n){"use strict";var i=n(7939);n(3855).element=i;var r=n(5670);r.isArray=i.isArray,r.isFunction=i.isFunction,r.isObject=i.isPlainObject,r.bind=i.proxy,r.each=function(e,t){i.each(e,function(e,n){return t(n,e)})},r.map=i.map,r.mixin=i.extend,r.Event=i.Event;var s="aaAutocomplete",o=n(4520),a=n(7368);function u(e,t,n,u){n=r.isArray(n)?n:[].slice.call(arguments,2);var c=i(e).each(function(e,r){var c=i(r),l=new a({el:c}),h=u||new o({input:c,eventBus:l,dropdownMenuContainer:t.dropdownMenuContainer,hint:void 0===t.hint||!!t.hint,minLength:t.minLength,autoselect:t.autoselect,autoselectOnBlur:t.autoselectOnBlur,tabAutocomplete:t.tabAutocomplete,openOnFocus:t.openOnFocus,templates:t.templates,debug:t.debug,clearOnSelected:t.clearOnSelected,cssClasses:t.cssClasses,datasets:n,keyboardShortcuts:t.keyboardShortcuts,appendTo:t.appendTo,autoWidth:t.autoWidth,ariaLabel:t.ariaLabel||r.getAttribute("aria-label")});c.data(s,h)});return c.autocomplete={},r.each(["open","close","getVal","setVal","destroy","getWrapper"],function(e){c.autocomplete[e]=function(){var t,n=arguments;return c.each(function(r,o){var a=i(o).data(s);t=a[e].apply(a,n)}),t}}),c}u.sources=o.sources,u.escapeHighlightedString=r.escapeHighlightedString;var c="autocomplete"in window,l=window.autocomplete;u.noConflict=function(){return c?window.autocomplete=l:delete window.autocomplete,u},e.exports=u},3489:function(e){e.exports="0.37.1"},7939:function(e){var t,n;t=window,n=function(e){var t,n,i=function(){var t,n,i,r,s,o,a=[],u=a.concat,c=a.filter,l=a.slice,h=e.document,p={},d={},f={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},g=/^\s*<(\w+|!)[^>]*>/,m=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,y=/^(?:body|html)$/i,x=/([A-Z])/g,b=["val","css","html","text","data","width","height","offset"],w=h.createElement("table"),S=h.createElement("tr"),C={tr:h.createElement("tbody"),tbody:w,thead:w,tfoot:w,td:S,th:S,"*":h.createElement("div")},E=/complete|loaded|interactive/,_=/^[\w-]*$/,k={},T=k.toString,O={},L=h.createElement("div"),A={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},$=Array.isArray||function(e){return e instanceof Array};function P(e){return null==e?String(e):k[T.call(e)]||"object"}function I(e){return"function"==P(e)}function Q(e){return null!=e&&e==e.window}function R(e){return null!=e&&e.nodeType==e.DOCUMENT_NODE}function N(e){return"object"==P(e)}function D(e){return N(e)&&!Q(e)&&Object.getPrototypeOf(e)==Object.prototype}function F(e){var t=!!e&&"length"in e&&e.length,n=i.type(e);return"function"!=n&&!Q(e)&&("array"==n||0===t||"number"==typeof t&&t>0&&t-1 in e)}O.matches=function(e,t){if(!t||!e||1!==e.nodeType)return!1;var n=e.matches||e.webkitMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.matchesSelector;if(n)return n.call(e,t);var i,r=e.parentNode,s=!r;return s&&(r=L).appendChild(e),i=~O.qsa(r,t).indexOf(e),s&&L.removeChild(e),i};function j(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function H(e){return e in d?d[e]:d[e]=RegExp("(^|\\s)"+e+"(\\s|$)")}function V(e,t){return"number"!=typeof t||f[j(e)]?t:t+"px"}s=function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},o=function(e){return c.call(e,function(t,n){return e.indexOf(t)==n})};function B(e){return"children"in e?l.call(e.children):i.map(e.childNodes,function(e){if(1==e.nodeType)return e})}function M(e,t){var n,i=e?e.length:0;for(n=0;n<i;n++)this[n]=e[n];this.length=i,this.selector=t||""}O.fragment=function(e,n,r){var s,o,a;return m.test(e)&&(s=i(h.createElement(RegExp.$1))),!s&&(e.replace&&(e=e.replace(v,"<$1></$2>")),t===n&&(n=g.test(e)&&RegExp.$1),!(n in C)&&(n="*"),(a=C[n]).innerHTML=""+e,s=i.each(l.call(a.childNodes),function(){a.removeChild(this)})),D(r)&&(o=i(s),i.each(r,function(e,t){b.indexOf(e)>-1?o[e](t):o.attr(e,t)})),s},O.Z=function(e,t){return new M(e,t)},O.isZ=function(e){return e instanceof O.Z},O.init=function(e,n){var r,s;if(!e)return O.Z();if("string"==typeof e){if("<"==(e=e.trim())[0]&&g.test(e))r=O.fragment(e,RegExp.$1,n),e=null;else{if(t!==n)return i(n).find(e);r=O.qsa(h,e)}}else{if(I(e))return i(h).ready(e);if(O.isZ(e))return e;if($(e)){;s=e,r=c.call(s,function(e){return null!=e})}else if(N(e))r=[e],e=null;else if(g.test(e))r=O.fragment(e.trim(),RegExp.$1,n),e=null;else{if(t!==n)return i(n).find(e);r=O.qsa(h,e)}}return O.Z(r,e)},i=function(e,t){return O.init(e,t)};function q(e,t){return null==t?i(e):i(e).filter(t)}function z(e,t,n,i){return I(t)?t.call(e,n,i):t}function K(e,t,n){null==n?e.removeAttribute(t):e.setAttribute(t,n)}function W(e,n){var i=e.className||"",r=i&&i.baseVal!==t;if(t===n)return r?i.baseVal:i;r?i.baseVal=n:e.className=n}function U(e){try{return e?"true"==e||"false"!=e&&("null"==e?null:+e+""==e?+e:/^[\[\{]/.test(e)?i.parseJSON(e):e):e}catch(t){return e}}return i.extend=function(e){var i,r=l.call(arguments,1);return"boolean"==typeof e&&(i=e,e=r.shift()),r.forEach(function(r){!function e(i,r,s){for(n in r)s&&(D(r[n])||$(r[n]))?(D(r[n])&&!D(i[n])&&(i[n]={}),$(r[n])&&!$(i[n])&&(i[n]=[]),e(i[n],r[n],s)):r[n]!==t&&(i[n]=r[n])}(e,r,i)}),e},O.qsa=function(e,t){var n,i="#"==t[0],r=!i&&"."==t[0],s=i||r?t.slice(1):t,o=_.test(s);return e.getElementById&&o&&i?(n=e.getElementById(s))?[n]:[]:1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType?[]:l.call(o&&!i&&e.getElementsByClassName?r?e.getElementsByClassName(s):e.getElementsByTagName(t):e.querySelectorAll(t))},i.contains=h.documentElement.contains?function(e,t){return e!==t&&e.contains(t)}:function(e,t){for(;t&&(t=t.parentNode);)if(t===e)return!0;return!1},i.type=P,i.isFunction=I,i.isWindow=Q,i.isArray=$,i.isPlainObject=D,i.isEmptyObject=function(e){var t;for(t in e)return!1;return!0},i.isNumeric=function(e){var t=Number(e),n=typeof e;return null!=e&&"boolean"!=n&&("string"!=n||e.length)&&!isNaN(t)&&isFinite(t)||!1},i.inArray=function(e,t,n){return a.indexOf.call(t,e,n)},i.camelCase=s,i.trim=function(e){return null==e?"":String.prototype.trim.call(e)},i.uuid=0,i.support={},i.expr={},i.noop=function(){},i.map=function(e,t){var n,r,s,o,a=[];if(F(e))for(s=0;s<e.length;s++)null!=(r=t(e[s],s))&&a.push(r);else for(o in e)null!=(r=t(e[o],o))&&a.push(r);return(n=a).length>0?i.fn.concat.apply([],n):n},i.each=function(e,t){var n,i;if(F(e))for(n=0;n<e.length&&!1!==t.call(e[n],n,e[n]);n++);else for(i in e)if(!1===t.call(e[i],i,e[i]))break;return e},i.grep=function(e,t){return c.call(e,t)},e.JSON&&(i.parseJSON=JSON.parse),i.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){k["[object "+t+"]"]=t.toLowerCase()}),i.fn={constructor:O.Z,length:0,forEach:a.forEach,reduce:a.reduce,push:a.push,sort:a.sort,splice:a.splice,indexOf:a.indexOf,concat:function(){var e,t,n=[];for(e=0;e<arguments.length;e++)t=arguments[e],n[e]=O.isZ(t)?t.toArray():t;return u.apply(O.isZ(this)?this.toArray():this,n)},map:function(e){return i(i.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return i(l.apply(this,arguments))},ready:function(e){return E.test(h.readyState)&&h.body?e(i):h.addEventListener("DOMContentLoaded",function(){e(i)},!1),this},get:function(e){return t===e?l.call(this):this[e>=0?e:e+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(e){return a.every.call(this,function(t,n){return!1!==e.call(t,n,t)}),this},filter:function(e){return I(e)?this.not(this.not(e)):i(c.call(this,function(t){return O.matches(t,e)}))},add:function(e,t){return i(o(this.concat(i(e,t))))},is:function(e){return this.length>0&&O.matches(this[0],e)},not:function(e){var n=[];if(I(e)&&e.call!==t)this.each(function(t){!e.call(this,t)&&n.push(this)});else{var r="string"==typeof e?this.filter(e):F(e)&&I(e.item)?l.call(e):i(e);this.forEach(function(e){0>r.indexOf(e)&&n.push(e)})}return i(n)},has:function(e){return this.filter(function(){return N(e)?i.contains(this,e):i(this).find(e).size()})},eq:function(e){return -1===e?this.slice(e):this.slice(e,+e+1)},first:function(){var e=this[0];return e&&!N(e)?e:i(e)},last:function(){var e=this[this.length-1];return e&&!N(e)?e:i(e)},find:function(e){var t,n=this;return t=e?"object"==typeof e?i(e).filter(function(){var e=this;return a.some.call(n,function(t){return i.contains(t,e)})}):1==this.length?i(O.qsa(this[0],e)):this.map(function(){return O.qsa(this,e)}):i()},closest:function(e,t){var n=[],r="object"==typeof e&&i(e);return this.each(function(i,s){for(;s&&!(r?r.indexOf(s)>=0:O.matches(s,e));)s=s!==t&&!R(s)&&s.parentNode;s&&0>n.indexOf(s)&&n.push(s)}),i(n)},parents:function(e){for(var t=[],n=this;n.length>0;)n=i.map(n,function(e){if((e=e.parentNode)&&!R(e)&&0>t.indexOf(e))return t.push(e),e});return q(t,e)},parent:function(e){return q(o(this.pluck("parentNode")),e)},children:function(e){return q(this.map(function(){return B(this)}),e)},contents:function(){return this.map(function(){return this.contentDocument||l.call(this.childNodes)})},siblings:function(e){return q(this.map(function(e,t){return c.call(B(t.parentNode),function(e){return e!==t})}),e)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(e){return i.map(this,function(t){return t[e]})},show:function(){return this.each(function(){if("none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")){var e,t,n;this.style.display=(!p[e=this.nodeName]&&(t=h.createElement(e),h.body.appendChild(t),n=getComputedStyle(t,"").getPropertyValue("display"),t.parentNode.removeChild(t),"none"==n&&(n="block"),p[e]=n),p[e])}})},replaceWith:function(e){return this.before(e).remove()},wrap:function(e){var t=I(e);if(this[0]&&!t)var n=i(e).get(0),r=n.parentNode||this.length>1;return this.each(function(s){i(this).wrapAll(t?e.call(this,s):r?n.cloneNode(!0):n)})},wrapAll:function(e){if(this[0]){var t;for(i(this[0]).before(e=i(e));(t=e.children()).length;)e=t.first();i(e).append(this)}return this},wrapInner:function(e){var t=I(e);return this.each(function(n){var r=i(this),s=r.contents(),o=t?e.call(this,n):e;s.length?s.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){i(this).replaceWith(i(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(e){return this.each(function(){var n=i(this);(t===e?"none"==n.css("display"):e)?n.show():n.hide()})},prev:function(e){return i(this.pluck("previousElementSibling")).filter(e||"*")},next:function(e){return i(this.pluck("nextElementSibling")).filter(e||"*")},html:function(e){return 0 in arguments?this.each(function(t){var n=this.innerHTML;i(this).empty().append(z(this,e,t,n))}):0 in this?this[0].innerHTML:null},text:function(e){return 0 in arguments?this.each(function(t){var n=z(this,e,t,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(e,i){var r;return"string"!=typeof e||1 in arguments?this.each(function(t){if(1===this.nodeType){if(N(e))for(n in e)K(this,n,e[n]);else K(this,e,z(this,i,t,this.getAttribute(e)))}}):0 in this&&1==this[0].nodeType&&null!=(r=this[0].getAttribute(e))?r:t},removeAttr:function(e){return this.each(function(){1===this.nodeType&&e.split(" ").forEach(function(e){K(this,e)},this)})},prop:function(e,t){return e=A[e]||e,1 in arguments?this.each(function(n){this[e]=z(this,t,n,this[e])}):this[0]&&this[0][e]},removeProp:function(e){return e=A[e]||e,this.each(function(){delete this[e]})},data:function(e,n){var i="data-"+e.replace(x,"-$1").toLowerCase(),r=1 in arguments?this.attr(i,n):this.attr(i);return null!==r?U(r):t},val:function(e){return 0 in arguments?(null==e&&(e=""),this.each(function(t){this.value=z(this,e,t,this.value)})):this[0]&&(this[0].multiple?i(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var n=i(this),r=z(this,t,e,n.offset()),s=n.offsetParent().offset(),o={top:r.top-s.top,left:r.left-s.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(h.documentElement!==this[0]&&!i.contains(h.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+e.pageXOffset,top:n.top+e.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(e,t){if(arguments.length<2){var r=this[0];if("string"==typeof e){if(!r)return;return r.style[s(e)]||getComputedStyle(r,"").getPropertyValue(e)}if($(e)){if(!r)return;var o={},a=getComputedStyle(r,"");return i.each(e,function(e,t){o[t]=r.style[s(t)]||a.getPropertyValue(t)}),o}}var u="";if("string"==P(e))t||0===t?u=j(e)+":"+V(e,t):this.each(function(){this.style.removeProperty(j(e))});else for(n in e)e[n]||0===e[n]?u+=j(n)+":"+V(n,e[n])+";":this.each(function(){this.style.removeProperty(j(n))});return this.each(function(){this.style.cssText+=";"+u})},index:function(e){return e?this.indexOf(i(e)[0]):this.parent().children().indexOf(this[0])},hasClass:function(e){return!!e&&a.some.call(this,function(e){return this.test(W(e))},H(e))},addClass:function(e){return e?this.each(function(t){if("className"in this){r=[];var n=W(this);z(this,e,t,n).split(/\s+/g).forEach(function(e){!i(this).hasClass(e)&&r.push(e)},this),r.length&&W(this,n+(n?" ":"")+r.join(" "))}}):this},removeClass:function(e){return this.each(function(n){if("className"in this){if(t===e)return W(this,"");z(this,e,n,r=W(this)).split(/\s+/g).forEach(function(e){r=r.replace(H(e)," ")}),W(this,r.trim())}})},toggleClass:function(e,n){return e?this.each(function(r){var s=i(this);z(this,e,r,W(this)).split(/\s+/g).forEach(function(e){(t===n?!s.hasClass(e):n)?s.addClass(e):s.removeClass(e)})}):this},scrollTop:function(e){if(this.length){var n="scrollTop"in this[0];return t===e?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=e}:function(){this.scrollTo(this.scrollX,e)})}},scrollLeft:function(e){if(this.length){var n="scrollLeft"in this[0];return t===e?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=e}:function(){this.scrollTo(e,this.scrollY)})}},position:function(){if(this.length){var e=this[0],t=this.offsetParent(),n=this.offset(),r=y.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(i(e).css("margin-top"))||0,n.left-=parseFloat(i(e).css("margin-left"))||0,r.top+=parseFloat(i(t[0]).css("border-top-width"))||0,r.left+=parseFloat(i(t[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||h.body;e&&!y.test(e.nodeName)&&"static"==i(e).css("position");)e=e.offsetParent;return e})}},i.fn.detach=i.fn.remove,["width","height"].forEach(function(e){var n=e.replace(/./,function(e){return e[0].toUpperCase()});i.fn[e]=function(r){var s,o=this[0];return t===r?Q(o)?o["inner"+n]:R(o)?o.documentElement["scroll"+n]:(s=this.offset())&&s[e]:this.each(function(t){(o=i(this)).css(e,z(this,r,t,o[e]()))})}}),["after","prepend","before","append"].forEach(function(n,r){var s=r%2;i.fn[n]=function(){var n,o,a=i.map(arguments,function(e){var r=[];return"array"==(n=P(e))?(e.forEach(function(e){return e.nodeType!==t?r.push(e):i.zepto.isZ(e)?r=r.concat(e.get()):void(r=r.concat(O.fragment(e)))}),r):"object"==n||null==e?e:O.fragment(e)}),u=this.length>1;return a.length<1?this:this.each(function(t,n){o=s?n:n.parentNode,n=0==r?n.nextSibling:1==r?n.firstChild:2==r?n:null;var c=i.contains(h.documentElement,o);a.forEach(function(t){if(u)t=t.cloneNode(!0);else if(!o)return i(t).remove();o.insertBefore(t,n),c&&!function e(t,n){n(t);for(var i=0,r=t.childNodes.length;i<r;i++)e(t.childNodes[i],n)}(t,function(t){if(null!=t.nodeName&&"SCRIPT"===t.nodeName.toUpperCase()&&(!t.type||"text/javascript"===t.type)&&!t.src){var n=t.ownerDocument?t.ownerDocument.defaultView:e;n.eval.call(n,t.innerHTML)}})})})},i.fn[s?n+"To":"insert"+(r?"Before":"After")]=function(e){return i(e)[n](this),this}}),O.Z.prototype=M.prototype=i.fn,O.uniq=o,O.deserializeValue=U,i.zepto=O,i}();return!function(t){var n,i=1,r=Array.prototype.slice,s=t.isFunction,o=function(e){return"string"==typeof e},a={},u={},c="onfocusin"in e,l={focus:"focusin",blur:"focusout"},h={mouseenter:"mouseover",mouseleave:"mouseout"};function p(e){return e._zid||(e._zid=i++)}function d(e,t,n,i){if((t=f(t)).ns)var r=function(e){return RegExp("(?:^| )"+e.replace(" "," .* ?")+"(?: |$)")}(t.ns);return(a[p(e)]||[]).filter(function(e){return e&&(!t.e||e.e==t.e)&&(!t.ns||r.test(e.ns))&&(!n||p(e.fn)===p(n))&&(!i||e.sel==i)})}function f(e){var t=(""+e).split(".");return{e:t[0],ns:t.slice(1).sort().join(" ")}}u.click=u.mousedown=u.mouseup=u.mousemove="MouseEvents";function g(e,t){return e.del&&!c&&e.e in l||!!t}function m(e){return h[e]||c&&l[e]||e}function v(e,i,r,s,o,u,c){var l=p(e),d=a[l]||(a[l]=[]);i.split(/\s/).forEach(function(i){if("ready"==i)return t(document).ready(r);var a=f(i);a.fn=r,a.sel=o,a.e in h&&(r=function(e){var n=e.relatedTarget;if(!n||n!==this&&!t.contains(this,n))return a.fn.apply(this,arguments)}),a.del=u;var l=u||r;a.proxy=function(t){if(!(t=C(t)).isImmediatePropagationStopped()){try{var i=Object.getOwnPropertyDescriptor(t,"data");(!i||i.writable)&&(t.data=s)}catch(e){}var r=l.apply(e,t._args==n?[t]:[t].concat(t._args));return!1===r&&(t.preventDefault(),t.stopPropagation()),r}},a.i=d.length,d.push(a),"addEventListener"in e&&e.addEventListener(m(a.e),a.proxy,g(a,c))})}function y(e,t,n,i,r){var s=p(e);(t||"").split(/\s/).forEach(function(t){d(e,t,n,i).forEach(function(t){delete a[s][t.i],"removeEventListener"in e&&e.removeEventListener(m(t.e),t.proxy,g(t,r))})})}t.event={add:v,remove:y},t.proxy=function(e,n){var i=2 in arguments&&r.call(arguments,2);if(s(e)){var a=function(){return e.apply(n,i?i.concat(r.call(arguments)):arguments)};return a._zid=p(e),a}if(o(n))return i?(i.unshift(e[n],e),t.proxy.apply(null,i)):t.proxy(e[n],e);throw TypeError("expected function")},t.fn.bind=function(e,t,n){return this.on(e,t,n)},t.fn.unbind=function(e,t){return this.off(e,t)},t.fn.one=function(e,t,n,i){return this.on(e,t,n,i,1)};var x=function(){return!0},b=function(){return!1},w=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,S={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};function C(e,i){if(i||!e.isDefaultPrevented){i||(i=e),t.each(S,function(t,n){var r=i[t];e[t]=function(){return this[n]=x,r&&r.apply(i,arguments)},e[n]=b});try{e.timeStamp||(e.timeStamp=Date.now())}catch(e){}(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?!1===i.returnValue:i.getPreventDefault&&i.getPreventDefault())&&(e.isDefaultPrevented=x)}return e}function E(e){var t,i={originalEvent:e};for(t in e)!w.test(t)&&e[t]!==n&&(i[t]=e[t]);return C(i,e)}t.fn.delegate=function(e,t,n){return this.on(t,e,n)},t.fn.undelegate=function(e,t,n){return this.off(t,e,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,i,a,u,c){var l,h,p=this;return e&&!o(e)?(t.each(e,function(e,t){p.on(e,i,a,t,c)}),p):(!o(i)&&!s(u)&&!1!==u&&(u=a,a=i,i=n),(n===u||!1===a)&&(u=a,a=n),!1===u&&(u=b),p.each(function(n,s){c&&(l=function(e){return y(s,e.type,u),u.apply(this,arguments)}),i&&(h=function(e){var n,o=t(e.target).closest(i,s).get(0);if(o&&o!==s)return n=t.extend(E(e),{currentTarget:o,liveFired:s}),(l||u).apply(o,[n].concat(r.call(arguments,1)))}),v(s,e,u,a,i,h||l)}))},t.fn.off=function(e,i,r){var a=this;return e&&!o(e)?(t.each(e,function(e,t){a.off(e,i,t)}),a):(!o(i)&&!s(r)&&!1!==r&&(r=i,i=n),!1===r&&(r=b),a.each(function(){y(this,e,r,i)}))},t.fn.trigger=function(e,n){return(e=o(e)||t.isPlainObject(e)?t.Event(e):C(e))._args=n,this.each(function(){e.type in l&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,n){var i,r;return this.each(function(s,a){(i=E(o(e)?t.Event(e):e))._args=n,i.target=a,t.each(d(a,e.type||e),function(e,t){if(r=t.proxy(i),i.isImmediatePropagationStopped())return!1})}),r},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(e,t){!o(e)&&(e=(t=e).type);var n=document.createEvent(u[e]||"Events"),i=!0;if(t)for(var r in t)"bubbles"==r?i=!!t[r]:n[r]=t[r];return n.initEvent(e,i,!0),C(n)}}(i),n=[],i.fn.remove=function(){return this.each(function(){this.parentNode&&("IMG"===this.tagName&&(n.push(this),this.src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=",t&&clearTimeout(t),t=setTimeout(function(){n=[]},6e4)),this.parentNode.removeChild(this))})},!function(e){var t={},n=e.fn.data,i=e.camelCase,r=e.expando="Zepto"+ +new Date,s=[];function o(n,o,a){var u=n[r]||(n[r]=++e.uuid),c=t[u]||(t[u]=function(t){var n={};return e.each(t.attributes||s,function(t,r){0==r.name.indexOf("data-")&&(n[i(r.name.replace("data-",""))]=e.zepto.deserializeValue(r.value))}),n}(n));return void 0!==o&&(c[i(o)]=a),c}e.fn.data=function(s,a){return void 0===a?e.isPlainObject(s)?this.each(function(t,n){e.each(s,function(e,t){o(n,e,t)})}):0 in this?function(s,a){var u=s[r],c=u&&t[u];if(void 0===a)return c||o(s);if(c){if(a in c)return c[a];var l=i(a);if(l in c)return c[l]}return n.call(e(s),a)}(this[0],s):void 0:this.each(function(){o(this,s,a)})},e.data=function(t,n,i){return e(t).data(n,i)},e.hasData=function(n){var i=n[r],s=i&&t[i];return!!s&&!e.isEmptyObject(s)},e.fn.removeData=function(n){return"string"==typeof n&&(n=n.split(/\s+/)),this.each(function(){var s=this[r],o=s&&t[s];o&&e.each(n||o,function(e){delete o[n?i(this):e]})})},["remove","empty"].forEach(function(t){var n=e.fn[t];e.fn[t]=function(){var e=this.find("*");return"remove"===t&&(e=e.add(this)),e.removeData(),n.call(this)}})}(i),i},e.exports=n(t)},9397:function(e,t){!function(e){var t=/\S/,n=/\"/g,i=/\n/g,r=/\r/g,s=/\\/g,o=/\u2028/,a=/\u2029/;e.tags={"#":1,"^":2,"<":3,$:4,"/":5,"!":6,">":7,"=":8,_v:9,"{":10,"&":11,_t:12},e.scan=function(n,i){var r=n.length,s=0,o=null,a=null,l="",h=[],p=!1,d=0,f=0,g="{{",m="}}";function v(){l.length>0&&(h.push({tag:"_t",text:new String(l)}),l="")}function y(n,i){if(v(),n&&function(){for(var n=!0,i=f;i<h.length;i++)if(!(n=e.tags[h[i].tag]<e.tags._v||"_t"==h[i].tag&&null===h[i].text.match(t)))return!1;return n}())for(var r,s=f;s<h.length;s++)h[s].text&&((r=h[s+1])&&">"==r.tag&&(r.indent=h[s].text.toString()),h.splice(s,1));else!i&&h.push({tag:"\n"});p=!1,f=h.length}for(i&&(g=(i=i.split(" "))[0],m=i[1]),d=0;d<r;d++)0==s?c(g,n,d)?(--d,v(),s=1):"\n"==n.charAt(d)?y(p):l+=n.charAt(d):1==s?(d+=g.length-1,"="==(o=(a=e.tags[n.charAt(d+1)])?n.charAt(d+1):"_v")?(d=function(e,t){var n="="+m,i=e.indexOf(n,t),r=u(e.substring(e.indexOf("=",t)+1,i)).split(" ");return g=r[0],m=r[r.length-1],i+n.length-1}(n,d),s=0):(a&&d++,s=2),p=d):c(m,n,d)?(h.push({tag:o,n:u(l),otag:g,ctag:m,i:"/"==o?p-g.length:d+m.length}),l="",d+=m.length-1,s=0,"{"==o&&("}}"==m?d++:function(e){"}"===e.n.substr(e.n.length-1)&&(e.n=e.n.substring(0,e.n.length-1))}(h[h.length-1]))):l+=n.charAt(d);return y(p,!0),h};function u(e){return e.trim?e.trim():e.replace(/^\s*|\s*$/g,"")}function c(e,t,n){if(t.charAt(n)!=e.charAt(0))return!1;for(var i=1,r=e.length;i<r;i++)if(t.charAt(n+i)!=e.charAt(i))return!1;return!0}var l={_t:!0,"\n":!0,$:!0,"/":!0};e.stringify=function(t,n,i){return"{code: function (c,p,i) { "+e.wrapMain(t.code)+" },"+function e(t){var n=[];for(var i in t.partials)n.push('"'+p(i)+'":{name:"'+p(t.partials[i].name)+'", '+e(t.partials[i])+"}");return"partials: {"+n.join(",")+"}, subs: "+function(e){var t=[];for(var n in e)t.push('"'+p(n)+'": function(c,p,t,i) {'+e[n]+"}");return"{ "+t.join(",")+" }"}(t.subs)}(t)+"}"};var h=0;function p(e){return e.replace(s,"\\\\").replace(n,'\\"').replace(i,"\\n").replace(r,"\\r").replace(o,"\\u2028").replace(a,"\\u2029")}function d(e){return~e.indexOf(".")?"d":"f"}function f(e,t){var n="<"+(t.prefix||"")+e.n+h++;return t.partials[n]={name:e.n,partials:{}},t.code+='t.b(t.rp("'+p(n)+'",c,p,"'+(e.indent||"")+'"));',n}function g(e,t){t.code+="t.b(t.t(t."+d(e.n)+'("'+p(e.n)+'",c,p,0)));'}function m(e){return"t.b("+e+");"}e.generate=function(t,n,i){h=0;var r={code:"",subs:{},partials:{}};return(e.walk(t,r),i.asString)?this.stringify(r,n,i):this.makeTemplate(r,n,i)},e.wrapMain=function(e){return'var t=this;t.b(i=i||"");'+e+"return t.fl();"},e.template=e.Template,e.makeTemplate=function(e,t,n){var i=this.makePartials(e);return i.code=Function("c","p","i",this.wrapMain(e.code)),new this.template(i,t,this,n)},e.makePartials=function(e){var t,n={subs:{},partials:e.partials,name:e.name};for(t in n.partials)n.partials[t]=this.makePartials(n.partials[t]);for(t in e.subs)n.subs[t]=Function("c","p","t","i",e.subs[t]);return n},e.codegen={"#":function(t,n){n.code+="if(t.s(t."+d(t.n)+'("'+p(t.n)+'",c,p,1),c,p,0,'+t.i+","+t.end+',"'+t.otag+" "+t.ctag+'")){t.rs(c,p,function(c,p,t){',e.walk(t.nodes,n),n.code+="});c.pop();}"},"^":function(t,n){n.code+="if(!t.s(t."+d(t.n)+'("'+p(t.n)+'",c,p,1),c,p,1,0,0,"")){',e.walk(t.nodes,n),n.code+="};"},">":f,"<":function(t,n){var i={partials:{},code:"",subs:{},inPartial:!0};e.walk(t.nodes,i);var r=n.partials[f(t,n)];r.subs=i.subs,r.partials=i.partials},$:function(t,n){var i={subs:{},code:"",partials:n.partials,prefix:t.n};e.walk(t.nodes,i),n.subs[t.n]=i.code,!n.inPartial&&(n.code+='t.sub("'+p(t.n)+'",c,p,i);')},"\n":function(e,t){t.code+=m('"\\n"'+(e.last?"":" + i"))},_v:function(e,t){t.code+="t.b(t.v(t."+d(e.n)+'("'+p(e.n)+'",c,p,0)));'},_t:function(e,t){t.code+=m('"'+p(e.text)+'"')},"{":g,"&":g},e.walk=function(t,n){for(var i,r=0,s=t.length;r<s;r++)(i=e.codegen[t[r].tag])&&i(t[r],n);return n},e.parse=function(t,n,i){return function t(n,i,r,s){var o=[],a=null,u=null,c=null;for(u=r[r.length-1];n.length>0;){if(c=n.shift(),u&&"<"==u.tag&&!(c.tag in l))throw Error("Illegal content in < super tag.");if(e.tags[c.tag]<=e.tags.$||function(e,t){for(var n=0,i=t.length;n<i;n++)if(t[n].o==e.n)return e.tag="#",!0}(c,s))r.push(c),c.nodes=t(n,c.tag,r,s);else if("/"==c.tag){if(0===r.length)throw Error("Closing tag without opener: /"+c.n);if(a=r.pop(),c.n!=a.n&&!function(e,t,n){for(var i=0,r=n.length;i<r;i++)if(n[i].c==e&&n[i].o==t)return!0}(c.n,a.n,s))throw Error("Nesting error: "+a.n+" vs. "+c.n);return a.end=c.i,o}else"\n"==c.tag&&(c.last=0==n.length||"\n"==n[0].tag);o.push(c)}if(r.length>0)throw Error("missing closing tag: "+r.pop().n);return o}(t,"",[],(i=i||{}).sectionTags||[])},e.cache={},e.cacheKey=function(e,t){return[e,!!t.asString,!!t.disableLambda,t.delimiters,!!t.modelGet].join("||")},e.compile=function(t,n){n=n||{};var i=e.cacheKey(t,n),r=this.cache[i];if(r){var s=r.partials;for(var o in s)delete s[o].instance;return r}return r=this.generate(this.parse(this.scan(t,n.delimiters),t,n),t,n),this.cache[i]=r}}(t)},5485:function(e,t,n){var i=n(9397);i.Template=n(2882).Template,i.template=i.Template,e.exports=i},2882:function(e,t){!function(e){function t(e,t,n){var i;return t&&"object"==typeof t&&(void 0!==t[e]?i=t[e]:n&&t.get&&"function"==typeof t.get&&(i=t.get(e))),i}e.Template=function(e,t,n,i){e=e||{},this.r=e.code||this.r,this.c=n,this.options=i||{},this.text=t||"",this.partials=e.partials||{},this.subs=e.subs||{},this.buf=""},e.Template.prototype={r:function(e,t,n){return""},v:function(e){return e=u(e),a.test(e)?e.replace(n,"&").replace(i,"<").replace(r,">").replace(s,"'").replace(o,"""):e},t:u,render:function(e,t,n){return this.ri([e],t||{},n)},ri:function(e,t,n){return this.r(e,t,n)},ep:function(e,t){var n=this.partials[e],i=t[n.name];if(n.instance&&n.base==i)return n.instance;if("string"==typeof i){if(!this.c)throw Error("No compiler available.");i=this.c.compile(i,this.options)}if(!i)return null;if(this.partials[e].base=i,n.subs){for(key in!t.stackText&&(t.stackText={}),n.subs)!t.stackText[key]&&(t.stackText[key]=void 0!==this.activeSub&&t.stackText[this.activeSub]?t.stackText[this.activeSub]:this.text);i=function(e,t,n,i,r,s){function o(){}function a(){}o.prototype=e,a.prototype=e.subs;var u,c=new o;for(u in c.subs=new a,c.subsText={},c.buf="",i=i||{},c.stackSubs=i,c.subsText=s,t)!i[u]&&(i[u]=t[u]);for(u in i)c.subs[u]=i[u];for(u in r=r||{},c.stackPartials=r,n)!r[u]&&(r[u]=n[u]);for(u in r)c.partials[u]=r[u];return c}(i,n.subs,n.partials,this.stackSubs,this.stackPartials,t.stackText)}return this.partials[e].instance=i,i},rp:function(e,t,n,i){var r=this.ep(e,n);return r?r.ri(t,n,i):""},rs:function(e,t,n){var i=e[e.length-1];if(!c(i)){n(e,t,this);return}for(var r=0;r<i.length;r++)e.push(i[r]),n(e,t,this),e.pop()},s:function(e,t,n,i,r,s,o){var a;return(!c(e)||0!==e.length)&&("function"==typeof e&&(e=this.ms(e,t,n,i,r,s,o)),a=!!e,!i&&a&&t&&t.push("object"==typeof e?e:t[t.length-1]),a)},d:function(e,n,i,r){var s,o=e.split("."),a=this.f(o[0],n,i,r),u=this.options.modelGet,l=null;if("."===e&&c(n[n.length-2]))a=n[n.length-1];else for(var h=1;h<o.length;h++)void 0!==(s=t(o[h],a,u))?(l=a,a=s):a="";return(!r||!!a)&&(!r&&"function"==typeof a&&(n.push(l),a=this.mv(a,n,i),n.pop()),a)},f:function(e,n,i,r){for(var s=!1,o=null,a=!1,u=this.options.modelGet,c=n.length-1;c>=0;c--)if(void 0!==(s=t(e,o=n[c],u))){a=!0;break}return a?(!r&&"function"==typeof s&&(s=this.mv(s,n,i)),s):!r&&""},ls:function(e,t,n,i,r){var s=this.options.delimiters;return this.options.delimiters=r,this.b(this.ct(u(e.call(t,i)),t,n)),this.options.delimiters=s,!1},ct:function(e,t,n){if(this.options.disableLambda)throw Error("Lambda features disabled.");return this.c.compile(e,this.options).render(t,n)},b:function(e){this.buf+=e},fl:function(){var e=this.buf;return this.buf="",e},ms:function(e,t,n,i,r,s,o){var a,u=t[t.length-1],c=e.call(u);if("function"==typeof c)return!!i||(a=this.activeSub&&this.subsText&&this.subsText[this.activeSub]?this.subsText[this.activeSub]:this.text,this.ls(c,u,n,a.substring(r,s),o));return c},mv:function(e,t,n){var i=t[t.length-1],r=e.call(i);return"function"==typeof r?this.ct(u(r.call(i)),i,n):r},sub:function(e,t,n,i){var r=this.subs[e];r&&(this.activeSub=e,r(t,n,this,i),this.activeSub=!1)}};var n=/&/g,i=/</g,r=/>/g,s=/\'/g,o=/\"/g,a=/[&<>\"\']/;function u(e){return String(null==e?"":e)}var c=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}}(t)},624:function(e,t,n){"use strict";var i,r,s,o=[n(7936),n(4785),n(8291),n(2709),n(2506),n(9176)],a=-1,u=[],c=!1;function l(){if(!!i&&!!r)i=!1,r.length?u=r.concat(u):a=-1,u.length&&h()}function h(){if(!i){c=!1,i=!0;for(var e=u.length,t=setTimeout(l);e;){for(r=u,u=[];r&&++a<e;)r[a].run();a=-1,e=u.length}r=null,a=-1,i=!1,clearTimeout(t)}}for(var p=-1,d=o.length;++p<d;)if(o[p]&&o[p].test&&o[p].test()){s=o[p].install(h);break}function f(e,t){this.fun=e,this.array=t}f.prototype.run=function(){var e=this.fun,t=this.array;switch(t.length){case 0:return e();case 1:return e(t[0]);case 2:return e(t[0],t[1]);case 3:return e(t[0],t[1],t[2]);default:return e.apply(null,t)}},e.exports=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];u.push(new f(e,t)),!c&&!i&&(c=!0,s())}},2709:function(e,t,n){"use strict";t.test=function(){return!n.g.setImmediate&&void 0!==n.g.MessageChannel},t.install=function(e){var t=new n.g.MessageChannel;return t.port1.onmessage=e,function(){t.port2.postMessage(0)}}},8291:function(e,t,n){"use strict";var i=n.g.MutationObserver||n.g.WebKitMutationObserver;t.test=function(){return i},t.install=function(e){var t=0,r=new i(e),s=n.g.document.createTextNode("");return r.observe(s,{characterData:!0}),function(){s.data=t=++t%2}}},4785:function(e,t,n){"use strict";t.test=function(){return"function"==typeof n.g.queueMicrotask},t.install=function(e){return function(){n.g.queueMicrotask(e)}}},2506:function(e,t,n){"use strict";t.test=function(){return"document"in n.g&&"onreadystatechange"in n.g.document.createElement("script")},t.install=function(e){return function(){var t=n.g.document.createElement("script");return t.onreadystatechange=function(){e(),t.onreadystatechange=null,t.parentNode.removeChild(t),t=null},n.g.document.documentElement.appendChild(t),e}}},9176:function(e,t){"use strict";t.test=function(){return!0},t.install=function(e){return function(){setTimeout(e,0)}}},1336:function(e){!function(){var t,n,i,r,s,o,a,u,c,l,h,p,d,f,g,m,v,y,x,b,w,S,C,E,_,k,T,O,L,A=function(e){var t=new A.Builder;return t.pipeline.add(A.trimmer,A.stopWordFilter,A.stemmer),t.searchPipeline.add(A.stemmer),e.call(t,t),t.build()};A.version="2.3.9",A.utils={},A.utils.warn=(t=this,function(e){t.console&&console.warn&&console.warn(e)}),A.utils.asString=function(e){return null==e?"":e.toString()},A.utils.clone=function(e){if(null==e)return e;for(var t=Object.create(null),n=Object.keys(e),i=0;i<n.length;i++){var r=n[i],s=e[r];if(Array.isArray(s)){t[r]=s.slice();continue}if("string"==typeof s||"number"==typeof s||"boolean"==typeof s){t[r]=s;continue}throw TypeError("clone is not deep and does not support nested objects")}return t},A.FieldRef=function(e,t,n){this.docRef=e,this.fieldName=t,this._stringValue=n},A.FieldRef.joiner="/",A.FieldRef.fromString=function(e){var t=e.indexOf(A.FieldRef.joiner);if(-1===t)throw"malformed field ref string";var n=e.slice(0,t),i=e.slice(t+1);return new A.FieldRef(i,n,e)},A.FieldRef.prototype.toString=function(){return void 0==this._stringValue&&(this._stringValue=this.fieldName+A.FieldRef.joiner+this.docRef),this._stringValue},A.Set=function(e){if(this.elements=Object.create(null),e){this.length=e.length;for(var t=0;t<this.length;t++)this.elements[e[t]]=!0}else this.length=0},A.Set.complete={intersect:function(e){return e},union:function(){return this},contains:function(){return!0}},A.Set.empty={intersect:function(){return this},union:function(e){return e},contains:function(){return!1}},A.Set.prototype.contains=function(e){return!!this.elements[e]},A.Set.prototype.intersect=function(e){var t,n,i,r=[];if(e===A.Set.complete)return this;if(e===A.Set.empty)return e;this.length<e.length?(t=this,n=e):(t=e,n=this),i=Object.keys(t.elements);for(var s=0;s<i.length;s++){var o=i[s];o in n.elements&&r.push(o)}return new A.Set(r)},A.Set.prototype.union=function(e){return e===A.Set.complete?A.Set.complete:e===A.Set.empty?this:new A.Set(Object.keys(this.elements).concat(Object.keys(e.elements)))},A.idf=function(e,t){var n=0;for(var i in e)"_index"!=i&&(n+=Object.keys(e[i]).length);return Math.log(1+Math.abs((t-n+.5)/(n+.5)))},A.Token=function(e,t){this.str=e||"",this.metadata=t||{}},A.Token.prototype.toString=function(){return this.str},A.Token.prototype.update=function(e){return this.str=e(this.str,this.metadata),this},A.Token.prototype.clone=function(e){return e=e||function(e){return e},new A.Token(e(this.str,this.metadata),this.metadata)},A.tokenizer=function(e,t){if(null==e||void 0==e)return[];if(Array.isArray(e))return e.map(function(e){return new A.Token(A.utils.asString(e).toLowerCase(),A.utils.clone(t))});for(var n=e.toString().toLowerCase(),i=n.length,r=[],s=0,o=0;s<=i;s++){var a=n.charAt(s),u=s-o;if(a.match(A.tokenizer.separator)||s==i){if(u>0){var c=A.utils.clone(t)||{};c.position=[o,u],c.index=r.length,r.push(new A.Token(n.slice(o,s),c))}o=s+1}}return r},A.tokenizer.separator=/[\s\-]+/,A.Pipeline=function(){this._stack=[]},A.Pipeline.registeredFunctions=Object.create(null),A.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&A.utils.warn("Overwriting existing registered function: "+t),e.label=t,A.Pipeline.registeredFunctions[e.label]=e},A.Pipeline.warnIfFunctionNotRegistered=function(e){!(e.label&&e.label in this.registeredFunctions)&&A.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},A.Pipeline.load=function(e){var t=new A.Pipeline;return e.forEach(function(e){var n=A.Pipeline.registeredFunctions[e];if(n)t.add(n);else throw Error("Cannot load unregistered function: "+e)}),t},A.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){A.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},A.Pipeline.prototype.after=function(e,t){A.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw Error("Cannot find existingFn");n+=1,this._stack.splice(n,0,t)},A.Pipeline.prototype.before=function(e,t){A.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw Error("Cannot find existingFn");this._stack.splice(n,0,t)},A.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);if(-1!=t)this._stack.splice(t,1)},A.Pipeline.prototype.run=function(e){for(var t=this._stack.length,n=0;n<t;n++){for(var i=this._stack[n],r=[],s=0;s<e.length;s++){var o=i(e[s],s,e);if(null!=o&&""!==o){if(Array.isArray(o))for(var a=0;a<o.length;a++)r.push(o[a]);else r.push(o)}}e=r}return e},A.Pipeline.prototype.runString=function(e,t){var n=new A.Token(e,t);return this.run([n]).map(function(e){return e.toString()})},A.Pipeline.prototype.reset=function(){this._stack=[]},A.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return A.Pipeline.warnIfFunctionNotRegistered(e),e.label})},A.Vector=function(e){this._magnitude=0,this.elements=e||[]},A.Vector.prototype.positionForIndex=function(e){if(0==this.elements.length)return 0;for(var t=0,n=this.elements.length/2,i=n-t,r=Math.floor(i/2),s=this.elements[2*r];i>1&&(s<e&&(t=r),s>e&&(n=r),s!=e);){;i=n-t,r=t+Math.floor(i/2),s=this.elements[2*r]}return s==e||s>e?2*r:s<e?(r+1)*2:void 0},A.Vector.prototype.insert=function(e,t){this.upsert(e,t,function(){throw"duplicate index"})},A.Vector.prototype.upsert=function(e,t,n){this._magnitude=0;var i=this.positionForIndex(e);this.elements[i]==e?this.elements[i+1]=n(this.elements[i+1],t):this.elements.splice(i,0,e,t)},A.Vector.prototype.magnitude=function(){if(this._magnitude)return this._magnitude;for(var e=0,t=this.elements.length,n=1;n<t;n+=2){var i=this.elements[n];e+=i*i}return this._magnitude=Math.sqrt(e)},A.Vector.prototype.dot=function(e){for(var t=0,n=this.elements,i=e.elements,r=n.length,s=i.length,o=0,a=0,u=0,c=0;u<r&&c<s;)o=n[u],o<(a=i[c])?u+=2:o>a?c+=2:o==a&&(t+=n[u+1]*i[c+1],u+=2,c+=2);return t},A.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},A.Vector.prototype.toArray=function(){for(var e=Array(this.elements.length/2),t=1,n=0;t<this.elements.length;t+=2,n++)e[n]=this.elements[t];return e},A.Vector.prototype.toJSON=function(){return this.elements},A.stemmer=(n={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},i={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},a=RegExp("^("+(s="[^aeiou][^aeiouy]*")+")?"+(o=(r="[aeiouy]")+"[aeiou]*")+s),u=RegExp("^("+s+")?"+o+s+o+s),c=RegExp("^("+s+")?"+o+s+"("+o+")?$"),l=RegExp("^("+s+")?"+r),h=/^(.+?)(ss|i)es$/,p=/^(.+?)([^s])s$/,d=/^(.+?)eed$/,f=/^(.+?)(ed|ing)$/,g=/.$/,m=/(at|bl|iz)$/,v=RegExp("([^aeiouylsz])\\1$"),y=RegExp("^"+s+r+"[^aeiouwxy]$"),x=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,w=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,S=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,C=/^(.+?)(s|t)(ion)$/,E=/^(.+?)e$/,_=/ll$/,k=RegExp("^"+s+r+"[^aeiouwxy]$"),T=function(e){var t,r,s,o,T,O;if(e.length<3)return e;if("y"==(s=e.substr(0,1))&&(e=s.toUpperCase()+e.substr(1)),o=h,T=p,o.test(e)?e=e.replace(o,"$1$2"):T.test(e)&&(e=e.replace(T,"$1$2")),o=d,T=f,o.test(e)){var L=o.exec(e);(o=a).test(L[1])&&(o=g,e=e.replace(o,""))}else if(T.test(e)){var L=T.exec(e);if(t=L[1],(T=l).test(t)){e=t,T=m,O=v;T.test(e)?e+="e":O.test(e)?(o=g,e=e.replace(o,"")):y.test(e)&&(e+="e")}}if((o=x).test(e)){var L=o.exec(e);e=(t=L[1])+"i"}if((o=b).test(e)){var L=o.exec(e);t=L[1],r=L[2],(o=a).test(t)&&(e=t+n[r])}if((o=w).test(e)){var L=o.exec(e);t=L[1],r=L[2],(o=a).test(t)&&(e=t+i[r])}if(o=S,T=C,o.test(e)){var L=o.exec(e);t=L[1],(o=u).test(t)&&(e=t)}else if(T.test(e)){var L=T.exec(e);t=L[1]+L[2],(T=u).test(t)&&(e=t)}if((o=E).test(e)){var L=o.exec(e);t=L[1],o=u,T=c,O=k,(o.test(t)||T.test(t)&&!O.test(t))&&(e=t)}return o=_,T=u,o.test(e)&&T.test(e)&&(o=g,e=e.replace(o,"")),"y"==s&&(e=s.toLowerCase()+e.substr(1)),e},function(e){return e.update(T)}),A.Pipeline.registerFunction(A.stemmer,"stemmer"),A.generateStopWordFilter=function(e){var t=e.reduce(function(e,t){return e[t]=t,e},{});return function(e){if(e&&t[e.toString()]!==e.toString())return e}},A.stopWordFilter=A.generateStopWordFilter(["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"]),A.Pipeline.registerFunction(A.stopWordFilter,"stopWordFilter"),A.trimmer=function(e){return e.update(function(e){return e.replace(/^\W+/,"").replace(/\W+$/,"")})},A.Pipeline.registerFunction(A.trimmer,"trimmer"),A.TokenSet=function(){this.final=!1,this.edges={},this.id=A.TokenSet._nextId,A.TokenSet._nextId+=1},A.TokenSet._nextId=1,A.TokenSet.fromArray=function(e){for(var t=new A.TokenSet.Builder,n=0,i=e.length;n<i;n++)t.insert(e[n]);return t.finish(),t.root},A.TokenSet.fromClause=function(e){return"editDistance"in e?A.TokenSet.fromFuzzyString(e.term,e.editDistance):A.TokenSet.fromString(e.term)},A.TokenSet.fromFuzzyString=function(e,t){for(var n=new A.TokenSet,i=[{node:n,editsRemaining:t,str:e}];i.length;){var r=i.pop();if(r.str.length>0){var s,o=r.str.charAt(0);o in r.node.edges?s=r.node.edges[o]:(s=new A.TokenSet,r.node.edges[o]=s),1==r.str.length&&(s.final=!0),i.push({node:s,editsRemaining:r.editsRemaining,str:r.str.slice(1)})}if(0!=r.editsRemaining){if("*"in r.node.edges)var a=r.node.edges["*"];else{var a=new A.TokenSet;r.node.edges["*"]=a}if(0==r.str.length&&(a.final=!0),i.push({node:a,editsRemaining:r.editsRemaining-1,str:r.str}),r.str.length>1&&i.push({node:r.node,editsRemaining:r.editsRemaining-1,str:r.str.slice(1)}),1==r.str.length&&(r.node.final=!0),r.str.length>=1){if("*"in r.node.edges)var u=r.node.edges["*"];else{var u=new A.TokenSet;r.node.edges["*"]=u}1==r.str.length&&(u.final=!0),i.push({node:u,editsRemaining:r.editsRemaining-1,str:r.str.slice(1)})}if(r.str.length>1){var c,l=r.str.charAt(0),h=r.str.charAt(1);h in r.node.edges?c=r.node.edges[h]:(c=new A.TokenSet,r.node.edges[h]=c),1==r.str.length&&(c.final=!0),i.push({node:c,editsRemaining:r.editsRemaining-1,str:l+r.str.slice(2)})}}}return n},A.TokenSet.fromString=function(e){for(var t=new A.TokenSet,n=t,i=0,r=e.length;i<r;i++){var s=e[i],o=i==r-1;if("*"==s)t.edges[s]=t,t.final=o;else{var a=new A.TokenSet;a.final=o,t.edges[s]=a,t=a}}return n},A.TokenSet.prototype.toArray=function(){for(var e=[],t=[{prefix:"",node:this}];t.length;){var n=t.pop(),i=Object.keys(n.node.edges),r=i.length;n.node.final&&(n.prefix.charAt(0),e.push(n.prefix));for(var s=0;s<r;s++){var o=i[s];t.push({prefix:n.prefix.concat(o),node:n.node.edges[o]})}}return e},A.TokenSet.prototype.toString=function(){if(this._str)return this._str;for(var e=this.final?"1":"0",t=Object.keys(this.edges).sort(),n=t.length,i=0;i<n;i++){var r=t[i],s=this.edges[r];e=e+r+s.id}return e},A.TokenSet.prototype.intersect=function(e){for(var t=new A.TokenSet,n=void 0,i=[{qNode:e,output:t,node:this}];i.length;){for(var r=Object.keys((n=i.pop()).qNode.edges),s=r.length,o=Object.keys(n.node.edges),a=o.length,u=0;u<s;u++){for(var c=r[u],l=0;l<a;l++){var h=o[l];if(h==c||"*"==c){var p=n.node.edges[h],d=n.qNode.edges[c],f=p.final&&d.final,g=void 0;h in n.output.edges?(g=n.output.edges[h]).final=g.final||f:((g=new A.TokenSet).final=f,n.output.edges[h]=g),i.push({qNode:d,output:g,node:p})}}}}return t},A.TokenSet.Builder=function(){this.previousWord="",this.root=new A.TokenSet,this.uncheckedNodes=[],this.minimizedNodes={}},A.TokenSet.Builder.prototype.insert=function(e){var t,n=0;if(e<this.previousWord)throw Error("Out of order word insertion");for(var i=0;i<e.length&&i<this.previousWord.length&&e[i]==this.previousWord[i];i++)n++;this.minimize(n),t=0==this.uncheckedNodes.length?this.root:this.uncheckedNodes[this.uncheckedNodes.length-1].child;for(var i=n;i<e.length;i++){var r=new A.TokenSet,s=e[i];t.edges[s]=r,this.uncheckedNodes.push({parent:t,char:s,child:r}),t=r}t.final=!0,this.previousWord=e},A.TokenSet.Builder.prototype.finish=function(){this.minimize(0)},A.TokenSet.Builder.prototype.minimize=function(e){for(var t=this.uncheckedNodes.length-1;t>=e;t--){var n=this.uncheckedNodes[t],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}},A.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},A.Index.prototype.search=function(e){return this.query(function(t){new A.QueryParser(e,t).parse()})},A.Index.prototype.query=function(e){for(var t=new A.Query(this.fields),n=Object.create(null),i=Object.create(null),r=Object.create(null),s=Object.create(null),o=Object.create(null),a=0;a<this.fields.length;a++)i[this.fields[a]]=new A.Vector;e.call(t,t);for(var a=0;a<t.clauses.length;a++){var u=t.clauses[a],c=null,l=A.Set.empty;c=u.usePipeline?this.pipeline.runString(u.term,{fields:u.fields}):[u.term];for(var h=0;h<c.length;h++){var p=c[h];u.term=p;var d=A.TokenSet.fromClause(u),f=this.tokenSet.intersect(d).toArray();if(0===f.length&&u.presence===A.Query.presence.REQUIRED){for(var g=0;g<u.fields.length;g++){var m=u.fields[g];s[m]=A.Set.empty}break}for(var v=0;v<f.length;v++){for(var y=f[v],x=this.invertedIndex[y],b=x._index,g=0;g<u.fields.length;g++){var m=u.fields[g],w=x[m],S=Object.keys(w),C=y+"/"+m,E=new A.Set(S);if(u.presence==A.Query.presence.REQUIRED&&(l=l.union(E),void 0===s[m]&&(s[m]=A.Set.complete)),u.presence==A.Query.presence.PROHIBITED){void 0===o[m]&&(o[m]=A.Set.empty),o[m]=o[m].union(E);continue}if(i[m].upsert(b,u.boost,function(e,t){return e+t}),!r[C]){for(var _=0;_<S.length;_++){var k,T=S[_],O=new A.FieldRef(T,m),L=w[T];void 0===(k=n[O])?n[O]=new A.MatchData(y,m,L):k.add(y,m,L)}r[C]=!0}}}}if(u.presence===A.Query.presence.REQUIRED)for(var g=0;g<u.fields.length;g++){var m=u.fields[g];s[m]=s[m].intersect(l)}}for(var $=A.Set.complete,P=A.Set.empty,a=0;a<this.fields.length;a++){var m=this.fields[a];s[m]&&($=$.intersect(s[m])),o[m]&&(P=P.union(o[m]))}var I=Object.keys(n),Q=[],R=Object.create(null);if(t.isNegated()){I=Object.keys(this.fieldVectors);for(var a=0;a<I.length;a++){var O=I[a],N=A.FieldRef.fromString(O);n[O]=new A.MatchData}}for(var a=0;a<I.length;a++){var N=A.FieldRef.fromString(I[a]),D=N.docRef;if(!(!$.contains(D)||P.contains(D))){var F,j=this.fieldVectors[N],H=i[N.fieldName].similarity(j);if(void 0!==(F=R[D]))F.score+=H,F.matchData.combine(n[N]);else{var V={ref:D,score:H,matchData:n[N]};R[D]=V,Q.push(V)}}}return Q.sort(function(e,t){return t.score-e.score})},A.Index.prototype.toJSON=function(){var e=Object.keys(this.invertedIndex).sort().map(function(e){return[e,this.invertedIndex[e]]},this),t=Object.keys(this.fieldVectors).map(function(e){return[e,this.fieldVectors[e].toJSON()]},this);return{version:A.version,fields:this.fields,fieldVectors:t,invertedIndex:e,pipeline:this.pipeline.toJSON()}},A.Index.load=function(e){var t={},n={},i=e.fieldVectors,r=Object.create(null),s=e.invertedIndex,o=new A.TokenSet.Builder,a=A.Pipeline.load(e.pipeline);e.version!=A.version&&A.utils.warn("Version mismatch when loading serialised index. Current version of lunr '"+A.version+"' does not match serialized index '"+e.version+"'");for(var u=0;u<i.length;u++){var c=i[u],l=c[0],h=c[1];n[l]=new A.Vector(h)}for(var u=0;u<s.length;u++){var c=s[u],p=c[0],d=c[1];o.insert(p),r[p]=d}return o.finish(),t.fields=e.fields,t.fieldVectors=n,t.invertedIndex=r,t.tokenSet=o.root,t.pipeline=a,new A.Index(t)},A.Builder=function(){this._ref="id",this._fields=Object.create(null),this._documents=Object.create(null),this.invertedIndex=Object.create(null),this.fieldTermFrequencies={},this.fieldLengths={},this.tokenizer=A.tokenizer,this.pipeline=new A.Pipeline,this.searchPipeline=new A.Pipeline,this.documentCount=0,this._b=.75,this._k1=1.2,this.termIndex=0,this.metadataWhitelist=[]},A.Builder.prototype.ref=function(e){this._ref=e},A.Builder.prototype.field=function(e,t){if(/\//.test(e))throw RangeError("Field '"+e+"' contains illegal character '/'");this._fields[e]=t||{}},A.Builder.prototype.b=function(e){e<0?this._b=0:e>1?this._b=1:this._b=e},A.Builder.prototype.k1=function(e){this._k1=e},A.Builder.prototype.add=function(e,t){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=t||{},this.documentCount+=1;for(var r=0;r<i.length;r++){var s=i[r],o=this._fields[s].extractor,a=o?o(e):e[s],u=this.tokenizer(a,{fields:[s]}),c=this.pipeline.run(u),l=new A.FieldRef(n,s),h=Object.create(null);this.fieldTermFrequencies[l]=h,this.fieldLengths[l]=0,this.fieldLengths[l]+=c.length;for(var p=0;p<c.length;p++){var d=c[p];if(void 0==h[d]&&(h[d]=0),h[d]+=1,void 0==this.invertedIndex[d]){var f=Object.create(null);f._index=this.termIndex,this.termIndex+=1;for(var g=0;g<i.length;g++)f[i[g]]=Object.create(null);this.invertedIndex[d]=f}void 0==this.invertedIndex[d][s][n]&&(this.invertedIndex[d][s][n]=Object.create(null));for(var m=0;m<this.metadataWhitelist.length;m++){var v=this.metadataWhitelist[m],y=d.metadata[v];void 0==this.invertedIndex[d][s][n][v]&&(this.invertedIndex[d][s][n][v]=[]),this.invertedIndex[d][s][n][v].push(y)}}}},A.Builder.prototype.calculateAverageFieldLengths=function(){for(var e=Object.keys(this.fieldLengths),t=e.length,n={},i={},r=0;r<t;r++){var s=A.FieldRef.fromString(e[r]),o=s.fieldName;i[o]||(i[o]=0),i[o]+=1,n[o]||(n[o]=0),n[o]+=this.fieldLengths[s]}for(var a=Object.keys(this._fields),r=0;r<a.length;r++){var u=a[r];n[u]=n[u]/i[u]}this.averageFieldLength=n},A.Builder.prototype.createFieldVectors=function(){for(var e={},t=Object.keys(this.fieldTermFrequencies),n=t.length,i=Object.create(null),r=0;r<n;r++){for(var s=A.FieldRef.fromString(t[r]),o=s.fieldName,a=this.fieldLengths[s],u=new A.Vector,c=this.fieldTermFrequencies[s],l=Object.keys(c),h=l.length,p=this._fields[o].boost||1,d=this._documents[s.docRef].boost||1,f=0;f<h;f++){var g,m,v,y=l[f],x=c[y],b=this.invertedIndex[y]._index;void 0===i[y]?(g=A.idf(this.invertedIndex[y],this.documentCount),i[y]=g):g=i[y],v=Math.round(1e3*(m=g*((this._k1+1)*x)/(this._k1*(1-this._b+this._b*(a/this.averageFieldLength[o]))+x)*p*d))/1e3,u.insert(b,v)}e[s]=u}this.fieldVectors=e},A.Builder.prototype.createTokenSet=function(){this.tokenSet=A.TokenSet.fromArray(Object.keys(this.invertedIndex).sort())},A.Builder.prototype.build=function(){return this.calculateAverageFieldLengths(),this.createFieldVectors(),this.createTokenSet(),new A.Index({invertedIndex:this.invertedIndex,fieldVectors:this.fieldVectors,tokenSet:this.tokenSet,fields:Object.keys(this._fields),pipeline:this.searchPipeline})},A.Builder.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},A.MatchData=function(e,t,n){for(var i=Object.create(null),r=Object.keys(n||{}),s=0;s<r.length;s++){var o=r[s];i[o]=n[o].slice()}this.metadata=Object.create(null),void 0!==e&&(this.metadata[e]=Object.create(null),this.metadata[e][t]=i)},A.MatchData.prototype.combine=function(e){for(var t=Object.keys(e.metadata),n=0;n<t.length;n++){var i=t[n],r=Object.keys(e.metadata[i]);void 0==this.metadata[i]&&(this.metadata[i]=Object.create(null));for(var s=0;s<r.length;s++){var o=r[s],a=Object.keys(e.metadata[i][o]);void 0==this.metadata[i][o]&&(this.metadata[i][o]=Object.create(null));for(var u=0;u<a.length;u++){var c=a[u];void 0==this.metadata[i][o][c]?this.metadata[i][o][c]=e.metadata[i][o][c]:this.metadata[i][o][c]=this.metadata[i][o][c].concat(e.metadata[i][o][c])}}}},A.MatchData.prototype.add=function(e,t,n){if(!(e in this.metadata)){this.metadata[e]=Object.create(null),this.metadata[e][t]=n;return}if(!(t in this.metadata[e])){this.metadata[e][t]=n;return}for(var i=Object.keys(n),r=0;r<i.length;r++){var s=i[r];s in this.metadata[e][t]?this.metadata[e][t][s]=this.metadata[e][t][s].concat(n[s]):this.metadata[e][t][s]=n[s]}},A.Query=function(e){this.clauses=[],this.allFields=e},A.Query.wildcard=new String("*"),A.Query.wildcard.NONE=0,A.Query.wildcard.LEADING=1,A.Query.wildcard.TRAILING=2,A.Query.presence={OPTIONAL:1,REQUIRED:2,PROHIBITED:3},A.Query.prototype.clause=function(e){return!("fields"in e)&&(e.fields=this.allFields),!("boost"in e)&&(e.boost=1),!("usePipeline"in e)&&(e.usePipeline=!0),!("wildcard"in e)&&(e.wildcard=A.Query.wildcard.NONE),e.wildcard&A.Query.wildcard.LEADING&&e.term.charAt(0)!=A.Query.wildcard&&(e.term="*"+e.term),e.wildcard&A.Query.wildcard.TRAILING&&e.term.slice(-1)!=A.Query.wildcard&&(e.term=""+e.term+"*"),!("presence"in e)&&(e.presence=A.Query.presence.OPTIONAL),this.clauses.push(e),this},A.Query.prototype.isNegated=function(){for(var e=0;e<this.clauses.length;e++)if(this.clauses[e].presence!=A.Query.presence.PROHIBITED)return!1;return!0},A.Query.prototype.term=function(e,t){if(Array.isArray(e))return e.forEach(function(e){this.term(e,A.utils.clone(t))},this),this;var n=t||{};return n.term=e.toString(),this.clause(n),this},A.QueryParseError=function(e,t,n){this.name="QueryParseError",this.message=e,this.start=t,this.end=n},A.QueryParseError.prototype=Error(),A.QueryLexer=function(e){this.lexemes=[],this.str=e,this.length=e.length,this.pos=0,this.start=0,this.escapeCharPositions=[]},A.QueryLexer.prototype.run=function(){for(var e=A.QueryLexer.lexText;e;)e=e(this)},A.QueryLexer.prototype.sliceString=function(){for(var e=[],t=this.start,n=this.pos,i=0;i<this.escapeCharPositions.length;i++)n=this.escapeCharPositions[i],e.push(this.str.slice(t,n)),t=n+1;return e.push(this.str.slice(t,this.pos)),this.escapeCharPositions.length=0,e.join("")},A.QueryLexer.prototype.emit=function(e){this.lexemes.push({type:e,str:this.sliceString(),start:this.start,end:this.pos}),this.start=this.pos},A.QueryLexer.prototype.escapeCharacter=function(){this.escapeCharPositions.push(this.pos-1),this.pos+=1},A.QueryLexer.prototype.next=function(){if(this.pos>=this.length)return A.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},A.QueryLexer.prototype.width=function(){return this.pos-this.start},A.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},A.QueryLexer.prototype.backup=function(){this.pos-=1},A.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do t=(e=this.next()).charCodeAt(0);while(t>47&&t<58);e!=A.QueryLexer.EOS&&this.backup()},A.QueryLexer.prototype.more=function(){return this.pos<this.length},A.QueryLexer.EOS="EOS",A.QueryLexer.FIELD="FIELD",A.QueryLexer.TERM="TERM",A.QueryLexer.EDIT_DISTANCE="EDIT_DISTANCE",A.QueryLexer.BOOST="BOOST",A.QueryLexer.PRESENCE="PRESENCE",A.QueryLexer.lexField=function(e){return e.backup(),e.emit(A.QueryLexer.FIELD),e.ignore(),A.QueryLexer.lexText},A.QueryLexer.lexTerm=function(e){if(e.width()>1&&(e.backup(),e.emit(A.QueryLexer.TERM)),e.ignore(),e.more())return A.QueryLexer.lexText},A.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(A.QueryLexer.EDIT_DISTANCE),A.QueryLexer.lexText},A.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(A.QueryLexer.BOOST),A.QueryLexer.lexText},A.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(A.QueryLexer.TERM)},A.QueryLexer.termSeparator=A.tokenizer.separator,A.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==A.QueryLexer.EOS)return A.QueryLexer.lexEOS;if(92==t.charCodeAt(0)){e.escapeCharacter();continue}if(":"==t)return A.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(A.QueryLexer.TERM),A.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(A.QueryLexer.TERM),A.QueryLexer.lexBoost;if("+"==t&&1===e.width()||"-"==t&&1===e.width())return e.emit(A.QueryLexer.PRESENCE),A.QueryLexer.lexText;if(t.match(A.QueryLexer.termSeparator))return A.QueryLexer.lexTerm}},A.QueryParser=function(e,t){this.lexer=new A.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},A.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=A.QueryParser.parseClause;e;)e=e(this);return this.query},A.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},A.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},A.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},A.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(void 0!=t)switch(t.type){case A.QueryLexer.PRESENCE:return A.QueryParser.parsePresence;case A.QueryLexer.FIELD:return A.QueryParser.parseField;case A.QueryLexer.TERM:return A.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(n+=" with value '"+t.str+"'"),new A.QueryParseError(n,t.start,t.end)}},A.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(void 0!=t){switch(t.str){case"-":e.currentClause.presence=A.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=A.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+t.str+"'";throw new A.QueryParseError(n,t.start,t.end)}var i=e.peekLexeme();if(void 0==i){var n="expecting term or field, found nothing";throw new A.QueryParseError(n,t.start,t.end)}switch(i.type){case A.QueryLexer.FIELD:return A.QueryParser.parseField;case A.QueryLexer.TERM:return A.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new A.QueryParseError(n,i.start,i.end)}}},A.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(void 0!=t){if(-1==e.query.allFields.indexOf(t.str)){var n=e.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),i="unrecognised field '"+t.str+"', possible fields: "+n;throw new A.QueryParseError(i,t.start,t.end)}e.currentClause.fields=[t.str];var r=e.peekLexeme();if(void 0==r){var i="expecting term, found nothing";throw new A.QueryParseError(i,t.start,t.end)}if(r.type===A.QueryLexer.TERM)return A.QueryParser.parseTerm;var i="expecting term, found '"+r.type+"'";throw new A.QueryParseError(i,r.start,r.end)}},A.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(void 0!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(void 0==n){e.nextClause();return}switch(n.type){case A.QueryLexer.TERM:return e.nextClause(),A.QueryParser.parseTerm;case A.QueryLexer.FIELD:return e.nextClause(),A.QueryParser.parseField;case A.QueryLexer.EDIT_DISTANCE:return A.QueryParser.parseEditDistance;case A.QueryLexer.BOOST:return A.QueryParser.parseBoost;case A.QueryLexer.PRESENCE:return e.nextClause(),A.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new A.QueryParseError(i,n.start,n.end)}}},A.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(void 0!=t){var n=parseInt(t.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new A.QueryParseError(i,t.start,t.end)}e.currentClause.editDistance=n;var r=e.peekLexeme();if(void 0==r){e.nextClause();return}switch(r.type){case A.QueryLexer.TERM:return e.nextClause(),A.QueryParser.parseTerm;case A.QueryLexer.FIELD:return e.nextClause(),A.QueryParser.parseField;case A.QueryLexer.EDIT_DISTANCE:return A.QueryParser.parseEditDistance;case A.QueryLexer.BOOST:return A.QueryParser.parseBoost;case A.QueryLexer.PRESENCE:return e.nextClause(),A.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new A.QueryParseError(i,r.start,r.end)}}},A.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(void 0!=t){var n=parseInt(t.str,10);if(isNaN(n)){var i="boost must be numeric";throw new A.QueryParseError(i,t.start,t.end)}e.currentClause.boost=n;var r=e.peekLexeme();if(void 0==r){e.nextClause();return}switch(r.type){case A.QueryLexer.TERM:return e.nextClause(),A.QueryParser.parseTerm;case A.QueryLexer.FIELD:return e.nextClause(),A.QueryParser.parseField;case A.QueryLexer.EDIT_DISTANCE:return A.QueryParser.parseEditDistance;case A.QueryLexer.BOOST:return A.QueryParser.parseBoost;case A.QueryLexer.PRESENCE:return e.nextClause(),A.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new A.QueryParseError(i,r.start,r.end)}}},O=0,L=function(){return A},"function"==typeof define&&define.amd?define(L):e.exports=L()}()},5322:function(e,t,n){"use strict";n.r(t),n.d(t,{default:()=>v});var i=n("5485"),r=n.n(i),s=n("4802");s.Z.tokenizer.separator=/[\s\-/]+/;let o=class e{constructor(e,t,n="/",i){this.searchDocs=e,this.lunrIndex=s.Z.Index.load(t),this.baseUrl=n,this.maxHits=i}getLunrResult(e){return this.lunrIndex.query(function(t){let n=s.Z.tokenizer(e);t.term(n,{boost:10}),t.term(n,{wildcard:s.Z.Query.wildcard.TRAILING})})}getHit(e,t,n){return{hierarchy:{lvl0:e.pageTitle||e.title,lvl1:0===e.type?null:e.title},url:e.url,version:e.version,_snippetResult:n?{content:{value:n,matchLevel:"full"}}:null,_highlightResult:{hierarchy:{lvl0:{value:0===e.type?t||e.title:e.pageTitle},lvl1:0===e.type?null:{value:t||e.title}}}}}getTitleHit(e,t,n){let i=t[0],r=t[0]+n,s=e.title.substring(0,i)+'<span class="algolia-docsearch-suggestion--highlight">'+e.title.substring(i,r)+"</span>"+e.title.substring(r,e.title.length);return this.getHit(e,s)}getKeywordHit(e,t,n){let i=t[0],r=t[0]+n,s=e.title+"<br /><i>Keywords: "+e.keywords.substring(0,i)+'<span class="algolia-docsearch-suggestion--highlight">'+e.keywords.substring(i,r)+"</span>"+e.keywords.substring(r,e.keywords.length)+"</i>";return this.getHit(e,s)}getContentHit(e,t){let n=t[0],i=t[0]+t[1],r=n,s=i,o=!0,a=!0;for(let t=0;t<3;t++){let t=e.content.lastIndexOf(" ",r-2),n=e.content.lastIndexOf(".",r-2);if(n>0&&n>t){r=n+1,o=!1;break}if(t<0){r=0,o=!1;break}r=t+1}for(let t=0;t<10;t++){let t=e.content.indexOf(" ",s+1),n=e.content.indexOf(".",s+1);if(n>0&&n<t){s=n,a=!1;break}if(t<0){s=e.content.length,a=!1;break}s=t}let u=e.content.substring(r,n);return o&&(u="... "+u),u+='<span class="algolia-docsearch-suggestion--highlight">'+e.content.substring(n,i)+"</span>",u+=e.content.substring(i,s),a&&(u+=" ..."),this.getHit(e,null,u)}search(e){return new Promise((t,n)=>{let i=this.getLunrResult(e),r=[];i.length>this.maxHits&&(i.length=this.maxHits),this.titleHitsRes=[],this.contentHitsRes=[],i.forEach(t=>{let n=this.searchDocs[t.ref],{metadata:i}=t.matchData;for(let s in i)if(i[s].title){if(!this.titleHitsRes.includes(t.ref)){let o=i[s].title.position[0];r.push(this.getTitleHit(n,o,e.length)),this.titleHitsRes.push(t.ref)}}else if(i[s].content){let e=i[s].content.position[0];r.push(this.getContentHit(n,e))}else if(i[s].keywords){let o=i[s].keywords.position[0];r.push(this.getKeywordHit(n,o,e.length)),this.titleHitsRes.push(t.ref)}}),r.length>this.maxHits&&(r.length=this.maxHits),t(r)})}};var a=n("1639"),u=n.n(a);let c="algolia-docsearch",l=`${c}-suggestion`,h=`${c}-footer`,p={suggestion:` + <a class="${l} + {{#isCategoryHeader}}${l}__main{{/isCategoryHeader}} + {{#isSubCategoryHeader}}${l}__secondary{{/isSubCategoryHeader}} + " + aria-label="Link to the result" + href="{{{url}}}" + > + <div class="${l}--category-header"> + <span class="${l}--category-header-lvl0">{{{category}}}</span> + </div> + <div class="${l}--wrapper"> + <div class="${l}--subcategory-column"> + <span class="${l}--subcategory-column-text">{{{subcategory}}}</span> + </div> + {{#isTextOrSubcategoryNonEmpty}} + <div class="${l}--content"> + <div class="${l}--subcategory-inline">{{{subcategory}}}</div> + <div class="${l}--title">{{{title}}}</div> + {{#text}}<div class="${l}--text">{{{text}}}</div>{{/text}} + {{#version}}<div class="${l}--version">{{version}}</div>{{/version}} + </div> + {{/isTextOrSubcategoryNonEmpty}} + </div> + </a> + `,suggestionSimple:` + <div class="${l} + {{#isCategoryHeader}}${l}__main{{/isCategoryHeader}} + {{#isSubCategoryHeader}}${l}__secondary{{/isSubCategoryHeader}} + suggestion-layout-simple + "> + <div class="${l}--category-header"> + {{^isLvl0}} + <span class="${l}--category-header-lvl0 ${l}--category-header-item">{{{category}}}</span> + {{^isLvl1}} + {{^isLvl1EmptyOrDuplicate}} + <span class="${l}--category-header-lvl1 ${l}--category-header-item"> + {{{subcategory}}} + </span> + {{/isLvl1EmptyOrDuplicate}} + {{/isLvl1}} + {{/isLvl0}} + <div class="${l}--title ${l}--category-header-item"> + {{#isLvl2}} + {{{title}}} + {{/isLvl2}} + {{#isLvl1}} + {{{subcategory}}} + {{/isLvl1}} + {{#isLvl0}} + {{{category}}} + {{/isLvl0}} + </div> + </div> + <div class="${l}--wrapper"> + {{#text}} + <div class="${l}--content"> + <div class="${l}--text">{{{text}}}</div> + </div> + {{/text}} + </div> + </div> + `,footer:` + <div class="${h}"> + </div> + `,empty:` + <div class="${l}"> + <div class="${l}--wrapper"> + <div class="${l}--content ${l}--no-results"> + <div class="${l}--title"> + <div class="${l}--text"> + No results found for query <b>"{{query}}"</b> + </div> + </div> + </div> + </div> + </div> + `,searchBox:` + <form novalidate="novalidate" onsubmit="return false;" class="searchbox"> + <div role="search" class="searchbox__wrapper"> + <input id="docsearch" type="search" name="search" placeholder="Search the docs" autocomplete="off" required="required" class="searchbox__input"/> + <button type="submit" title="Submit your search query." class="searchbox__submit" > + <svg width=12 height=12 role="img" aria-label="Search"> + <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-search-13"></use> + </svg> + </button> + <button type="reset" title="Clear the search query." class="searchbox__reset hide"> + <svg width=12 height=12 role="img" aria-label="Reset"> + <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-clear-3"></use> + </svg> + </button> + </div> +</form> + +<div class="svg-icons" style="height: 0; width: 0; position: absolute; visibility: hidden"> + <svg xmlns="http://www.w3.org/2000/svg"> + <symbol id="sbx-icon-clear-3" viewBox="0 0 40 40"><path d="M16.228 20L1.886 5.657 0 3.772 3.772 0l1.885 1.886L20 16.228 34.343 1.886 36.228 0 40 3.772l-1.886 1.885L23.772 20l14.342 14.343L40 36.228 36.228 40l-1.885-1.886L20 23.772 5.657 38.114 3.772 40 0 36.228l1.886-1.885L16.228 20z" fill-rule="evenodd"></symbol> + <symbol id="sbx-icon-search-13" viewBox="0 0 40 40"><path d="M26.806 29.012a16.312 16.312 0 0 1-10.427 3.746C7.332 32.758 0 25.425 0 16.378 0 7.334 7.333 0 16.38 0c9.045 0 16.378 7.333 16.378 16.38 0 3.96-1.406 7.593-3.746 10.426L39.547 37.34c.607.608.61 1.59-.004 2.203a1.56 1.56 0 0 1-2.202.004L26.807 29.012zm-10.427.627c7.322 0 13.26-5.938 13.26-13.26 0-7.324-5.938-13.26-13.26-13.26-7.324 0-13.26 5.936-13.26 13.26 0 7.322 5.936 13.26 13.26 13.26z" fill-rule="evenodd"></symbol> + </svg> +</div> + `};var d=n("7939"),f=n.n(d);let g={mergeKeyWithParent(e,t){if(void 0===e[t]||"object"!=typeof e[t])return e;let n=f().extend({},e,e[t]);return delete n[t],n},groupBy(e,t){let n={};return f().each(e,(e,i)=>{if(void 0===i[t])throw Error(`[groupBy]: Object has no key ${t}`);let r=i[t];"string"==typeof r&&(r=r.toLowerCase()),!Object.prototype.hasOwnProperty.call(n,r)&&(n[r]=[]),n[r].push(i)}),n},values:e=>Object.keys(e).map(t=>e[t]),flatten(e){let t=[];return e.forEach(e=>{if(!Array.isArray(e)){t.push(e);return}e.forEach(e=>{t.push(e)})}),t},flattenAndFlagFirst(e,t){let n=this.values(e).map(e=>e.map((e,n)=>(e[t]=0===n,e)));return this.flatten(n)},compact(e){let t=[];return e.forEach(e=>{if(!!e)t.push(e)}),t},getHighlightedValue:(e,t)=>e._highlightResult&&e._highlightResult.hierarchy_camel&&e._highlightResult.hierarchy_camel[t]&&e._highlightResult.hierarchy_camel[t].matchLevel&&"none"!==e._highlightResult.hierarchy_camel[t].matchLevel&&e._highlightResult.hierarchy_camel[t].value?e._highlightResult.hierarchy_camel[t].value:e._highlightResult&&e._highlightResult&&e._highlightResult[t]&&e._highlightResult[t].value?e._highlightResult[t].value:e[t],getSnippetedValue(e,t){if(!e._snippetResult||!e._snippetResult[t]||!e._snippetResult[t].value)return e[t];let n=e._snippetResult[t].value;return n[0]!==n[0].toUpperCase()&&(n=`\u{2026}${n}`),-1===[".","!","?"].indexOf(n[n.length-1])&&(n=`${n}\u{2026}`),n},deepClone:e=>JSON.parse(JSON.stringify(e))};class m{constructor({searchDocs:e,searchIndex:t,inputSelector:n,debug:i=!1,baseUrl:r="/",queryDataCallback:s=null,autocompleteOptions:a={debug:!1,hint:!1,autoselect:!0},transformData:c=!1,queryHook:l=!1,handleSelected:h=!1,enhancedSearchInput:d=!1,layout:g="column",maxHits:v=5}){this.input=m.getInputFromSelector(n),this.queryDataCallback=s||null;let y=!!a&&!!a.debug&&a.debug;a.debug=i||y,this.autocompleteOptions=a,this.autocompleteOptions.cssClasses=this.autocompleteOptions.cssClasses||{},this.autocompleteOptions.cssClasses.prefix=this.autocompleteOptions.cssClasses.prefix||"ds";let x=this.input&&"function"==typeof this.input.attr&&this.input.attr("aria-label");this.autocompleteOptions.ariaLabel=this.autocompleteOptions.ariaLabel||x||"search input",this.isSimpleLayout="simple"===g,this.client=new o(e,t,r,v),d&&(this.input=m.injectSearchBox(this.input)),this.autocomplete=u()(this.input,a,[{source:this.getAutocompleteSource(c,l),templates:{suggestion:m.getSuggestionTemplate(this.isSimpleLayout),footer:p.footer,empty:m.getEmptyTemplate()}}]);this.handleSelected=h||this.handleSelected,h&&f()(".algolia-autocomplete").on("click",".ds-suggestions a",e=>{e.preventDefault()}),this.autocomplete.on("autocomplete:selected",this.handleSelected.bind(null,this.autocomplete.autocomplete)),this.autocomplete.on("autocomplete:shown",this.handleShown.bind(null,this.input)),d&&m.bindSearchBoxEvent(),document.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&"k"==e.key&&(this.input.focus(),e.preventDefault())})}static injectSearchBox(e){e.before(p.searchBox);let t=e.prev().prev().find("input");return e.remove(),t}static bindSearchBoxEvent(){f()('.searchbox [type="reset"]').on("click",function(){f()("input#docsearch").focus(),f()(this).addClass("hide"),u().autocomplete.setVal("")}),f()("input#docsearch").on("keyup",()=>{let e=document.querySelector("input#docsearch"),t=document.querySelector('.searchbox [type="reset"]');t.className="searchbox__reset",0===e.value.length&&(t.className+=" hide")})}static getInputFromSelector(e){let t=f()(e).filter("input");return t.length?f()(t[0]):null}getAutocompleteSource(e,t){return(n,i)=>{t&&(n=t(n)||n),this.client.search(n).then(t=>{this.queryDataCallback&&"function"==typeof this.queryDataCallback&&this.queryDataCallback(t),e&&(t=e(t)||t),i(m.formatHits(t))})}}static formatHits(e){let t=g.deepClone(e).map(e=>(e._highlightResult&&(e._highlightResult=g.mergeKeyWithParent(e._highlightResult,"hierarchy")),g.mergeKeyWithParent(e,"hierarchy"))),n=g.groupBy(t,"lvl0");return f().each(n,(e,t)=>{let i=g.groupBy(t,"lvl1"),r=g.flattenAndFlagFirst(i,"isSubCategoryHeader");n[e]=r}),(n=g.flattenAndFlagFirst(n,"isCategoryHeader")).map(e=>{let t=m.formatURL(e),n=g.getHighlightedValue(e,"lvl0"),i=g.getHighlightedValue(e,"lvl1")||n,r=g.compact([g.getHighlightedValue(e,"lvl2")||i,g.getHighlightedValue(e,"lvl3"),g.getHighlightedValue(e,"lvl4"),g.getHighlightedValue(e,"lvl5"),g.getHighlightedValue(e,"lvl6")]).join('<span class="aa-suggestion-title-separator" aria-hidden="true"> \u203A </span>'),s=g.getSnippetedValue(e,"content"),o=i&&""!==i||r&&""!==r,a=!i||""===i||i===n,u=r&&""!==r&&r!==i,c=!u&&i&&""!==i&&i!==n,l=e.version;return{isLvl0:!c&&!u,isLvl1:c,isLvl2:u,isLvl1EmptyOrDuplicate:a,isCategoryHeader:e.isCategoryHeader,isSubCategoryHeader:e.isSubCategoryHeader,isTextOrSubcategoryNonEmpty:o,category:n,subcategory:i,title:r,text:s,url:t,version:l}})}static formatURL(e){let{url:t,anchor:n}=e;if(t){if(-1!==t.indexOf("#"));else if(n)return`${e.url}#${e.anchor}`;return t}return n?`#${e.anchor}`:(console.warn("no anchor nor url for : ",JSON.stringify(e)),null)}static getEmptyTemplate(){return e=>r().compile(p.empty).render(e)}static getSuggestionTemplate(e){let t=e?p.suggestionSimple:p.suggestion,n=r().compile(t);return e=>n.render(e)}handleSelected(e,t,n,i){let r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};if("click"!==r.selectionMethod)e.setVal(""),window.location.assign(n.url)}handleShown(e){let t=e.offset().left+e.width()/2,n=f()(document).width()/2;isNaN(n)&&(n=900);let i=t-n>=0?"algolia-autocomplete-right":"algolia-autocomplete-left",r=t-n<0?"algolia-autocomplete-right":"algolia-autocomplete-left",s=f()(".algolia-autocomplete");!s.hasClass(i)&&s.addClass(i),s.hasClass(r)&&s.removeClass(r)}}let v=m}}]); \ No newline at end of file diff --git a/assets/js/47f41a37.e28a1f98.js b/assets/js/47f41a37.e28a1f98.js new file mode 100644 index 0000000..a8a7282 --- /dev/null +++ b/assets/js/47f41a37.e28a1f98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7073"],{2134:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return l},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return c}});var o=n(2231),i=n(5893),r=n(65);let a={slug:"2015/12/testing-cramer",title:"Testing Cramer",date:new Date("2015-12-26T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},c=[];function h(e){let t={p:"p",...(0,r.a)(),...e.components};return(0,i.jsx)(t.p,{children:"Pursuant to attending a graduate school studying Financial Engineering, I've been a fan of the [Mad Money][1] TV show featuring the bombastic Jim Cramer. One of the things that he's said is that you shouldn't use the futures to predict where the stock market is going to go. But he says it often enough, I've begun to wonder - who is he trying to convince?"})}function l(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return a}});var o=n(7294);let i={},r=o.createContext(i);function a(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:t},e.children)}},2231:function(e){e.exports=JSON.parse('{"permalink":"/2015/12/testing-cramer","source":"@site/blog/2015-12-26-testing-cramer/index.mdx","title":"Testing Cramer","description":"Pursuant to attending a graduate school studying Financial Engineering, I\'ve been a fan of the Mad Money TV show featuring the bombastic Jim Cramer. One of the things that he\'s said is that you shouldn\'t use the futures to predict where the stock market is going to go. But he says it often enough, I\'ve begun to wonder - who is he trying to convince?","date":"2015-12-26T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/12/testing-cramer","title":"Testing Cramer","date":"2015-12-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"},"nextItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}}')}}]); \ No newline at end of file diff --git a/assets/js/4c2b0735.497a037f.js b/assets/js/4c2b0735.497a037f.js new file mode 100644 index 0000000..ef09485 --- /dev/null +++ b/assets/js/4c2b0735.497a037f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4718"],{5960:function(e,n,t){t.r(n),t.d(n,{assets:function(){return d},contentTitle:function(){return o},default:function(){return h},frontMatter:function(){return i},metadata:function(){return a},toc:function(){return l}});var a=t(173),r=t(5893),s=t(65);let i={slug:"2016/06/event-studies-and-earnings-releases",title:"Event studies and earnings releases",date:new Date("2016-06-08T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,d={authorsImageUrls:[void 0]},l=[{value:"The Market Just Knew",id:"the-market-just-knew",level:2},{value:"Formulating the Question",id:"formulating-the-question",level:2},{value:"Event Studies",id:"event-studies",level:2},{value:"Event Type 1: Trending down over the past N days",id:"event-type-1-trending-down-over-the-past-n-days",level:2},{value:"Event Type 2: Trending up for N days",id:"event-type-2-trending-up-for-n-days",level:2},{value:"Conclusion and Summary",id:"conclusion-and-summary",level:2}];function c(e){let n={code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components},{Details:a}=n;return!a&&function(e,n){throw Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Or, being suspicious of market insiders."}),"\n",(0,r.jsx)(n.h2,{id:"the-market-just-knew",children:"The Market Just Knew"}),"\n",(0,r.jsx)(n.p,{children:"I recently saw two examples of stock charts that have kept me thinking for a while. And now that the semester is complete, I finally have enough time to really look at them and give them the treatment they deserve. The first is good old Apple:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"from secrets import QUANDL_KEY\nimport matplotlib.pyplot as plt\nfrom matplotlib.dates import date2num\nfrom matplotlib.finance import candlestick_ohlc\nfrom matplotlib.dates import DateFormatter, WeekdayLocator,\\\n DayLocator, MONDAY\nimport quandl\nfrom datetime import datetime\nimport pandas as pd\n%matplotlib inline\n\ndef fetch_ticker(ticker, start, end):\n # Quandl is currently giving me issues with returning\n # the entire dataset and not slicing server-side.\n # So instead, we'll do it client-side!\n q_format = '%Y-%m-%d'\n ticker_data = quandl.get('YAHOO/' + ticker,\n start_date=start.strftime(q_format),\n end_date=end.strftime(q_format),\n authtoken=QUANDL_KEY)\n return ticker_data\n\ndef ohlc_dataframe(data, ax=None):\n # Much of this code re-used from:\n # http://matplotlib.org/examples/pylab_examples/finance_demo.html\n if ax is None:\n f, ax = plt.subplots()\n \n vals = [(date2num(date), *(data.loc[date]))\n for date in data.index]\n candlestick_ohlc(ax, vals)\n \n mondays = WeekdayLocator(MONDAY)\n alldays = DayLocator()\n weekFormatter = DateFormatter('%b %d')\n ax.xaxis.set_major_locator(mondays)\n ax.xaxis.set_minor_locator(alldays)\n ax.xaxis.set_major_formatter(weekFormatter)\n return ax\n"})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"AAPL = fetch_ticker('AAPL', datetime(2016, 3, 1), datetime(2016, 5, 1))\nax = ohlc_dataframe(AAPL)\nplt.vlines(date2num(datetime(2016, 4, 26, 12)),\n ax.get_ylim()[0], ax.get_ylim()[1],\n color='b',\n label='Earnings Release')\nplt.legend(loc=3)\nplt.title(\"Apple Price 3/1/2016 - 5/1/2016\");\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(8409).Z+"",width:"372",height:"266"})}),"\n",(0,r.jsx)(n.p,{children:"The second chart is from Facebook:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"FB = fetch_ticker('FB', datetime(2016, 3, 1), datetime(2016, 5, 5))\nax = ohlc_dataframe(FB)\nplt.vlines(date2num(datetime(2016, 4, 27, 12)),\n ax.get_ylim()[0], ax.get_ylim()[1],\n color='b', label='Earnings Release')\nplt.title('Facebook Price 3/5/2016 - 5/5/2016')\nplt.legend(loc=2);\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(4400).Z+"",width:"374",height:"266"})}),"\n",(0,r.jsx)(n.p,{children:"These two charts demonstrate two very specific phonomena: how the market prepares for earnings releases. Let's look at those charts again, but with some extra information. As we're about the see, the market \"knew\" in advance that Apple was going to perform poorly. The market expected that Facebook was going to perform poorly, and instead shot the lights out. Let's see that trend in action:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"def plot_hilo(ax, start, end, data):\n ax.plot([date2num(start), date2num(end)],\n [data.loc[start]['High'], data.loc[end]['High']],\n color='b')\n ax.plot([date2num(start), date2num(end)],\n [data.loc[start]['Low'], data.loc[end]['Low']],\n color='b')\n\nf, axarr = plt.subplots(1, 2)\n\nax_aapl = axarr[0]\nax_fb = axarr[1]\n\n# Plot the AAPL trend up and down\nohlc_dataframe(AAPL, ax=ax_aapl)\nplot_hilo(ax_aapl, datetime(2016, 3, 1), datetime(2016, 4, 15), AAPL)\nplot_hilo(ax_aapl, datetime(2016, 4, 18), datetime(2016, 4, 26), AAPL)\nax_aapl.vlines(date2num(datetime(2016, 4, 26, 12)),\n ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],\n color='g', label='Earnings Release')\nax_aapl.legend(loc=2)\nax_aapl.set_title('AAPL Price History')\n\n# Plot the FB trend down and up\nohlc_dataframe(FB, ax=ax_fb)\nplot_hilo(ax_fb, datetime(2016, 3, 30), datetime(2016, 4, 27), FB)\nplot_hilo(ax_fb, datetime(2016, 4, 28), datetime(2016, 5, 5), FB)\nax_fb.vlines(date2num(datetime(2016, 4, 27, 12)),\n ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],\n color='g', label='Earnings Release')\nax_fb.legend(loc=2)\nax_fb.set_title('FB Price History')\n\nf.set_size_inches(18, 6)\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(8475).Z+"",width:"1041",height:"378"})}),"\n",(0,r.jsx)(n.p,{children:"As we can see above, the market broke a prevailing trend on Apple in order to go down, and ultimately predict the earnings release. For Facebook, the opposite happened. While the trend was down, the earnings were fantastic and the market corrected itself much higher."}),"\n",(0,r.jsx)(n.h2,{id:"formulating-the-question",children:"Formulating the Question"}),"\n",(0,r.jsx)(n.p,{children:"While these are two specific examples, there are plenty of other examples you could cite one way or another. Even if the preponderance of evidence shows that the market correctly predicts earnings releases, we need not accuse people of collusion; for a company like Apple with many suppliers we can generally forecast how Apple has done based on those same suppliers."}),"\n",(0,r.jsxs)(n.p,{children:["The question then, is this: ",(0,r.jsx)(n.strong,{children:"how well does the market predict the earnings releases?"})," It's an incredibly broad question that I want to disect in a couple of different ways:"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Given a stock that has been trending down over the past N days before an earnings release, how likely does it continue downward after the release?"}),"\n",(0,r.jsx)(n.li,{children:"Given a stock trending up, how likely does it continue up?"}),"\n",(0,r.jsx)(n.li,{children:"Is there a difference in accuracy between large- and small-cap stocks?"}),"\n",(0,r.jsx)(n.li,{children:"How often, and for how long, do markets trend before an earnings release?"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"I want to especially thank Alejandro Saltiel for helping me retrieve the data."})," He's great. And now for all of the interesting bits."]}),"\n",(0,r.jsx)(n.h2,{id:"event-studies",children:"Event Studies"}),"\n",(0,r.jsx)(n.p,{children:"Before we go too much further, I want to introduce the actual event study. Each chart intends to capture a lot of information and present an easy-to-understand pattern:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"import numpy as np\nimport pandas as pd\nfrom pandas.tseries.holiday import USFederalHolidayCalendar\nfrom pandas.tseries.offsets import CustomBusinessDay\nfrom datetime import datetime, timedelta\n\n# If you remove rules, it removes them from *all* calendars\n# To ensure we don't pop rules we don't want to, first make\n# sure to fully copy the object\ntrade_calendar = USFederalHolidayCalendar()\ntrade_calendar.rules.pop(6) # Remove Columbus day\ntrade_calendar.rules.pop(7) # Remove Veteran's day\nTradeDay = lambda days: CustomBusinessDay(days, calendar=trade_calendar)\n\ndef plot_study(array):\n # Given a 2-d array, we assume the event happens at index `lookback`,\n # and create all of our summary statistics from there.\n lookback = int((array.shape[1] - 1) / 2)\n norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)\n centered_data = array / norm_factor - 1\n lookforward = centered_data.shape[1] - lookback\n means = centered_data.mean(axis=0)\n lookforward_data = centered_data[:,lookforward:]\n std_dev = np.hstack([0, lookforward_data.std(axis=0)])\n maxes = lookforward_data.max(axis=0)\n mins = lookforward_data.min(axis=0)\n \n f, axarr = plt.subplots(1, 2)\n range_begin = -lookback\n range_end = lookforward\n axarr[0].plot(range(range_begin, range_end), means)\n axarr[1].plot(range(range_begin, range_end), means)\n axarr[0].fill_between(range(0, range_end),\n means[-lookforward:] + std_dev,\n means[-lookforward:] - std_dev,\n alpha=.5, label=\"$\\pm$ 1 s.d.\")\n axarr[1].fill_between(range(0, range_end),\n means[-lookforward:] + std_dev,\n means[-lookforward:] - std_dev,\n alpha=.5, label=\"$\\pm$ 1 s.d.\")\n \n max_err = maxes - means[-lookforward+1:]\n min_err = means[-lookforward+1:] - mins\n axarr[0].errorbar(range(1, range_end),\n means[-lookforward+1:],\n yerr=[min_err, max_err], label='Max & Min')\n axarr[0].legend(loc=2)\n axarr[1].legend(loc=2)\n \n axarr[0].set_xlim((-lookback-1, lookback+1))\n axarr[1].set_xlim((-lookback-1, lookback+1))\n \ndef plot_study_small(array):\n # Given a 2-d array, we assume the event happens at index `lookback`,\n # and create all of our summary statistics from there.\n lookback = int((array.shape[1] - 1) / 2)\n norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)\n centered_data = array / norm_factor - 1\n lookforward = centered_data.shape[1] - lookback\n means = centered_data.mean(axis=0)\n lookforward_data = centered_data[:,lookforward:]\n std_dev = np.hstack([0, lookforward_data.std(axis=0)])\n maxes = lookforward_data.max(axis=0)\n mins = lookforward_data.min(axis=0)\n \n range_begin = -lookback\n range_end = lookforward\n plt.plot(range(range_begin, range_end), means)\n plt.fill_between(range(0, range_end),\n means[-lookforward:] + std_dev,\n means[-lookforward:] - std_dev,\n alpha=.5, label=\"$\\pm$ 1 s.d.\")\n \n max_err = maxes - means[-lookforward+1:]\n min_err = means[-lookforward+1:] - mins\n plt.errorbar(range(1, range_end),\n means[-lookforward+1:],\n yerr=[min_err, max_err], label='Max & Min')\n plt.legend(loc=2)\n plt.xlim((-lookback-1, lookback+1))\n \ndef fetch_event_data(ticker, events, horizon=5):\n # Use horizon+1 to account for including the day of the event,\n # and half-open interval - that is, for a horizon of 5,\n # we should be including 11 events. Additionally, using the\n # CustomBusinessDay means we automatically handle issues if\n # for example a company reports Friday afternoon - the date\n # calculator will turn this into a \"Saturday\" release, but\n # we effectively shift that to Monday with the logic below.\n td_back = TradeDay(horizon+1)\n td_forward = TradeDay(horizon+1)\n \n start_date = min(events) - td_back\n end_date = max(events) + td_forward\n total_data = fetch_ticker(ticker, start_date, end_date)\n event_data = [total_data.ix[event-td_back:event+td_forward]\\\n [0:horizon*2+1]\\\n ['Adjusted Close']\n for event in events]\n return np.array(event_data)\n"})})]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# Generate a couple of random events\n\nevent_dates = [datetime(2016, 5, 27) - timedelta(days=1) - TradeDay(x*20) for x in range(1, 40)]\ndata = fetch_event_data('CELG', event_dates)\nplot_study_small(data)\nplt.legend(loc=3)\nplt.gcf().set_size_inches(12, 6);\n\n\nplt.annotate('Mean price for days leading up to each event',\n (-5, -.01), (-4.5, .025),\n arrowprops=dict(facecolor='black', shrink=0.05))\nplt.annotate('', (-.1, .005), (-.5, .02),\n arrowprops={'facecolor': 'black', 'shrink': .05})\nplt.annotate('$\\pm$ 1 std. dev. each day', (5, .055), (2.5, .085),\n arrowprops={'facecolor': 'black', 'shrink': .05})\nplt.annotate('Min/Max each day', (.9, -.07), (-1, -.1),\n arrowprops={'facecolor': 'black', 'shrink': .05});\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(7134).Z+"",width:"721",height:"368"})}),"\n",(0,r.jsx)(n.p,{children:"And as a quick textual explanation as well:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"The blue line represents the mean price for each day, represented as a percentage of the price on the '0-day'. For example, if we defined an 'event' as whenever the stock price dropped for three days, we would see a decreasing blue line to the left of the 0-day."}),"\n",(0,r.jsx)(n.li,{children:"The blue shaded area represents one standard deviation above and below the mean price for each day following an event. This is intended to give us an idea of what the stock price does in general following an event."}),"\n",(0,r.jsx)(n.li,{children:"The green bars are the minimum and maximum price for each day following an event. This instructs us as to how much it's possible for the stock to move."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"event-type-1-trending-down-over-the-past-n-days",children:"Event Type 1: Trending down over the past N days"}),"\n",(0,r.jsxs)(n.p,{children:["The first type of event I want to study is how stocks perform when they've been trending down over the past couple of days prior to a release. However, we need to clarify what exactly is meant by \"trending down.\" To do so, we'll use the following metric: ",(0,r.jsx)(n.strong,{children:"the midpoint between each day's opening and closing price goes down over a period of N days"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"It's probably helpful to have an example:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"f, axarr = plt.subplots(1, 2)\nf.set_size_inches(18, 6)\n\nFB_plot = axarr[0]\nohlc_dataframe(FB[datetime(2016, 4, 18):], FB_plot)\n\nFB_truncated = FB[datetime(2016, 4, 18):datetime(2016, 4, 27)]\nmidpoint = FB_truncated['Open']/2 + FB_truncated['Close']/2\nFB_plot.plot(FB_truncated.index, midpoint, label='Midpoint')\nFB_plot.vlines(date2num(datetime(2016, 4, 27, 12)),\n ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],\n color='g', label='Earnings Release')\nFB_plot.legend(loc=2)\nFB_plot.set_title('FB Midpoint Plot')\n\nAAPL_plot = axarr[1]\nohlc_dataframe(AAPL[datetime(2016, 4, 10):], AAPL_plot)\nAAPL_truncated = AAPL[datetime(2016, 4, 10):datetime(2016, 4, 26)]\nmidpoint = AAPL_truncated['Open']/2 + AAPL_truncated['Close']/2\nAAPL_plot.plot(AAPL_truncated.index, midpoint, label='Midpoint')\nAAPL_plot.vlines(date2num(datetime(2016, 4, 26, 12)),\n ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],\n color='g', label='Earnings Release')\nAAPL_plot.legend(loc=3)\nAAPL_plot.set_title('AAPL Midpoint Plot');\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(6403).Z+"",width:"1041",height:"378"})}),"\n",(0,r.jsx)(n.p,{children:"Given these charts, we can see that FB was trending down for the four days preceding the earnings release, and AAPL was trending down for a whopping 8 days (we don't count the peak day). This will define the methodology that we will use for the study."}),"\n",(0,r.jsx)(n.p,{children:"So what are the results? For a given horizon, how well does the market actually perform?"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# Read in the events for each stock;\n# The file was created using the first code block in the Appendix\nimport yaml\nfrom dateutil.parser import parse\nfrom progressbar import ProgressBar\n\ndata_str = open('earnings_dates.yaml', 'r').read()\n# Need to remove invalid lines\nfiltered = filter(lambda x: '{' not in x, data_str.split('\\n'))\nearnings_data = yaml.load('\\n'.join(filtered))\n\n# Convert our earnings data into a list of (ticker, date) pairs\n# to make it easy to work with.\n# This is horribly inefficient, but should get us what we need\nticker_dates = []\nfor ticker, date_list in earnings_data.items():\n for iso_str in date_list:\n ticker_dates.append((ticker, parse(iso_str)))\n\ndef does_trend_down(ticker, event, horizon):\n # Figure out if the `event` has a downtrend for\n # the `horizon` days preceding it\n # As an interpretation note: it is assumed that\n # the closing price of day `event` is the reference\n # point, and we want `horizon` days before that.\n # The price_data.hdf was created in the second appendix code block\n try:\n ticker_data = pd.read_hdf('price_data.hdf', ticker)\n data = ticker_data[event-TradeDay(horizon):event]\n midpoints = data['Open']/2 + data['Close']/2\n\n # Shift dates one forward into the future and subtract\n # Effectively: do we trend down over all days?\n elems = midpoints - midpoints.shift(1)\n return len(elems)-1 == len(elems.dropna()[elems <= 0])\n except KeyError:\n # If the stock doesn't exist, it doesn't qualify as trending down\n # Mostly this is here to make sure the entire analysis doesn't \n # blow up if there were issues in data retrieval\n return False\n\ndef study_trend(horizon, trend_function):\n five_day_events = np.zeros((1, horizon*2 + 1))\n invalid_events = []\n for ticker, event in ProgressBar()(ticker_dates):\n if trend_function(ticker, event, horizon):\n ticker_data = pd.read_hdf('price_data.hdf', ticker)\n event_data = ticker_data[event-TradeDay(horizon):event+TradeDay(horizon)]['Close']\n\n try:\n five_day_events = np.vstack([five_day_events, event_data])\n except ValueError:\n # Sometimes we don't get exactly the right number of values due to calendar\n # issues. I've fixed most everything I can, and the few issues that are left\n # I assume don't systemically bias the results (i.e. data could be missing\n # because it doesn't exist, etc.). After running through, ~1% of events get\n # discarded this way\n invalid_events.append((ticker, event))\n \n\n # Remove our initial zero row\n five_day_events = five_day_events[1:,:]\n plot_study(five_day_events)\n plt.gcf().suptitle('Action over {} days: {} events'\n .format(horizon,five_day_events.shape[0]))\n plt.gcf().set_size_inches(18, 6)\n \n# Start with a 5 day study\nstudy_trend(5, does_trend_down)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:21:38 Time: 0:21:38\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(2446).Z+"",width:"1050",height:"397"})}),"\n",(0,r.jsxs)(n.p,{children:["When a stock has been trending down for 5 days, once the earnings are announced it really doesn't move on average. However, the variability is ",(0,r.jsx)(n.em,{children:"incredible"}),". This implies two important things:"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"The market is just as often wrong about an earnings announcement before it happens as it is correct"}),"\n",(0,r.jsxs)(n.li,{children:["The incredible width of the min/max bars and standard deviation area tell us that the market reacts ",(0,r.jsx)(n.em,{children:"violently"})," after the earnings are released."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Let's repeat the same study, but over a time horizon of 8 days and 3 days. Presumably if a stock has been going down for 8 days at a time before the earnings, the market should be more accurate."}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# 8 day study next\nstudy_trend(8, does_trend_down)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:29 Time: 0:20:29\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(3243).Z+"",width:"1047",height:"397"})}),"\n",(0,r.jsx)(n.p,{children:"However, looking only at stocks that trended down for 8 days prior to a release, the same pattern emerges: on average, the stock doesn't move, but the market reaction is often incredibly violent."}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# 3 day study after that\nstudy_trend(3, does_trend_down)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:26 Time: 0:26:26\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(6810).Z+"",width:"1040",height:"397"})}),"\n",(0,r.jsx)(n.p,{children:"Finally, when we look at a 3-day horizon, we start getting some incredible outliers. Stocks have a potential to move over ~300% up, and the standard deviation width is again, incredible. The results for a 3-day horizon follow the same pattern we've seen in the 5- and 8-day horizons."}),"\n",(0,r.jsx)(n.h2,{id:"event-type-2-trending-up-for-n-days",children:"Event Type 2: Trending up for N days"}),"\n",(0,r.jsx)(n.p,{children:"We're now going to repeat the analysis, but do it for uptrends instead. That is, instead of looking at stocks that have been trending down over the past number of days, we focus only on stocks that have been trending up."}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"def does_trend_up(ticker, event, horizon):\n # Figure out if the `event` has an uptrend for\n # the `horizon` days preceding it\n # As an interpretation note: it is assumed that\n # the closing price of day `event` is the reference\n # point, and we want `horizon` days before that.\n # The price_data.hdf was created in the second appendix code block\n try:\n ticker_data = pd.read_hdf('price_data.hdf', ticker)\n data = ticker_data[event-TradeDay(horizon):event]\n midpoints = data['Open']/2 + data['Close']/2\n\n # Shift dates one forward into the future and subtract\n # Effectively: do we trend down over all days?\n elems = midpoints - midpoints.shift(1)\n return len(elems)-1 == len(elems.dropna()[elems >= 0])\n except KeyError:\n # If the stock doesn't exist, it doesn't qualify as trending down\n # Mostly this is here to make sure the entire analysis doesn't \n # blow up if there were issues in data retrieval\n return False\n\nstudy_trend(5, does_trend_up)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:22:51 Time: 0:22:51\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(7600).Z+"",width:"1040",height:"397"})}),"\n",(0,r.jsx)(n.p,{children:"The patterns here are very similar. With the exception of noting that stocks can go to nearly 400% after an earnings announcement (most likely this included a takeover announcement, etc.), we still see large min/max bars and wide standard deviation of returns."}),"\n",(0,r.jsx)(n.p,{children:"We'll repeat the pattern for stocks going up for both 8 and 3 days straight, but at this point, the results should be very predictable:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"study_trend(8, does_trend_up)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:51 Time: 0:20:51\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(6955).Z+"",width:"1047",height:"397"})}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"study_trend(3, does_trend_up)\n"})}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:56 Time: 0:26:56\n"})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"png",src:t(5968).Z+"",width:"1040",height:"397"})}),"\n",(0,r.jsx)(n.h2,{id:"conclusion-and-summary",children:"Conclusion and Summary"}),"\n",(0,r.jsxs)(n.p,{children:["I guess the most important thing to summarize with is this: ",(0,r.jsx)(n.strong,{children:"looking at the entire market, stock performance prior to an earnings release has no bearing on the stock's performance."})," Honestly: given the huge variability of returns after an earnings release, even when the stock has been trending for a long time, you're best off divesting before an earnings release and letting the market sort itself out."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"However"}),", there is a big caveat. These results are taken when we look at the entire market. So while we can say that the market as a whole knows nothing and just reacts violently, I want to take a closer look into this data. Does the market typically perform poorly on large-cap/high liquidity stocks? Do smaller companies have investors that know them better and can thus predict performance better? Are specific market sectors better at prediction? Presumably technology stocks are more volatile than the industrials."]}),"\n",(0,r.jsx)(n.p,{children:"So there are some more interesting questions I still want to ask with this data. Knowing that the hard work of data processing is largely already done, it should be fairly simple to continue this analysis and get much more refined with it. Until next time."}),"\n",(0,r.jsx)(n.h1,{id:"appendix",children:"Appendix"}),"\n",(0,r.jsx)(n.p,{children:"Export event data for Russell 3000 companies:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"import pandas as pd\nfrom html.parser import HTMLParser\nfrom datetime import datetime, timedelta\nimport requests\nimport re\nfrom dateutil import parser\nimport progressbar\nfrom concurrent import futures\nimport yaml\n\nclass EarningsParser(HTMLParser):\n store_dates = False\n earnings_offset = None\n dates = []\n \n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.dates = []\n \n def handle_starttag(self, tag, attrs):\n if tag == 'table':\n self.store_dates = True\n \n def handle_data(self, data):\n if self.store_dates:\n match = re.match(r'\\d+/\\d+/\\d+', data)\n if match:\n self.dates.append(match.group(0))\n \n # If a company reports before the bell, record the earnings date\n # being at midnight the day before. Ex: WMT reports 5/19/2016,\n # but we want the reference point to be the closing price on 5/18/2016\n if 'After Close' in data:\n self.earnings_offset = timedelta(days=0)\n elif 'Before Open' in data:\n self.earnings_offset = timedelta(days=-1)\n \n def handle_endtag(self, tag):\n if tag == 'table':\n self.store_dates = False\n \ndef earnings_releases(ticker):\n #print(\"Looking up ticker {}\".format(ticker))\n user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) '\\\n 'Gecko/20100101 Firefox/46.0'\n headers = {'user-agent': user_agent}\n base_url = 'http://www.streetinsider.com/ec_earnings.php?q={}'\\\n .format(ticker)\n e = EarningsParser()\n s = requests.Session()\n a = requests.adapters.HTTPAdapter(max_retries=0)\n s.mount('http://', a)\n e.feed(str(s.get(base_url, headers=headers).content))\n \n if e.earnings_offset is not None:\n dates = map(lambda x: parser.parse(x) + e.earnings_offset, e.dates)\n past = filter(lambda x: x < datetime.now(), dates)\n return list(map(lambda d: d.isoformat(), past))\n\n# Use a Russell-3000 ETF tracker (ticker IWV) to get a list of holdings\nr3000 = pd.read_csv('https://www.ishares.com/us/products/239714/'\n 'ishares-russell-3000-etf/1449138789749.ajax?'\n 'fileType=csv&fileName=IWV_holdings&dataType=fund',\n header=10)\nr3000_equities = r3000[(r3000['Exchange'] == 'NASDAQ') |\n (r3000['Exchange'] == 'New York Stock Exchange Inc.')]\n\ndates_file = open('earnings_dates.yaml', 'w')\n\nwith futures.ThreadPoolExecutor(max_workers=8) as pool:\n fs = {pool.submit(earnings_releases, r3000_equities.ix[t]['Ticker']): t\n for t in r3000_equities.index}\n pbar = progressbar.ProgressBar(term_width=80,\n max_value=r3000_equities.index.max())\n \n for future in futures.as_completed(fs):\n i = fs[future]\n pbar.update(i)\n dates_file.write(yaml.dump({r3000_equities.ix[i]['Ticker']:\n future.result()}))\n"})})]}),"\n",(0,r.jsx)(n.p,{children:"Downloading stock price data needed for the event studies:"}),"\n",(0,r.jsxs)(a,{children:[(0,r.jsx)("summary",{children:"Code"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"from secrets import QUANDL_KEY\nimport pandas as pd\nimport yaml\nfrom dateutil.parser import parse\nfrom datetime import timedelta\nimport quandl\nfrom progressbar import ProgressBar\n\ndef fetch_ticker(ticker, start, end):\n # Quandl is currently giving me issues with returning\n # the entire dataset and not slicing server-side.\n # So instead, we'll do it client-side!\n q_format = '%Y-%m-%d'\n ticker_data = quandl.get('YAHOO/' + ticker,\n start_date=start.strftime(q_format),\n end_date=end.strftime(q_format),\n authtoken=QUANDL_KEY)\n return ticker_data\n \ndata_str = open('earnings_dates.yaml', 'r').read()\n# Need to remove invalid lines\nfiltered = filter(lambda x: '{' not in x, data_str.split('\\n'))\nearnings_data = yaml.load('\\n'.join(filtered))\n\n# Get the first 1500 keys - split up into two statements\n# because of Quandl rate limits\ntickers = list(earnings_data.keys())\n\nprice_dict = {}\ninvalid_tickers = []\nfor ticker in ProgressBar()(tickers[0:1500]):\n try:\n # Replace '.' with '-' in name for some tickers\n fixed = ticker.replace('.', '-')\n event_strs = earnings_data[ticker]\n events = [parse(event) for event in event_strs]\n td = timedelta(days=20)\n price_dict[ticker] = fetch_ticker(fixed,\n min(events)-td, max(events)+td)\n except quandl.NotFoundError:\n invalid_tickers.append(ticker)\n \n# Execute this after 10 minutes have passed\nfor ticker in ProgressBar()(tickers[1500:]):\n try:\n # Replace '.' with '-' in name for some tickers\n fixed = ticker.replace('.', '-')\n event_strs = earnings_data[ticker]\n events = [parse(event) for event in event_strs]\n td = timedelta(days=20)\n price_dict[ticker] = fetch_ticker(fixed,\n min(events)-td, max(events)+td)\n except quandl.NotFoundError:\n invalid_tickers.append(ticker)\n \nprices_store = pd.HDFStore('price_data.hdf')\nfor ticker, prices in price_dict.items():\n prices_store[ticker] = prices\n"})})]})]})}function h(e={}){let{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},7134:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_11_0-1c14b9b64e0cc03bce9e40f936d85202.png"},6403:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_14_0-8fad23eda4377ce379465c56be3eb022.png"},2446:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_16_1-144f4c4021e22c02fe015acc38d26343.png"},3243:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_18_1-0c204d1f3b296db4c925816140a946f2.png"},6810:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_20_1-76d1356ea34f0db5122ddbeb90dc117c.png"},7600:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_23_1-86585ab19c818b386afb7ec00dbec595.png"},6955:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_25_1-0db87f90eaf0febd08b4775910528a75.png"},5968:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_26_1-686b3995a84cbcac983b369843d1e222.png"},8409:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_3_0-6ba22789c3bcc8bd99c64f3fbfa11b30.png"},4400:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_5_0-34febf65365a147cd218c9266b77e4fb.png"},8475:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/_notebook_7_0-a9df30d31e6b96a01619455d5040eb8b.png"},65:function(e,n,t){t.d(n,{Z:function(){return o},a:function(){return i}});var a=t(7294);let r={},s=a.createContext(r);function i(e){let n=a.useContext(s);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),a.createElement(s.Provider,{value:n},e.children)}},173:function(e){e.exports=JSON.parse('{"permalink":"/2016/06/event-studies-and-earnings-releases","source":"@site/blog/2016-06-08-event-studies-and-earnings-releases/index.mdx","title":"Event studies and earnings releases","description":"Or, being suspicious of market insiders.","date":"2016-06-08T12:00:00.000Z","tags":[],"readingTime":16.01,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/06/event-studies-and-earnings-releases","title":"Event studies and earnings releases","date":"2016-06-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"},"nextItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"}}')}}]); \ No newline at end of file diff --git a/assets/js/4cf7e30f.9d25ceb5.js b/assets/js/4cf7e30f.9d25ceb5.js new file mode 100644 index 0000000..c74db32 --- /dev/null +++ b/assets/js/4cf7e30f.9d25ceb5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1446"],{8636:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return p},frontMatter:function(){return o},metadata:function(){return r},toc:function(){return u}});var r=n(3184),a=n(5893),i=n(65);let o={slug:"2019/05/making-bread",title:"Making bread",date:new Date("2019-05-03T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){let t={a:"a",p:"p",...(0,i.a)(),...e.components};return(0,a.jsxs)(t.p,{children:['Having recently started my "gardening leave" between positions, I have some more personal time\navailable. I\'m planning to stay productive, contributing to some open-source projects, but it also\noccurred to me that despite ',(0,a.jsx)(t.a,{href:"https://speice.io/2018/05/hello.html",children:"talking about"}),' bread pics, this\nblog has been purely technical. Maybe I\'ll change the site title from "The Old Speice Guy" to "Bites\nand Bytes"?']})}function p(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return o}});var r=n(7294);let a={},i=r.createContext(a);function o(e){let t=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),r.createElement(i.Provider,{value:t},e.children)}},3184:function(e){e.exports=JSON.parse('{"permalink":"/2019/05/making-bread","source":"@site/blog/2019-05-03-making-bread/index.mdx","title":"Making bread","description":"Having recently started my \\"gardening leave\\" between positions, I have some more personal time","date":"2019-05-03T12:00:00.000Z","tags":[],"readingTime":1.61,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/05/making-bread","title":"Making bread","date":"2019-05-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"},"nextItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"}}')}}]); \ No newline at end of file diff --git a/assets/js/4dbec139.aa429c61.js b/assets/js/4dbec139.aa429c61.js new file mode 100644 index 0000000..ac5988c --- /dev/null +++ b/assets/js/4dbec139.aa429c61.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7953"],{8873:function(t,e,o){o.r(e),o.d(e,{assets:function(){return s},contentTitle:function(){return c},default:function(){return l},frontMatter:function(){return i},metadata:function(){return n},toc:function(){return u}});var n=o(9098),a=o(5893),r=o(65);let i={slug:"2018/01/captains-cookbook-part-2",title:"Captain's Cookbook: Practical usage",date:new Date("2018-01-16T13:00:00.000Z"),authors:["bspeice"],tags:[]},c=void 0,s={authorsImageUrls:[void 0]},u=[];function p(t){let e={p:"p",...(0,r.a)(),...t.components};return(0,a.jsx)(e.p,{children:"A look at more practical usages of Cap'N Proto"})}function l(t={}){let{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(p,{...t})}):p(t)}},65:function(t,e,o){o.d(e,{Z:function(){return c},a:function(){return i}});var n=o(7294);let a={},r=n.createContext(a);function i(t){let e=n.useContext(r);return n.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function c(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:i(t.components),n.createElement(r.Provider,{value:e},t.children)}},9098:function(t){t.exports=JSON.parse('{"permalink":"/2018/01/captains-cookbook-part-2","source":"@site/blog/2018-01-16-captains-cookbook-part-2/index.mdx","title":"Captain\'s Cookbook: Practical usage","description":"A look at more practical usages of Cap\'N Proto","date":"2018-01-16T13:00:00.000Z","tags":[],"readingTime":6.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-2","title":"Captain\'s Cookbook: Practical usage","date":"2018-01-16T13:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Hello!","permalink":"/2018/05/hello"},"nextItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"}}')}}]); \ No newline at end of file diff --git a/assets/js/522b09ee.b6dc382a.js b/assets/js/522b09ee.b6dc382a.js new file mode 100644 index 0000000..9f30c65 --- /dev/null +++ b/assets/js/522b09ee.b6dc382a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5810"],{341:function(t,e,s){s.r(e),s.d(e,{assets:function(){return p},contentTitle:function(){return a},default:function(){return l},frontMatter:function(){return r},metadata:function(){return n},toc:function(){return c}});var n=s(8595),i=s(5893),o=s(65);let r={slug:"2018/09/isomorphic-apps",title:"Isomorphic desktop apps with Rust",date:new Date("2018-09-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,p={authorsImageUrls:[void 0]},c=[];function u(t){let e={a:"a",p:"p",...(0,o.a)(),...t.components};return(0,i.jsxs)(e.p,{children:["I both despise Javascript and am stunned by its success doing some really cool things. It's\n",(0,i.jsx)(e.a,{href:"https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript",children:"this duality"})," that's\nled me to a couple of (very) late nights over the past weeks trying to reconcile myself as I\nbootstrap a simple desktop application."]})}function l(t={}){let{wrapper:e}={...(0,o.a)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(u,{...t})}):u(t)}},65:function(t,e,s){s.d(e,{Z:function(){return a},a:function(){return r}});var n=s(7294);let i={},o=n.createContext(i);function r(t){let e=n.useContext(o);return n.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:r(t.components),n.createElement(o.Provider,{value:e},t.children)}},8595:function(t){t.exports=JSON.parse('{"permalink":"/2018/09/isomorphic-apps","source":"@site/blog/2018-09-15-isomorphic-apps/index.mdx","title":"Isomorphic desktop apps with Rust","description":"I both despise Javascript and am stunned by its success doing some really cool things. It\'s","date":"2018-09-15T12:00:00.000Z","tags":[],"readingTime":9.905,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/isomorphic-apps","title":"Isomorphic desktop apps with Rust","date":"2018-09-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731188450000,"prevItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"},"nextItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"}}')}}]); \ No newline at end of file diff --git a/assets/js/5601.f9142a81.js b/assets/js/5601.f9142a81.js new file mode 100644 index 0000000..4694a91 --- /dev/null +++ b/assets/js/5601.f9142a81.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5601"],{4183:function(e,t,a){a.d(t,{wj:()=>r,nO:()=>m,iZ:()=>f,cH:()=>N,n4:()=>c,Ne:()=>Z,CS:()=>v});var i=a("5893"),n=a("7294"),s=a("5346"),l=a("8312");function r(){let e=(0,l.Z)(),t=e?.data?.blogMetadata;if(!t)throw Error("useBlogMetadata() can't be called on the current route because the blog metadata could not be found in route context");return t}let o=n.createContext(null);function c(e){let{children:t,content:a,isBlogPostPage:s=!1}=e,l=function(e){let{content:t,isBlogPostPage:a}=e;return(0,n.useMemo)(()=>({metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:a}),[t,a])}({content:a,isBlogPostPage:s});return(0,i.jsx)(o.Provider,{value:l,children:t})}function m(){let e=(0,n.useContext)(o);if(null===e)throw new s.i6("BlogPostProvider");return e}var u=a("4757"),h=a("2933");let d=e=>new Date(e).toISOString();function g(e){let t=e.map(p);return{author:1===t.length?t[0]:t}}function x(e,t,a){return e?{image:function(e){let{imageUrl:t,caption:a}=e;return{"@type":"ImageObject","@id":t,url:t,contentUrl:t,caption:a}}({imageUrl:t(e,{absolute:!0}),caption:`title image for the blog post: ${a}`})}:{}}function v(e){let{siteConfig:t}=(0,h.Z)(),{withBaseUrl:a}=(0,u.Cg)(),{metadata:{blogDescription:i,blogTitle:n,permalink:s}}=e,l=`${t.url}${s}`;return{"@context":"https://schema.org","@type":"Blog","@id":l,mainEntityOfPage:l,headline:n,description:i,blogPost:e.items.map(e=>(function(e,t,a){let{assets:i,frontMatter:n,metadata:s}=e,{date:l,title:r,description:o,lastUpdatedAt:c}=s,m=i.image??n.image,u=n.keywords??[],h=`${t.url}${s.permalink}`,v=c?d(c):void 0;return{"@type":"BlogPosting","@id":h,mainEntityOfPage:h,url:h,headline:r,name:r,description:o,datePublished:l,...v?{dateModified:v}:{},...g(s.authors),...x(m,a,r),...u?{keywords:u}:{}}})(e.content,t,a))}}function f(){let e=r(),{assets:t,metadata:a}=m(),{siteConfig:i}=(0,h.Z)(),{withBaseUrl:n}=(0,u.Cg)(),{date:s,title:l,description:o,frontMatter:c,lastUpdatedAt:v}=a,f=t.image??c.image,p=c.keywords??[],j=v?d(v):void 0,w=`${i.url}${a.permalink}`;return{"@context":"https://schema.org","@type":"BlogPosting","@id":w,mainEntityOfPage:w,url:w,headline:l,name:l,description:o,datePublished:s,...j?{dateModified:j}:{},...g(a.authors),...x(f,n,l),...p?{keywords:p}:{},isPartOf:{"@type":"Blog","@id":`${i.url}${e.blogBasePath}`,name:e.blogTitle}}}function p(e){return{"@type":"Person",...e.name?{name:e.name}:{},...e.title?{description:e.title}:{},...e.url?{url:e.url}:{},...e.email?{email:e.email}:{},...e.imageURL?{image:e.imageURL}:{}}}var j=a("6550"),w=a("3012"),b=a("9246");function N(e){let{pathname:t}=(0,j.TH)();return(0,n.useMemo)(()=>e.filter(e=>{var a,i;return a=e,i=t,(!a.unlisted||!!(0,b.Mg)(a.permalink,i))&&!0}),[e,t])}function Z(e){let{items:t,ulClassName:a,liClassName:n,linkClassName:s,linkActiveClassName:l}=e;return(0,i.jsx)("ul",{className:a,children:t.map(e=>(0,i.jsx)("li",{className:n,children:(0,i.jsx)(w.Z,{isNavLink:!0,to:e.permalink,className:s,activeClassName:l,children:e.title})},e.permalink))})}},1389:function(e,t,a){a.d(t,{Z:()=>w});var i=a("5893");a("7294");var n=a("7026"),s=a("3012");let l="githubSvg_Uu4N",r="xSvg_y3PF",o=function(e){return(0,i.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...e,children:[(0,i.jsx)("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),(0,i.jsx)("path",{d:"M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"}),(0,i.jsx)("path",{d:"M3.6 9h16.8"}),(0,i.jsx)("path",{d:"M3.6 15h16.8"}),(0,i.jsx)("path",{d:"M11.5 3a17 17 0 0 0 0 18"}),(0,i.jsx)("path",{d:"M12.5 3a17 17 0 0 1 0 18"})]})},c="authorSocials_rSDt",m="authorSocialLink_owbf",u={twitter:{Icon:function(e){return(0,i.jsx)("svg",{viewBox:"0 0 256 209",width:"1em",height:"1em",xmlns:"http://www.w3.org/2000/svg",preserveAspectRatio:"xMidYMid",...e,children:(0,i.jsx)("path",{d:"M256 25.45c-9.42 4.177-19.542 7-30.166 8.27 10.845-6.5 19.172-16.793 23.093-29.057a105.183 105.183 0 0 1-33.351 12.745C205.995 7.201 192.346.822 177.239.822c-29.006 0-52.523 23.516-52.523 52.52 0 4.117.465 8.125 1.36 11.97-43.65-2.191-82.35-23.1-108.255-54.876-4.52 7.757-7.11 16.78-7.11 26.404 0 18.222 9.273 34.297 23.365 43.716a52.312 52.312 0 0 1-23.79-6.57c-.003.22-.003.44-.003.661 0 25.447 18.104 46.675 42.13 51.5a52.592 52.592 0 0 1-23.718.9c6.683 20.866 26.08 36.05 49.062 36.475-17.975 14.086-40.622 22.483-65.228 22.483-4.24 0-8.42-.249-12.529-.734 23.243 14.902 50.85 23.597 80.51 23.597 96.607 0 149.434-80.031 149.434-149.435 0-2.278-.05-4.543-.152-6.795A106.748 106.748 0 0 0 256 25.45",fill:"#55acee"})})},label:"Twitter"},github:{Icon:function(e){return(0,i.jsx)("svg",{viewBox:"0 0 256 250",width:"1em",height:"1em",...e,className:(0,n.Z)(e.className,l),xmlns:"http://www.w3.org/2000/svg",style:{"--dark":"#000","--light":"#fff"},preserveAspectRatio:"xMidYMid",children:(0,i.jsx)("path",{d:"M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z"})})},label:"GitHub"},stackoverflow:{Icon:function(e){return(0,i.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 169.61 200",width:"1em",height:"1em",...e,children:[(0,i.jsx)("path",{d:"M140.44 178.38v-48.65h21.61V200H0v-70.27h21.61v48.65z",fill:"#bcbbbb"}),(0,i.jsx)("path",{d:"M124.24 140.54l4.32-16.22-86.97-17.83-3.78 17.83zM49.7 82.16L130.72 120l7.56-16.22-81.02-37.83zm22.68-40l68.06 57.3 11.35-13.51-68.6-57.3-11.35 13.51zM116.14 0l-14.59 10.81 53.48 71.89 14.58-10.81zM37.81 162.16h86.43v-16.21H37.81z",fill:"#f48024"})]})},label:"Stack Overflow"},linkedin:{Icon:function(e){return(0,i.jsx)("svg",{width:"1em",height:"1em",xmlns:"http://www.w3.org/2000/svg",preserveAspectRatio:"xMidYMid",viewBox:"0 0 256 256",...e,children:(0,i.jsx)("path",{d:"M218.123 218.127h-37.931v-59.403c0-14.165-.253-32.4-19.728-32.4-19.756 0-22.779 15.434-22.779 31.369v60.43h-37.93V95.967h36.413v16.694h.51a39.907 39.907 0 0 1 35.928-19.733c38.445 0 45.533 25.288 45.533 58.186l-.016 67.013ZM56.955 79.27c-12.157.002-22.014-9.852-22.016-22.009-.002-12.157 9.851-22.014 22.008-22.016 12.157-.003 22.014 9.851 22.016 22.008A22.013 22.013 0 0 1 56.955 79.27m18.966 138.858H37.95V95.967h37.97v122.16ZM237.033.018H18.89C8.58-.098.125 8.161-.001 18.471v219.053c.122 10.315 8.576 18.582 18.89 18.474h218.144c10.336.128 18.823-8.139 18.966-18.474V18.454c-.147-10.33-8.635-18.588-18.966-18.453",fill:"#0A66C2"})})},label:"LinkedIn"},x:{Icon:function(e){return(0,i.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"1em",height:"1em",fill:"none",viewBox:"0 0 1200 1227",...e,className:(0,n.Z)(e.className,r),style:{"--dark":"#000","--light":"#fff"},children:(0,i.jsx)("path",{d:"M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z"})})},label:"X"}};function h(e){var t;let{platform:a,link:l}=e;let{Icon:r,label:c}=u[t=a]??{Icon:o,label:t};return(0,i.jsx)(s.Z,{className:m,href:l,title:c,children:(0,i.jsx)(r,{className:(0,n.Z)(m)})})}function d(e){let{author:t}=e,a=Object.entries(t.socials??{});return(0,i.jsx)("div",{className:c,children:a.map(e=>{let[t,a]=e;return(0,i.jsx)(h,{platform:t,link:a},t)})})}var g=a("4403");let x={authorImage:"authorImage_XqGP","author-as-h1":"author-as-h1_n9oJ","author-as-h2":"author-as-h2_gXvM",authorDetails:"authorDetails_lV9A",authorName:"authorName_yefp",authorTitle:"authorTitle_nd0D",authorBlogPostCount:"authorBlogPostCount_iiJ5"};function v(e){return e.href?(0,i.jsx)(s.Z,{...e}):(0,i.jsx)(i.Fragment,{children:e.children})}function f(e){let{title:t}=e;return(0,i.jsx)("small",{className:x.authorTitle,title:t,children:t})}function p(e){let{name:t,as:a}=e;return a?(0,i.jsx)(g.Z,{as:a,className:x.authorName,children:t}):(0,i.jsx)("span",{className:x.authorName,children:t})}function j(e){let{count:t}=e;return(0,i.jsx)("span",{className:(0,n.Z)(x.authorBlogPostCount),children:t})}function w(e){let{as:t,author:a,className:s,count:l}=e,{name:r,title:o,url:c,imageURL:m,email:u,page:h}=a,g=h?.permalink||c||u&&`mailto:${u}`||void 0;return(0,i.jsxs)("div",{className:(0,n.Z)("avatar margin-bottom--sm",s,x[`author-as-${t}`]),children:[m&&(0,i.jsx)(v,{href:g,className:"avatar__photo-link",children:(0,i.jsx)("img",{className:(0,n.Z)("avatar__photo",x.authorImage),src:m,alt:r})}),(r||o)&&(0,i.jsxs)("div",{className:(0,n.Z)("avatar__intro",x.authorDetails),children:[(0,i.jsxs)("div",{className:"avatar__name",children:[r&&(0,i.jsx)(v,{href:g,children:(0,i.jsx)(p,{name:r,as:t})}),void 0!==l&&(0,i.jsx)(j,{count:l})]}),!!o&&(0,i.jsx)(f,{title:o}),(0,i.jsx)(d,{author:a})]})]})}},979:function(e,t,a){a.d(t,{Z:()=>M});var i=a("5893"),n=a("7294"),s=a("7026"),l=a("5654"),r=a("4704"),o=a("6025"),c=a("4183"),m=a("131");let u="sidebar_re4s",h="sidebarItemTitle_pO2u",d="sidebarItemList_Yudw",g="sidebarItem__DBe",x="sidebarItemLink_mo7H",v="sidebarItemLinkActive_I1ZP",f="yearGroupHeading_rMGB",p=e=>{let{items:t}=e;return(0,i.jsx)(c.Ne,{items:t,ulClassName:(0,s.Z)(d,"clean-list"),liClassName:g,linkClassName:x,linkActiveClassName:v})},j=(0,n.memo)(function(e){let{sidebar:t}=e,a=(0,c.cH)(t.items);return(0,i.jsx)("aside",{className:"col col--3",children:(0,i.jsxs)("nav",{className:(0,s.Z)(u,"thin-scrollbar"),"aria-label":(0,o.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"}),children:[(0,i.jsx)("div",{className:(0,s.Z)(h,"margin-bottom--md"),children:t.title}),(0,i.jsx)(m.Z,{items:a,ListComponent:p,yearGroupHeadingClassName:f})]})})});var w=a("1179");let b="yearGroupHeading_QT03",N=e=>{let{items:t}=e;return(0,i.jsx)(c.Ne,{items:t,ulClassName:"menu__list",liClassName:"menu__list-item",linkClassName:"menu__link",linkActiveClassName:"menu__link--active"})};function Z(e){let{sidebar:t}=e,a=(0,c.cH)(t.items);return(0,i.jsx)(m.Z,{items:a,ListComponent:N,yearGroupHeadingClassName:b})}let _=(0,n.memo)(function(e){return(0,i.jsx)(w.Zo,{component:Z,props:e})});function k(e){let{sidebar:t}=e,a=(0,r.i)();return t?.items.length?"mobile"===a?(0,i.jsx)(_,{sidebar:t}):(0,i.jsx)(j,{sidebar:t}):null}function M(e){let{sidebar:t,toc:a,children:n,...r}=e,o=t&&t.items.length>0;return(0,i.jsx)(l.Z,{...r,children:(0,i.jsx)("div",{className:"container margin-vert--lg",children:(0,i.jsxs)("div",{className:"row",children:[(0,i.jsx)(k,{sidebar:t}),(0,i.jsx)("main",{className:(0,s.Z)("col",{"col--7":o,"col--9 col--offset-1":!o}),children:n}),a&&(0,i.jsx)("div",{className:"col col--2",children:a})]})})})}}}]); \ No newline at end of file diff --git a/assets/js/5f602fa1.12465c04.js b/assets/js/5f602fa1.12465c04.js new file mode 100644 index 0000000..211f623 --- /dev/null +++ b/assets/js/5f602fa1.12465c04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8345"],{84:function(s,e,a){a.r(e),a.d(e,{assets:function(){return m},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return t},metadata:function(){return l},toc:function(){return c}});var l=a(4018),n=a(5893),i=a(65);let t={slug:"2016/05/the-unfair-casino",title:"The unfair casino",date:new Date("2016-05-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,m={authorsImageUrls:[void 0]},c=[{value:"Proving we can detect cheating",id:"proving-we-can-detect-cheating",level:2},{value:"The Edge Cases",id:"the-edge-cases",level:2},{value:"Edge Case 1",id:"edge-case-1",level:3},{value:"Edge Case 2",id:"edge-case-2",level:3},{value:"Detection Conclusion",id:"detection-conclusion",level:2},{value:"Simulated Annealing",id:"simulated-annealing",level:2},{value:"Deriving the Likelihood function",id:"deriving-the-likelihood-function",level:3},{value:"The process of Simulated Annealing",id:"the-process-of-simulated-annealing",level:3},{value:"The actual code",id:"the-actual-code",level:2},{value:"Catching the Casino",id:"catching-the-casino",level:2},{value:"Attempt 1",id:"attempt-1",level:3},{value:"Attempt 2",id:"attempt-2",level:3},{value:"Attempt 3",id:"attempt-3",level:3},{value:"Attempt 4",id:"attempt-4",level:3},{value:"Attempt 5",id:"attempt-5",level:3},{value:"Conclusion",id:"conclusion",level:2},{value:"Justification of Simulated Annealing",id:"justification-of-simulated-annealing",level:2},{value:"Why Simulated Annealing?",id:"why-simulated-annealing",level:3},{value:"Why not something else?",id:"why-not-something-else",level:3}];function h(s){let e={a:"a",annotation:"annotation",code:"code",em:"em",h2:"h2",h3:"h3",hr:"hr",img:"img",li:"li",math:"math",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",mstyle:"mstyle",msub:"msub",mtable:"mtable",mtd:"mtd",mtr:"mtr",munderover:"munderover",ol:"ol",p:"p",path:"path",pre:"pre",semantics:"semantics",span:"span",strong:"strong",svg:"svg",...(0,i.a)(),...s.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.p,{children:"Trying to figure out how exactly two dice are loaded in a cheating casino."}),"\n",(0,n.jsx)(e.p,{children:"In the ongoing eternal cycle of mathematicians asking generally useless questions about probability, I dreamt up another one. The scenario is as follows:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.strong,{children:"You're playing a game with two die, and you do not get to see what the outcome of the die are on each roll. All you get to see is their sum. Given an arbitrarily long list of the sum of two rolls, can you determine if one or both die are loaded, and what those loadings are?"})}),"\n",(0,n.jsx)(e.h2,{id:"proving-we-can-detect-cheating",children:"Proving we can detect cheating"}),"\n",(0,n.jsx)(e.p,{children:"My first question is simply, is this possible? There's a lot of trivial cases that make it obvious that there's cheating going on. But there are some edge cases that might give us more difficulty. First though, let's get a picture of what the fair distribution looks like. In principle, we can only detect cheating if the distribution of the fair die differs from the distribution of the loaded die."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfair_1 = np.random.randint(1, 7, 10000)\nfair_2 = np.random.randint(1, 7, 10000)\n\npd.Series(fair_1 + fair_2).plot(kind='hist', bins=11);\nplt.title('Fair Distribution');\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(8960).Z+"",width:"400",height:"266"})}),"\n",(0,n.jsxs)(e.p,{children:["This distribution makes sense: there are many ways to make a 7 (the most frequent observed value) and very few ways to make a 12 or 2; an important symmetry. As a special note, you can notice that the sum of two fair dice is a discrete case of the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Triangular_distribution",children:"Triangle Distribution"}),", which is itself a special case of the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution",children:"Irwin-Hall Distribution"}),"."]}),"\n",(0,n.jsx)(e.h2,{id:"the-edge-cases",children:"The Edge Cases"}),"\n",(0,n.jsx)(e.p,{children:"Given that we understand how the results of two fair dice are distributed, let's see some of the interesting edge cases that come up. This will give us assurance that when a casino is cheating, it is detectable (given sufficient data). To make this as hard as possible, we will think of scenarios where the expected value of the sum of loaded dice is the same as the expected value of the sum of fair dice."}),"\n",(0,n.jsx)(e.h3,{id:"edge-case-1",children:"Edge Case 1"}),"\n",(0,n.jsx)(e.p,{children:"What happens when one die is biased low, and one die is biased high? That is, where:"}),"\n",(0,n.jsx)(e.span,{className:"katex-display",children:(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right",columnspacing:"",children:[(0,n.jsx)(e.mtr,{children:(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mo,{fence:"true",children:"{"}),(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"left right",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"1"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"2"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"3"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"4"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"5"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"6"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]})]})]})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mo,{fence:"true",children:"{"}),(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"left right",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"1"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"2"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"3"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"4"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"5"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"6"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]})]})]})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"2.5"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"4.5"})]})})})]})]})})})}),(0,n.jsx)(e.mtr,{children:(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{children:"+"}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"7"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"f"}),(0,n.jsx)(e.mi,{children:"a"}),(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mi,{children:"r"})]})]}),(0,n.jsx)(e.mo,{children:"+"}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"f"}),(0,n.jsx)(e.mi,{children:"a"}),(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mi,{children:"r"})]})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"})]})})})})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\n\\begin{array}{cc}\nD_1 = \\left\\{\n\\begin{array}{lr}\n1 & w.p. 1/3\\\\\n2 & w.p. 1/3\\\\\n3 & w.p. 1/12\\\\\n4 & w.p. 1/12\\\\\n5 & w.p. 1/12\\\\\n6 & w.p. 1/12\n\\end{array}\n\\right. &\nD_2 = \\left\\{\n\\begin{array}{lr}\n1 & w.p. 1/12\\\\\n2 & w.p. 1/12\\\\\n3 & w.p. 1/12\\\\\n4 & w.p. 1/12\\\\\n5 & w.p. 1/3\\\\\n6 & w.p. 1/3\n\\end{array}\n\\right. \\\\\n\\mathbb{E}[D_1] = 2.5 & \\mathbb{E}[D_2] = 4.5\n\\end{array}\\\\\n\\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}]\n\\end{align*}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"10.2em",verticalAlign:"-4.85em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mtable",children:(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"5.35em"},children:[(0,n.jsxs)(e.span,{style:{top:"-7.35em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"6.45em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-c",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"4.45em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.45em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsxs)(e.span,{className:"minner",children:[(0,n.jsx)(e.span,{className:"mopen",children:(0,n.jsx)(e.span,{className:"delimsizing mult",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.366em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A9"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.816em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A8"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.958em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-6.766em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A7"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})})}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"2"})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"3"})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"4"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"5"})})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"6"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})}),(0,n.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"2.5"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.95em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-c",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"4.45em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.45em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsxs)(e.span,{className:"minner",children:[(0,n.jsx)(e.span,{className:"mopen",children:(0,n.jsx)(e.span,{className:"delimsizing mult",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.366em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A9"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.816em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A8"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.958em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-6.766em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A7"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})})}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"2"})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"3"})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"4"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"5"})})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"6"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})}),(0,n.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"4.5"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.95em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"6.45em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(e.span,{className:"mbin",children:"+"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"7"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.10764em"},children:"f"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ai"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02778em"},children:"r"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(e.span,{className:"mbin",children:"+"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.10764em"},children:"f"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ai"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02778em"},children:"r"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"4.85em"},children:(0,n.jsx)(e.span,{})})})]})})})})]})})]})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"def unfair_die(p_vals, n):\n x = np.random.multinomial(1, p_vals, n)\n return x.nonzero()[1] + 1\n\nd1 = [1/3, 1/3, 1/12, 1/12, 1/12, 1/12]\nd2 = [1/12, 1/12, 1/12, 1/12, 1/3, 1/3]\n\nx1 = unfair_die(d1, 10000)\nx2 = unfair_die(d2, 10000)\n\npd.Series(x1 + x2).plot(kind='hist', bins=11);\nplt.title('$D_1$ biased low, $D_2$ biased high');\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(4707).Z+"",width:"400",height:"268"})}),"\n",(0,n.jsx)(e.p,{children:"We can see that while the 7 value remains the most likely (as expected), the distribution is not so nicely shaped any more."}),"\n",(0,n.jsx)(e.h3,{id:"edge-case-2",children:"Edge Case 2"}),"\n",(0,n.jsx)(e.p,{children:"When one die is loaded low, and one is loaded high, we've seen how we can detect them. How about when two die are loaded both low and high? That is, we have the following distribution:"}),"\n",(0,n.jsx)(e.span,{className:"katex-display",children:(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right",columnspacing:"",children:[(0,n.jsx)(e.mtr,{children:(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"center center",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mo,{fence:"true",children:"{"}),(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"left right",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"1"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"2"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"3"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"4"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"5"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"6"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]})]})]})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mo,{fence:"true",children:"{"}),(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"left right",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"1"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"2"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"3"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"4"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"5"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"12"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mn,{children:"6"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"w"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mi,{mathvariant:"normal",children:"/"}),(0,n.jsx)(e.mn,{children:"3"})]})})})]})]})]})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"3.5"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"3.5"})]})})})]})]})})})}),(0,n.jsx)(e.mtr,{children:(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mo,{children:"+"}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsx)(e.mn,{children:"2"})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"7"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mi,{mathvariant:"double-struck",children:"E"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"["}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"f"}),(0,n.jsx)(e.mi,{children:"a"}),(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mi,{children:"r"})]})]}),(0,n.jsx)(e.mo,{children:"+"}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"D"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"f"}),(0,n.jsx)(e.mi,{children:"a"}),(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mi,{children:"r"})]})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:"]"})]})})})})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\n\\begin{array}{cc}\nD_1 = \\left\\{\n\\begin{array}{lr}\n1 & w.p. 1/3\\\\\n2 & w.p. 1/12\\\\\n3 & w.p. 1/12\\\\\n4 & w.p. 1/12\\\\\n5 & w.p. 1/12\\\\\n6 & w.p. 1/3\n\\end{array}\n\\right. &\nD_2 = \\left\\{\n\\begin{array}{lr}\n1 & w.p. 1/3\\\\\n2 & w.p. 1/12\\\\\n3 & w.p. 1/12\\\\\n4 & w.p. 1/12\\\\\n5 & w.p. 1/12\\\\\n6 & w.p. 1/3\n\\end{array}\n\\right. \\\\\n\\mathbb{E}[D_1] = 3.5 & \\mathbb{E}[D_2] = 3.5\n\\end{array}\\\\\n\\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}]\n\\end{align*}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"10.2em",verticalAlign:"-4.85em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mtable",children:(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"5.35em"},children:[(0,n.jsxs)(e.span,{style:{top:"-7.35em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"6.45em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-c",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"4.45em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.45em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsxs)(e.span,{className:"minner",children:[(0,n.jsx)(e.span,{className:"mopen",children:(0,n.jsx)(e.span,{className:"delimsizing mult",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.366em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A9"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.816em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A8"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.958em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-6.766em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A7"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})})}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"2"})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"3"})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"4"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"5"})})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"6"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})}),(0,n.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"3.5"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.95em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-c",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"4.45em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.45em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsxs)(e.span,{className:"minner",children:[(0,n.jsx)(e.span,{className:"mopen",children:(0,n.jsx)(e.span,{className:"delimsizing mult",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.366em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A9"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.816em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A8"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.958em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{style:{height:"1.816em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.816em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1816",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-6.766em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.816em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A7"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})})}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"1"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"2"})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"3"})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"4"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"5"})})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mord",children:"6"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.85em"},children:[(0,n.jsxs)(e.span,{style:{top:"-6.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-4.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-3.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-1.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/12"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-0.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02691em"},children:"w"}),(0,n.jsx)(e.span,{className:"mord",children:"."}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"mord",children:".1/3"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.35em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})}),(0,n.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.85em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"3.5"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.95em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})})})]}),(0,n.jsxs)(e.span,{style:{top:"-2.26em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"6.45em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(e.span,{className:"mbin",children:"+"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"7"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord mathbb",children:"E"}),(0,n.jsx)(e.span,{className:"mopen",children:"["}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.10764em"},children:"f"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ai"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02778em"},children:"r"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(e.span,{className:"mbin",children:"+"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.10764em"},children:"f"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ai"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.02778em"},children:"r"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:"]"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"4.85em"},children:(0,n.jsx)(e.span,{})})})]})})})})]})})]})}),"\n",(0,n.jsx)(e.p,{children:"We can see even that the expected value of each individual die is the same as the fair die! However, the distribution (if we are doing this correctly) should still be skewed:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"d1 = [1/3, 1/12, 1/12, 1/12, 1/12, 1/3]\nd2 = d1\n\nx1 = unfair_die(d1, 10000)\nx2 = unfair_die(d2, 10000)\n\npd.Series(x1 + x2).plot(kind='hist', bins=11)\nplt.title(\"$D_1$ and $D_2$ biased to 1 and 6\");\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(9724).Z+"",width:"400",height:"268"})}),"\n",(0,n.jsx)(e.p,{children:"In a very un-subtle way, we have of course made the values 2 and 12 far more likely."}),"\n",(0,n.jsx)(e.h2,{id:"detection-conclusion",children:"Detection Conclusion"}),"\n",(0,n.jsx)(e.p,{children:"There are some trivial examples of cheating that are easy to detect: whenever the expected value of the sum of two fair dice deviates from the expected value for the sum of two fair dice, we can immediately conclude that there is cheating at stake."}),"\n",(0,n.jsx)(e.p,{children:"The interesting edge cases occur when the expected value of the sum of loaded dice matches the expected value of the sum of fair dice. Considering the above examples (and a couple more I ran through in developing this), we have seen that in every circumstance having two unfair dice leads to a distribution of results different from the fair results."}),"\n",(0,n.jsxs)(e.p,{children:["We can thus finally state: ",(0,n.jsx)(e.strong,{children:"just by looking at the distribution of results from this game, we can immediately conclude whether there is cheating."})]}),"\n",(0,n.jsx)(e.h2,{id:"simulated-annealing",children:"Simulated Annealing"}),"\n",(0,n.jsxs)(e.p,{children:["What we really would like to do though, is see if there is any way to determine how exactly the dice are loaded. This is significantly more complicated, but we can borrow some algorithms from Machine Learning to figure out exactly how to perform this process. I'm using the Simulated Annealing algorithm, and I discuss why this works and why I chose it over some of the alternatives in the ",(0,n.jsx)(e.a,{href:"#Justification-of-Simulated-Annealing",children:"justification"}),". If you don't care about how I set up the model and just want to see the code, check out ",(0,n.jsx)(e.a,{href:"#The-actual-code",children:"the actual code"}),"."]}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Simulated_annealing",children:"Simulated Annealing"})," is a variation of the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm",children:"Metropolis-Hastings Algorithm"}),", but the important thing for us is: Simulated Annealing allows us to quickly optimize high-dimensional problems. But what exactly are we trying to optimize? Ideally, we want a function that can tell us whether one distribution for the dice better explains the results than another distribution. This is known as the ",(0,n.jsx)(e.strong,{children:"likelihood"})," function."]}),"\n",(0,n.jsx)(e.h3,{id:"deriving-the-likelihood-function",children:"Deriving the Likelihood function"}),"\n",(0,n.jsxs)(e.p,{children:["To derive our likelihood function, we want to know: ",(0,n.jsx)(e.strong,{children:"what is the probability of seeing a specific result given those hidden parameters?"})," This is actually a surprisingly difficult problem. While we can do a lot of calculations by hand, we need a more general solution since we will be working with very some interesting die distributions."]}),"\n",(0,n.jsxs)(e.p,{children:["We first note that the sum of two dice can take on 11 different values - 2 through 12. This implies that each individual sum follows a ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Categorical_distribution",children:"Categorical distribution"}),". That is:"]}),"\n",(0,n.jsx)(e.span,{className:"katex-display",children:(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right",columnspacing:"",children:(0,n.jsx)(e.mtr,{children:(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"script",children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{mathvariant:"script",children:"x"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mo,{fence:"true",children:"{"}),(0,n.jsxs)(e.mtable,{rowspacing:"0.16em",columnalign:"left right",columnspacing:"1em",children:[(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mn,{children:"2"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"2"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mn,{children:"3"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"3"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mo,{lspace:"0em",rspace:"0em",children:"\u2026"})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsx)(e.mrow,{})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mn,{children:"11"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"11"})]})})})]}),(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mn,{children:"12"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"false",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"12"})]})})})]})]})]})]})})})})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\n\\mathcal{L(x)} = \\left\\{\n\\begin{array}{lr}\np_2 & x = 2\\\\\np_3 & x = 3\\\\\n\\ldots & \\\\\np_{11} & x = 11\\\\\np_{12} & x = 12\n\\end{array}\n\\right.\n\\end{align*}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"6.3em",verticalAlign:"-2.9em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"mtable",children:(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"3.4em"},children:(0,n.jsxs)(e.span,{style:{top:"-5.4em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"5.25em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathcal",children:"L"}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsxs)(e.span,{className:"minner",children:[(0,n.jsx)(e.span,{className:"mopen",children:(0,n.jsx)(e.span,{className:"delimsizing mult",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.25em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.366em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.216em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A9"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.216em"}}),(0,n.jsx)(e.span,{style:{height:"1.216em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.216em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1216",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1216 H384z M384 0 H504 V1216 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.216em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.216em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A8"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.358em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.216em"}}),(0,n.jsx)(e.span,{style:{height:"1.216em",width:"0.8889em"},children:(0,n.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.8889em",height:"1.216em",style:{width:"0.8889em"},viewBox:"0 0 888.89 1216",preserveAspectRatio:"xMinYMin",children:(0,n.jsx)(e.path,{d:"M384 0 H504 V1216 H384z M384 0 H504 V1216 H384z"})})})]}),(0,n.jsxs)(e.span,{style:{top:"-5.566em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.216em"}}),(0,n.jsx)(e.span,{className:"delimsizinginner delim-size4",children:(0,n.jsx)(e.span,{children:"\u23A7"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"2.75em"},children:(0,n.jsx)(e.span,{})})})]})})}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.25em"},children:[(0,n.jsxs)(e.span,{style:{top:"-5.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"2"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"3"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsx)(e.span,{className:"minner",children:"\u2026"})})]}),(0,n.jsxs)(e.span,{style:{top:"-1.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"11"})})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]}),(0,n.jsxs)(e.span,{style:{top:"-0.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3011em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:"12"})})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"2.75em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}}),(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"3.25em"},children:[(0,n.jsxs)(e.span,{style:{top:"-5.41em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"2"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-4.21em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"3"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-3.01em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsx)(e.span,{className:"mord"})]}),(0,n.jsxs)(e.span,{style:{top:"-1.81em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"11"})]})]}),(0,n.jsxs)(e.span,{style:{top:"-0.61em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mord",children:"12"})]})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"2.75em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"arraycolsep",style:{width:"0.5em"}})]})}),(0,n.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"2.9em"},children:(0,n.jsx)(e.span,{})})})]})})})})]})})]})}),"\n",(0,n.jsxs)(e.p,{children:["Where each ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mrow,{children:(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{children:"i"})]})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"p_i"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]})]})})]})," is the probability of seeing that specific result. However, we need to calculate what each probability is! I'll save you the details, but ",(0,n.jsx)(e.a,{href:"http://math.stackexchange.com/a/1646360/320784",children:"this author"})," explains how to do it."]}),"\n",(0,n.jsx)(e.p,{children:"Now, we would like to know the likelihood of our entire data-set. This is trivial:"}),"\n",(0,n.jsx)(e.span,{className:"katex-display",children:(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"script",children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{mathvariant:"bold",children:"X"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mrow,{}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.munderover,{children:[(0,n.jsx)(e.mo,{children:"\u220F"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mi,{children:"n"})]}),(0,n.jsx)(e.mi,{children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]})})})]})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\n\\mathcal{L(\\mathbf{X})} &= \\prod_{i=1}^n L(x)\n\\end{align*}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"3.2291em",verticalAlign:"-1.3645em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.8645em"},children:(0,n.jsxs)(e.span,{style:{top:"-3.8645em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.6514em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathcal",children:"L"}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathbf",children:"X"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.3645em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.8645em"},children:(0,n.jsxs)(e.span,{style:{top:"-3.8645em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.6514em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mop op-limits",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"1.6514em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,n.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u220F"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"L"}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.3645em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,n.jsxs)(e.p,{children:["However, it's typically much easier to work with the ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"log"}),(0,n.jsx)(e.mo,{children:"\u2061"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{mathvariant:"script",children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\log(\\mathcal{L})"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,n.jsxs)(e.span,{className:"mop",children:["lo",(0,n.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathcal",children:"L"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})})]})," function instead. This is critically important from a computational perspective: when you multiply so many small numbers together (i.e. the product of ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{children:"x"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"L(x)"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"L"}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})})]}),' terms) the computer suffers from rounding error; if we don\'t control for this, we will find that no matter the distributions we choose for each die, the "likelihood" will be close to zero because the computer is not precise enough.']}),"\n",(0,n.jsx)(e.span,{className:"katex-display",children:(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:(0,n.jsxs)(e.mtr,{children:[(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"log"}),(0,n.jsx)(e.mo,{children:"\u2061"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{mathvariant:"script",children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,n.jsx)(e.mtd,{children:(0,n.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mrow,{}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsxs)(e.munderover,{children:[(0,n.jsx)(e.mo,{children:"\u2211"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mo,{children:"="}),(0,n.jsx)(e.mn,{children:"1"})]}),(0,n.jsx)(e.mi,{children:"n"})]}),(0,n.jsx)(e.mi,{children:"log"}),(0,n.jsx)(e.mo,{children:"\u2061"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]})})})]})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\n\\log(\\mathcal{L}) &= \\sum_{i=1}^n \\log(L)\n\\end{align*}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"3.2291em",verticalAlign:"-1.3645em"}}),(0,n.jsx)(e.span,{className:"mord",children:(0,n.jsxs)(e.span,{className:"mtable",children:[(0,n.jsx)(e.span,{className:"col-align-r",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.8645em"},children:(0,n.jsxs)(e.span,{style:{top:"-3.8645em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.6514em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsxs)(e.span,{className:"mop",children:["lo",(0,n.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathcal",children:"L"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.3645em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"col-align-l",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.8645em"},children:(0,n.jsxs)(e.span,{style:{top:"-3.8645em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.6514em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"="}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mop op-limits",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsxs)(e.span,{className:"vlist",style:{height:"1.6514em"},children:[(0,n.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,n.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,n.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,n.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{children:(0,n.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,n.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})]}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,n.jsx)(e.span,{})})})]})}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsxs)(e.span,{className:"mop",children:["lo",(0,n.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"L"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"1.3645em"},children:(0,n.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,n.jsx)(e.h3,{id:"the-process-of-simulated-annealing",children:"The process of Simulated Annealing"}),"\n",(0,n.jsx)(e.p,{children:"The means by which we optimize our likelihood function is the simulated annealing algorithm. The way it works is as follows:"}),"\n",(0,n.jsxs)(e.ol,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsx)(e.p,{children:'Start with a random guess for the parameters we are trying to optimize. In our case we are trying to guess the distribution of two dice, and so we "optimize" until we have a distribution that matches the data.'}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsx)(e.p,{children:"For each iteration of the algorithm:"}),"\n",(0,n.jsxs)(e.ol,{children:["\n",(0,n.jsx)(e.li,{children:'Generate a new "proposed" set of parameters based on the current parameters -\ni.e. slightly modify the current parameters to get a new set of parameters.'}),"\n",(0,n.jsxs)(e.li,{children:["Calculate the value of ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"log"}),(0,n.jsx)(e.mo,{children:"\u2061"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mi,{mathvariant:"script",children:"L"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\log(\\mathcal{L})"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,n.jsxs)(e.span,{className:"mop",children:["lo",(0,n.jsx)(e.span,{style:{marginRight:"0.01389em"},children:"g"})]}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord mathcal",children:"L"}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})})]})," for each set of parameters. If the function value for the\nproposed parameter set is higher than for the current, automatically switch to the new parameter set\nand continue the next iteration."]}),"\n",(0,n.jsxs)(e.li,{children:["Given the new parameter set performs worse, determine a probability of switching to the new parameter set anyways: ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{mathvariant:"script",children:"P"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"c"}),(0,n.jsx)(e.mi,{children:"u"}),(0,n.jsx)(e.mi,{children:"r"}),(0,n.jsx)(e.mi,{children:"r"}),(0,n.jsx)(e.mi,{children:"e"}),(0,n.jsx)(e.mi,{children:"n"}),(0,n.jsx)(e.mi,{children:"t"})]})]}),(0,n.jsx)(e.mo,{separator:"true",children:","}),(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{children:"r"}),(0,n.jsx)(e.mi,{children:"o"}),(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsx)(e.mi,{children:"o"}),(0,n.jsx)(e.mi,{children:"s"}),(0,n.jsx)(e.mi,{children:"e"}),(0,n.jsx)(e.mi,{children:"d"})]})]}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{P}(p_{current}, p_{proposed})"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1.0361em",verticalAlign:"-0.2861em"}}),(0,n.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.08222em"},children:"P"}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2806em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"c"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"u"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"rre"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"t"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mpunct",children:","}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsxs)(e.span,{className:"mord mtight",children:[(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"p"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ro"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"p"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"ose"}),(0,n.jsx)(e.span,{className:"mord mathnormal mtight",children:"d"})]})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mclose",children:")"})]})})]})]}),"\n",(0,n.jsxs)(e.li,{children:["Switch to the new parameter set with probability ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mrow,{children:(0,n.jsx)(e.mi,{mathvariant:"script",children:"P"})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathcal{P}"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,n.jsx)(e.span,{className:"mord mathcal",style:{marginRight:"0.08222em"},children:"P"})]})})]}),". If you fail to switch, begin the next iteration."]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:["The algorithm is complete after we fail to make a transition ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsx)(e.mrow,{children:(0,n.jsx)(e.mi,{children:"n"})}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,n.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"n"})]})})]})," times in a row."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"If everything goes according to plan, we will have a value that is close to the true distribution of each die."}),"\n",(0,n.jsx)(e.h2,{id:"the-actual-code",children:"The actual code"}),"\n",(0,n.jsx)(e.p,{children:"We start by defining the score function. This will tell us how well the proposed die densities actually explain the results."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"import numpy as np\nfrom numpy import polynomial\n\ndef density_coef(d1_density, d2_density):\n # Calculating the probabilities of each outcome was taken\n # from this author: http://math.stackexchange.com/a/1710392/320784\n d1_p = polynomial.Polynomial(d1_density)\n d2_p = polynomial.Polynomial(d2_density)\n coefs = (d1_p * d2_p).coef\n return coefs\n\ndef score(x, d1_density, d2_density):\n # We've now got the probabilities of each event, but we need\n # to shift the array a bit so we can use the x values to actually\n # index into it. This will allow us to do all the calculations\n # incredibly quickly\n coefs = density_coef(d1_density, d2_density)\n coefs = np.hstack((0, 0, coefs))\n return np.log(coefs[x]).sum()\n"})}),"\n",(0,n.jsx)(e.p,{children:"Afterward, we need to write something to permute the proposal densities. We make random modifications, and eventually the best one survives."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"def permute(d1_density, d2_density):\n # To ensure we have legitimate densities, we will randomly\n # increase one die face probability by `change`,\n # and decrease one by `change`.\n # This means there are something less than (1/`change`)^12 possibilities\n # we are trying to search over.\n change = .01\n \n d1_index1, d1_index2 = np.random.randint(0, 6, 2)\n d2_index1, d2_index2 = np.random.randint(0, 6, 2)\n \n # Also make sure to copy. I've had some weird aliasing issues\n # in the past that made everything blow up.\n new_d1 = np.float64(np.copy(d1_density))\n new_d2 = np.float64(np.copy(d2_density))\n \n # While this doesn't account for the possibility that some\n # values go negative, in practice this never happens\n new_d1[d1_index1] += change\n new_d1[d1_index2] -= change\n new_d2[d2_index1] += change\n new_d2[d2_index2] -= change\n \n return new_d1, new_d2\n"})}),"\n",(0,n.jsx)(e.p,{children:"Now we've got the main algorithm code to do. This is what brings all the pieces together."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"def optimize(data, conv_count=10, max_iter=1e4):\n switch_failures = 0\n iter_count = 0\n \n # Start with guessing fair dice\n cur_d1 = np.repeat(1/6, 6)\n cur_d2 = np.repeat(1/6, 6)\n cur_score = score(data, cur_d1, cur_d2)\n \n # Keep track of our best guesses - may not be\n # what we end with\n max_score = cur_score\n max_d1 = cur_d1\n max_d2 = cur_d2\n \n # Optimization stops when we have failed to switch `conv_count`\n # times (presumably because we have a great guess), or we reach\n # the maximum number of iterations.\n while switch_failures < conv_count and iter_count < max_iter:\n iter_count += 1\n if iter_count % (max_iter / 10) == 0:\n print('Iteration: {}; Current score (higher is better): {}'.format(\n iter_count, cur_score))\n \n new_d1, new_d2 = permute(cur_d1, cur_d2)\n new_score = score(data, new_d1, new_d2)\n \n if new_score > max_score:\n max_score = new_score\n max_d1 = new_d1\n max_d2 = new_d2\n \n if new_score > cur_score:\n # If the new permutation beats the old one,\n # automatically select it.\n cur_score = new_score\n cur_d1 = new_d1\n cur_d2 = new_d2\n switch_failures = 0\n else:\n # We didn't beat the current score, but allow\n # for possibly switching anyways.\n accept_prob = np.exp(new_score - cur_score)\n coin_toss = np.random.rand()\n if coin_toss < accept_prob:\n # We randomly switch to the new distribution\n cur_score = new_score\n cur_d1 = new_d1\n cur_d2 = new_d2\n switch_failures = 0\n else:\n switch_failures += 1\n \n # Return both our best guess, and the ending guess\n return max_d1, max_d2, cur_d1, cur_d2\n"})}),"\n",(0,n.jsx)(e.p,{children:"And now we have finished the hard work!"}),"\n",(0,n.jsx)(e.h2,{id:"catching-the-casino",children:"Catching the Casino"}),"\n",(0,n.jsxs)(e.p,{children:["Let's go through a couple of scenarios and see if we can catch the casino cheating with some loaded dice. ",(0,n.jsx)(e.strong,{children:"In every scenario we start with an assumption of fair dice"}),", and then try our hand to figure out what the ",(0,n.jsx)(e.em,{children:"actual"})," distribution was."]}),"\n",(0,n.jsx)(e.h3,{id:"attempt-1",children:"Attempt 1"}),"\n",(0,n.jsx)(e.p,{children:"The casino is using two dice that are both biased low. How well can we recover the distribution?"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"import time\ndef simulate_casino(d1_dist, d2_dist, n=10000):\n d1_vals = unfair_die(d1_dist, n)\n d2_vals = unfair_die(d2_dist, n)\n \n start = time.perf_counter()\n max_d1, max_d2, final_d1, final_d2 = optimize(d1_vals + d2_vals)\n end = time.perf_counter()\n print(\"Simulated Annealing time: {:.02f}s\".format(end - start))\n \n coef_range = np.arange(2, 13) - .5\n plt.subplot(221)\n plt.bar(coef_range, density_coef(d1_dist, d2_dist), width=1)\n plt.title('True Distribution')\n \n plt.subplot(222)\n plt.hist(d1_vals + d2_vals, bins=11)\n plt.title('Empirical Distribution')\n \n plt.subplot(223)\n plt.bar(coef_range, density_coef(max_d1, max_d2), width=1)\n plt.title('Recovered Distribution')\n \n plt.gcf().set_size_inches(10, 10)\n\n\nsimulate_casino([2/9, 2/9, 2/9, 1/9, 1/9, 1/9],\n [2/9, 2/9, 2/9, 1/9, 1/9, 1/9])\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:" Iteration: 1000; Current score (higher is better): -22147.004400281654\n Simulated Annealing time: 0.30s\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(4452).Z+"",width:"605",height:"601"})}),"\n",(0,n.jsx)(e.h3,{id:"attempt-2",children:"Attempt 2"}),"\n",(0,n.jsx)(e.p,{children:"The casino now uses dice that are both biased towards 1 and 6."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],\n [1/3, 1/12, 1/12, 1/12, 1/12, 1/3])\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:" Simulated Annealing time: 0.08s\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(2053).Z+"",width:"605",height:"601"})}),"\n",(0,n.jsx)(e.h3,{id:"attempt-3",children:"Attempt 3"}),"\n",(0,n.jsx)(e.p,{children:"The casino will now use one die biased towards 1 and 6, and one die towards 3 and 4."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],\n [1/12, 1/12, 1/3, 1/3, 1/12, 1/12])\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:" Simulated Annealing time: 0.09s\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(2477).Z+"",width:"605",height:"601"})}),"\n",(0,n.jsx)(e.h3,{id:"attempt-4",children:"Attempt 4"}),"\n",(0,n.jsx)(e.p,{children:"We'll now finally go to a fair casino to make sure that we can still recognize a positive result."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"simulate_casino(np.repeat(1/6, 6), np.repeat(1/6, 6))\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:" Simulated Annealing time: 0.02s\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(1875).Z+"",width:"605",height:"601"})}),"\n",(0,n.jsx)(e.h3,{id:"attempt-5",children:"Attempt 5"}),"\n",(0,n.jsx)(e.p,{children:"We've so far been working with a large amount of data - 10,000 data points. Can we now scale things back to only 250 throws? We'll start with two dice biased high."}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-python",children:"simulate_casino([1/9, 1/9, 1/9, 2/9, 2/9, 2/9],\n [1/9, 1/9, 1/9, 2/9, 2/9, 2/9],\n n=250)\n"})}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:" Iteration: 1000; Current score (higher is better): -551.6995384525453\n Iteration: 2000; Current score (higher is better): -547.7803673440676\n Iteration: 3000; Current score (higher is better): -547.9805613193807\n Iteration: 4000; Current score (higher is better): -546.7574874775273\n Iteration: 5000; Current score (higher is better): -549.5798007672656\n Iteration: 6000; Current score (higher is better): -545.0354060154496\n Iteration: 7000; Current score (higher is better): -550.1134504086606\n Iteration: 8000; Current score (higher is better): -549.9306537114975\n Iteration: 9000; Current score (higher is better): -550.7075182119111\n Iteration: 10000; Current score (higher is better): -549.400679551826\n Simulated Annealing time: 1.94s\n"})}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"png",src:a(1270).Z+"",width:"605",height:"601"})}),"\n",(0,n.jsx)(e.p,{children:"The results are surprisingly good. While the actual optimization process took much longer to finish than in the other examples, we still have a very good guess. As a caveat though: the recovered distribution tends to overfit the data. That is, if the data doesn't fit the underlying distribution well, the model will also fail."}),"\n",(0,n.jsx)(e.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,n.jsx)(e.p,{children:"Given the results above, we can see that we have indeed come up with a very good algorithm to determine the distribution of two dice given their results. As a benefit, we have even seen that results come back very quickly; it's not uncommon for the optimization to converge within a tenth of a second."}),"\n",(0,n.jsx)(e.p,{children:"Additionally, we have seen that the algorithm can intuit the distribution even when there is not much data. While the final example shows that we can 'overfit' on the dataset, we can still get valuable information from a relatively small dataset."}),"\n",(0,n.jsxs)(e.p,{children:["We can declare at long last: ",(0,n.jsx)(e.strong,{children:"the mathematicians have again triumphed over the casino"}),"."]}),"\n",(0,n.jsx)(e.hr,{}),"\n",(0,n.jsx)(e.h2,{id:"justification-of-simulated-annealing",children:"Justification of Simulated Annealing"}),"\n",(0,n.jsx)(e.h3,{id:"why-simulated-annealing",children:"Why Simulated Annealing?"}),"\n",(0,n.jsxs)(e.p,{children:["So why even use an algorithm with a fancy title like Simulated Annealing? First of all, because the title is sexy. Second of all, because this is a reasonably complicated problem to try and solve. We have a parameter space where each value ",(0,n.jsxs)(e.span,{className:"katex",children:[(0,n.jsx)(e.span,{className:"katex-mathml",children:(0,n.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(e.semantics,{children:[(0,n.jsxs)(e.mrow,{children:[(0,n.jsxs)(e.msub,{children:[(0,n.jsx)(e.mi,{children:"p"}),(0,n.jsxs)(e.mrow,{children:[(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mi,{children:"j"})]})]}),(0,n.jsx)(e.mo,{children:"\u2208"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"("}),(0,n.jsx)(e.mn,{children:"0"}),(0,n.jsx)(e.mo,{separator:"true",children:","}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mo,{stretchy:"false",children:")"}),(0,n.jsx)(e.mo,{separator:"true",children:";"}),(0,n.jsx)(e.mi,{children:"i"}),(0,n.jsx)(e.mo,{separator:"true",children:","}),(0,n.jsx)(e.mi,{children:"j"}),(0,n.jsx)(e.mo,{children:"\u2208"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"{"}),(0,n.jsx)(e.mn,{children:"1"}),(0,n.jsx)(e.mo,{separator:"true",children:","}),(0,n.jsx)(e.mo,{children:"\u2026"}),(0,n.jsx)(e.mo,{separator:"true",children:","}),(0,n.jsx)(e.mn,{children:"6"}),(0,n.jsx)(e.mo,{stretchy:"false",children:"}"})]}),(0,n.jsx)(e.annotation,{encoding:"application/x-tex",children:"p_{ij} \\in (0, 1); i, j \\in \\{1, \\ldots, 6\\}"})]})})}),(0,n.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"0.8252em",verticalAlign:"-0.2861em"}}),(0,n.jsxs)(e.span,{className:"mord",children:[(0,n.jsx)(e.span,{className:"mord mathnormal",children:"p"}),(0,n.jsx)(e.span,{className:"msupsub",children:(0,n.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(e.span,{className:"vlist-r",children:[(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,n.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,n.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(e.span,{className:"mord mtight",children:(0,n.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.05724em"},children:"ij"})})})]})}),(0,n.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(e.span,{className:"vlist-r",children:(0,n.jsx)(e.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(e.span,{})})})]})})]}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"\u2208"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,n.jsx)(e.span,{className:"mopen",children:"("}),(0,n.jsx)(e.span,{className:"mord",children:"0"}),(0,n.jsx)(e.span,{className:"mpunct",children:","}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mord",children:"1"}),(0,n.jsx)(e.span,{className:"mclose",children:")"}),(0,n.jsx)(e.span,{className:"mpunct",children:";"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mord mathnormal",children:"i"}),(0,n.jsx)(e.span,{className:"mpunct",children:","}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.05724em"},children:"j"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,n.jsx)(e.span,{className:"mrel",children:"\u2208"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,n.jsxs)(e.span,{className:"base",children:[(0,n.jsx)(e.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,n.jsx)(e.span,{className:"mopen",children:"{"}),(0,n.jsx)(e.span,{className:"mord",children:"1"}),(0,n.jsx)(e.span,{className:"mpunct",children:","}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"minner",children:"\u2026"}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mpunct",children:","}),(0,n.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,n.jsx)(e.span,{className:"mord",children:"6"}),(0,n.jsx)(e.span,{className:"mclose",children:"}"})]})]})]}),", for a total of 12 different variables we are trying to optimize over. Additionally, given a 12-dimensional function we are trying to optimize, simulated annealing makes sure that we don't fall into a local minimum."]}),"\n",(0,n.jsx)(e.h3,{id:"why-not-something-else",children:"Why not something else?"}),"\n",(0,n.jsxs)(e.p,{children:["This is a fair question. There are two classes of algorithms that can also be used to solve this problem: ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Nonlinear_programming",children:"Non-linear optimization"})," methods, and the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Expectation%E2%80%93maximization_algorithm",children:"EM algorithm"}),"."]}),"\n",(0,n.jsxs)(e.ol,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:["I chose not to use non-linear optimization simply because I'm a bit concerned that it will trap me in a local maximum. Instead of running multiple different optimizations from different starting points, I can just use simulated annealing to take that into account. In addition, throughout the course of testing the simulated annealing code converged ",(0,n.jsx)(e.em,{children:"incredibly"})," quickly - far more quickly than any non-linear solver would be able to accomplish."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:["The EM Algorithm was originally what I intended to write this blog post with. Indeed, the post was inspired by the ",(0,n.jsx)(e.a,{href:"http://web.stanford.edu/class/stats366/hmmR2.html",children:"crooked casino"})," example which uses the EM algorithm to solve it. However, after modeling the likelihood function I realized that the algebra would very quickly get out of hand. Trying to compute all the polynomial terms would not be fun, which would be needed to actually optimize for each parameter. So while the EM algorithm would likely be much faster in raw speed terms, the amount of time needed to program and verify it meant that I was far better off using a different method for optimization."]}),"\n"]}),"\n"]})]})}function d(s={}){let{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,n.jsx)(e,{...s,children:(0,n.jsx)(h,{...s})}):h(s)}},4452:function(s,e,a){a.d(e,{Z:function(){return l}});let l=a.p+"assets/images/_notebook_14_1-22c2867e2cee02c45b87635ab4d3b76a.png"},2053:function(s,e,a){a.d(e,{Z:function(){return l}});let l=a.p+"assets/images/_notebook_16_1-eaa9ebc93d4557216c77a63df7df5192.png"},2477:function(s,e,a){a.d(e,{Z:function(){return l}});let l=a.p+"assets/images/_notebook_18_1-f61745c7c099b114becca8acb3175541.png"},8960:function(s,e,a){a.d(e,{Z:function(){return l}});let l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEKCAYAAAA8QgPpAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAHVRJREFUeJzt3X20XXV95/H3hyBPEhB1yK2JkCANBgtq1PiA1KMoD1pDOrOKWFtEGGeVYKE6y1WCayZ3OmsUnDI+tIOjgjGwQBrwgTDFACkcK1MwKNCgQUyrCUkglyIUH7CQSz7zx943HC65ybk795x97zmf11pnZe/f2Wd/v+esm/M9v99vP8g2ERER47VX3QlERMTUlAISERGVpIBEREQlKSAREVFJCkhERFSSAhIREZWkgERfkPRlSRdM8D7nSPrFBO5vR46STpD0swnc99sk3TdR+4sAUM4DialE0gbgUGAYEGBgru2tExznbOCLwJNl078ATeBTtv+pwr7+yPbbx/GaE4Av2z5iPLHK104DtgGzbT843tdHtCs9kJhqDLzH9kG2p5f/7lHxKL9wd+bvbR8EHAy8k+JL+fuSjhpvCIq8d5XDRP5f3G28iImQAhJTkZ7XULhW0sOSHpN0q6RXtjx/paT/Wi6fIOlnkpZIehj40q6CufAz238C3AEsLffzCknbW2KcXe73F5L+SdJpkn4H+CvgeEm/lPRISz5/Lenbkn4JvLU1x5a39V8kPSrpnyW9r+WJ70o6Y1Ts28rV75T/ritz+f3RQ2KSjpbUlPS4pH+U9O5Rn9XnJN1Yvv7/STp8V59R9KcUkOglNwCvAAaAHwJX7mLbWcABwMuBxeOI8Q3g+JZ1A0iaDlwCnFD2Wo4D1tr+IfAR4Ltlj+nQlte+H1hqezpw5xg5vhD4LeA/Al+RtKshrZFex+9SFNl5ZQ/tm6NyfQHwfyk+r5cCHwP+ZtS+3w98AjgE2AT8913EjT6VAhJT0bfKXsZjkr4BO3oJV9h+0vbTwF8Ar5O0/xj72AYM2h62/dQ4Yj8EvHiM57YDx0ja1/aQ7R/vZl/ftL2mzP/pnTz/TJnjNtu3AauAPxhHrs/rqZXeCrzA9iW2n7H9d8C3gdNbtrnO9j22nwGuAl4zjrjRJ1JAYio61faLy8e/h2IOQdKny6GefwXWU/zifukY+xgqvxzHaybw2OhG27+k+NX+EWCrpJWSfns3+9q0m+d/bvvfWtY3Ai8bT7Jj+C1g9OT6Ror3NqJ1XulJ4MAJiBs9JgUkpqKd/bI+AzgZaNh+EXBkud1Yv8KrTjIvAr670x3aN9l+F8UQ2j8D/2c3sXaXw0sk7duyfhhFDwjg1xRDcCMGxrHfhyiG7lodBmzZzesiniMFJHrFdOAp4HFJLwQ+yZ4fiSTY0buZI+lSirmNv9jJNgOSfq8cMhum+IIfmWAfAmZJ2nuc8acBg5JeIKlBUSCvLZ+7F/gPkvaTNBc4a+RFtrcDjwJjzZf8AzAs6WOS9pb0DuAU4Jpx5hd9LgUkppqxisIy4GGKX9f3Abe3+bpdeWt5ouATwN8B+wGvHzW3MbLfacDHy/j/ArwZOLd87haKIbUhSQ8xttE5bqIoRA9TvL+zbf+0fO4vy3+HgMt4/gEDS4GvlfNEi54TpJhveS9Fb+pR4LPA+1v2nUOAoy0dPZFQ0uXA71GMNx9btr2aomu/H8VE5mLb3y+fW0LxS2oYON/2zWX7fOCr5WtutP1nHUs6IiLa0ukeyDLgpFFtn6Y4dPG1FL+S/icUx6UDpwHzKLrTl0oaGb/+AsWvr7nAXEmj9xkREV3W0QJi+3bg8VHN2ynO7AV4Ec9O3C0ErikPq9xA0eVfIGkAmG77rnK7Kyi63hERUaPxTupNhI8CN0m6hGIC8i1l+0yKs3xHbCnbhoHNLe2bee7hhhERUYM6JtHPoZjfOIyimHylhhwiImIP1dED+aDt8wFsXyfpsrJ9C889Nn1W2TZW+05JyhEkEREV2B7rvKmd6kYPZPTJXFskvQ12XLJ6fdm+Ejhd0j6S5lCcCLamvNLqE5IWlJPqZwDX7yqg7Txsli5dWnsOk+WRzyKfRT6LXT+q6GgPRNLVQIPijNoHKY66+jDw+fIS2v8G/CcA2+skrQDW8ezhvSPv6lyeexjvqk7mHRERu9fRAmL7D8d46vVjbP8p4FM7af8BcMwEphYREXsoZ6L3sEajUXcKk0Y+i2fls3hWPos903O3tJXkXntPERGdJglPwkn0iIjoQSkgERFRSQpIRERUkgISERGVpIBEjMPAwGwkdf0xMDC77rce8Tw5CitiHIqLIdTx96XKZwtHtCNHYUVERNekgERERCUpIBERUUkKSEREVJICEhERlaSAREREJSkgERFRSQpIRERU0tECIulySUOS1o5q/1NJ90u6T9JFLe1LJK0vnzuxpX2+pLWSfiLps53MOSIi2tPpHsgy4KTWBkkN4L3AMbaPAf6ybJ8HnAbMA04BLi3vgQ7wBeBs23OBuZKes8+IiOi+jhYQ27cDj49qPge4yPZwuc2jZfupwDW2h21vANYDCyQNANNt31VudwWwqJN5R0TE7tUxBzIX+F1Jd0q6TdLryvaZwKaW7baUbTOBzS3tm8u2iIio0d41xTzE9pskvQG4FjhiIgMMDg7uWG40GrnvcUTEKM1mk2azuUf76PjVeCUdDtxg+9hy/UbgYtvfKdfXA28CPgxg+6KyfRWwFNgI3GZ7Xtl+OvA22+eMES9X442OydV4o1dN1qvxqnyM+BbwDgBJc4F9bP8cWAm8T9I+kuYARwJrbG8FnpC0oJxUPwO4vgt5R0TELnR0CEvS1UADeImkByl6FF8Blkm6D3iKoiBge52kFcA6YBuwuKUrcS7wVWA/4EbbqzqZd0RE7F5uKBUxDhnCil41WYewIiKiB6WAREREJSkgERFRSQpIRERUkgISERGVpIBEREQlKSAREVFJCkhERFSSAhIREZWkgERERCUpIBERUUkKSEREVJICEhERlaSAREREJSkgERFRSQpIRERU0tECIulySUOS1u7kuf8sabukF7e0LZG0XtL9kk5saZ8vaa2kn0j6bCdzjoiI9nS6B7IMOGl0o6RZwLuAjS1t84DTgHnAKcCl5T3QAb4AnG17LjBX0vP2GRER3dXRAmL7duDxnTz1GeDjo9pOBa6xPWx7A7AeWCBpAJhu+65yuyuARR1KOSIi2tT1ORBJC4FNtu8b9dRMYFPL+paybSawuaV9c9kWERE12rubwSTtD1xIMXzVMYODgzuWG40GjUajk+EiIqacZrNJs9nco33I9sRkM1YA6XDgBtvHSvodYDXwJCBgFkVPYwFwFoDti8rXrQKWUsyT3GZ7Xtl+OvA22+eMEc+dfk/Rv4ppuTr+vkT+rqOTJGFbu9/yWd0YwlL5wPYPbQ/YPsL2HIrhqNfafgRYCbxP0j6S5gBHAmtsbwWekLSgnFQ/A7i+C3lHTCL7IqmWx8DA7LrffExSHR3CknQ10ABeIulBYKntZS2bmGeLyzpJK4B1wDZgcUtX4lzgq8B+wI22V3Uy74jJ5ynq6fnA0NC4fpRGH+n4EFa3ZQgrOqnOIay6CkiGz/pDlSGsrk6iR0yEgYHZDA1t3P2GEdFR6YHElFNfLwDq6wmkBxKdNVkn0SMiogelgERERCUpIBERUUkKSEREVJICEhERlaSAREREJSkgERFRSQpIRERUkgISERGVpIBEREQlKSAREVFJCkhERFSSAhIREZWkgERERCUdLSCSLpc0JGltS9unJd0v6V5JX5d0UMtzSyStL58/saV9vqS1kn4i6bOdzDkiItrT6R7IMuCkUW03A6+y/RpgPbAEQNLRwGnAPOAU4NLyHugAXwDOtj0XmCtp9D4jIqLLOlpAbN8OPD6qbbXt7eXqncCscnkhcI3tYdsbKIrLAkkDwHTbd5XbXQEs6mTeERGxe3XPgZwF3FguzwQ2tTy3pWybCWxuad9ctkVERI1quye6pE8A22x/baL3PTg4uGO50WjQaDQmOkRExJTWbDZpNpt7tI+O3xNd0uHADbaPbWk7E/gw8A7bT5VtFwC2fXG5vgpYCmwEbrM9r2w/HXib7XPGiJd7ove43BO9+7Hzf6r3TdZ7oqt8FCvSycDHgYUjxaO0Ejhd0j6S5gBHAmtsbwWekLSgnFQ/A7i+C3lHRMQudHQIS9LVQAN4iaQHKXoUFwL7ALeUB1ndaXux7XWSVgDrgG3A4pauxLnAV4H9gBttr+pk3hERsXsdH8Lqtgxh9b4MYXU/dv5P9b7JOoQVERE9KAUkIiIqSQGJiIhKajsPJKa+gYHZDA1trDuNiKhJJtGjsvomszOJ3u3Y+T/V+zKJHhERXZMCEhERlaSAREREJW0VEEnHdDqRiIiYWtrtgVwqaY2kxZIO7mhGERExJbRVQGwfD3wAeDnwA0lXS3pXRzOLiIhJbVyH8UqaRnE3wM8Dv6A4tvBC29/oTHrjl8N4uyeH8fZDXCiuYfrUbreaaDNmHM7WrRu6HrdfVTmMt60CIulY4EPAe4BbgMtt3y3pZcAdtg+vknAnpIB0TwpIP8StM3bOP+mmThaQ7wCXAdfZ/s2o5/7Y9pXjyrSDUkC6JwWkH+LWGTsFpJs6WUAOBH5j+5lyfS9gP9tPVsq0g1JAuicFpB/i1hk7BaSbOnkm+mpg/5b1A8q23SV0uaQhSWtb2g6RdLOkByTd1HpUl6QlktZLul/SiS3t8yWtlfQTSZ9tM+eIiOigdgvIfrZ/NbJSLh/QxuuWASeNarsAWG37KOBWYAmApKOB04B5wCkUhw6PVMMvAGfbngvMlTR6nxER0WXtFpBfS5o/siLpdcBvdrE9ALZvBx4f1XwqsLxcXk5xVBfAQuAa28O2NwDrgQWSBoDptu8qt7ui5TUREVGTdi/n/mfAtZIeohgQHQDeVzHmobaHAGxvlXRo2T4TuKNluy1l2zCwuaV9c9keERE1aquA2L5L0iuBo8qmB2xvm6AcMksWETEFjeeGUm8AZpevmV/O2F9RIeaQpBm2h8rhqUfK9i0UZ7qPmFW2jdU+psHBwR3LjUaDRqNRIc2IiN7VbDZpNpt7tI92D+O9EngFcC/wTNls2+e18drZwA22jynXLwYes32xpD8HDrF9QTmJfhXwRoohqluA37ZtSXcC5wF3AX8LfN72qjHi5TDeLslhvP0Qt87YOYy3m6ocxttuD+T1wNHj/WaWdDXQAF4i6UFgKXARxXzKWcBGiiOvsL1O0gpgHbANWNwS71zgqxTXVLhxrOIRERHd024P5FrgPNsPdz6lPZMeSPekB9IPceuMnR5IN3WyB/JSYJ2kNbRcVc32wvEEi4iI3tFuARnsZBIRETH1tH05d0mHU0xqr5Z0ADDN9i87ml0FGcLqngxh9UPcOmNnCKubOnYtLEkfBq4Dvlg2zQS+Nb70IiKil7R7KZNzgeMobiKF7fXAobt8RURE9LR2C8hTtp8eWZG0NzmDPCKir7VbQL4j6UJg//Je6NcCN3QurYiImOzaPQ9kL+Bs4ESKGbWbgMsm42x1JtG7J5Po/RC3ztiZRO+mjt2RcCpJAemeFJB+iFtn7BSQburYiYSSfsZO/oJsHzGeYBER0TvGcy2sEfsBfwC8eOLTiYiIqaLyEJakH9h+3QTns8cyhNU9GcLqh7h1xs4QVjd1cghrfsvqXhQ9kvHcSyQiInpMu0XgkpblYWAD5WXYIyKiP+UorKgsQ1j9ELfO2BnC6qZODmF9bFfP2/5f4wkaERFTX7tnor8eOIfiIoozgT8B5gPTy8e4SfqopB9KWivpKkn7SDpE0s2SHpB0k6SDW7ZfImm9pPslnVglZkRETJx2z0T/e+A9I5dvlzQd+Fvbv1spqPQy4HbglbaflvQ3wI3A0cDPbX96jPulvwGYBaymvF/6TvadIawuyRBWP8StM3aGsLqpY5dzB2YAT7esP1227YlpwAvLCzPuD2wBTgWWl88vBxaVywuBa2wP294ArAcW7GH8iJjU9kVSLY+Bgdl1v/kpod2jsK4A1kj6Zrm+iGe/6MfN9kOSLgEeBJ4Ebi5vVDXD9lC5zVZJI5eMnwnc0bKLLWVbRPSsp6ir1zU0NK4f4n2rrQJi+39I+jZwfNn0Idv3VA0q6UUUvY3DgSeAayV9gOf/taT/2oaBgdkMDW2sO42I6DPjORnwAOAXtpdJ+neS5tj+WcW47wR+avsxgLJn8xZgaKQXImkAeKTcfgvw8pbXzyrbdmpwcHDHcqPRoNFoVExzaiiKR13j8hExFTWbTZrN5h7to91J9KUUR2IdZXtuOQl+re3jKgWVFgCXU0yKPwUsA+4CDgMes33xGJPob6QYurqFTKLv0H+T2f05oZz33N3Y/fg90pHzQIDfB14L3A075jAqHb5bvn6NpOuAe4Bt5b9fojgkeIWks4CNlGe7214naQWwrtx+cd9ViYiISabdHsga2wsk3W17vqQXAnfYPrbzKY5PeiBdjdxnceuMnffc7dj9+D3SqcN4V0j6IvAiSR+mOA/jy+NNMCIiekfb18Iq74W+45a2tm/pZGJVpQfS1ch9FrfO2HnP3Y7dj98jE35LW0nTgNW2374nyXVLCkhXI/dZ3Dpj5z13O3Y/fo9M+BCW7WeA7a3XpYqIiGj3KKxfAfdJugX49Uij7fM6klVEREx67RaQb5SPiIgIYDdzIJIOs/1gF/PZY5kD6WrkPotbZ+y8527H7sfvkYmeA/lWy86/XimriIjoSbsrIK3V6IhOJhIREVPL7gqIx1iOiIg+t7s5kGcojroSxU2fnhx5CrDtgzqe4ThlDqSrkfssbp2x8567Hbsfv0cm9GKKtqftWUoREdGr2r0WVkRExHOkgERERCUpIBERUUkKSEREVFJbAZF0sKRrJd0v6UeS3ijpEEk3S3pA0k2tF3CUtETS+nL7E+vKOyIiCnX2QD4H3Gh7HvBq4MfABRSXjj8KuBVYAlDeE/00YB5wCnCpimNXIyKiJrUUEEkHAcfbXgZge9j2E8CpwPJys+XAonJ5IXBNud0GYD2woLtZR0REq7p6IHOARyUtk3S3pC9JOgCYYXsIwPZW4NBy+5nAppbXbynbIiKiJu1ezr0TcecD59r+vqTPUAxfjT71s9KpoIODgzuWG40GjUajWpYRET2q2WzSbDb3aB9t3xN9IkmaAdxh+4hy/a0UBeQVQMP2kKQB4Dbb8yRdQHHplIvL7VcBS21/byf7zqVMuhe5z+LWGTvvudux+/F7ZMJvadsJ5TDVJklzy6YTgB8BK4Ezy7YPAteXyyuB0yXtI2kOcCSwpnsZR0TEaHUNYQGcB1wl6QXAT4EPAdOAFZLOAjZSHHmF7XWSVgDrgG3A4r7rZkRETDK1DGF1Uoawuhq5z+LWGTvvudux+/F7ZEKvxhvtGxiYzdDQxrrTiIjomvRAJi4u+YXY63HrjJ333O3YvfbduDvpgURETIh9qeNiFzNmHM7WrRu6Hreq9EAmLi75hdjrceuMnffcH7Hr6/lMmcN4IyJi6ksBiYiISlJAIiKikhSQiIioJAUkIiIqSQGJiIhKUkAiIqKSFJCIiKgkBSQiIipJAYmIiEpSQCIiopIUkIiIqKTWAiJpL0l3S1pZrh8i6WZJD0i6SdLBLdsukbRe0v2STqwv64iIgPp7IOdT3KZ2xAXAattHAbcCSwAkHU1xe9t5wCnAparjWssREbFDbQVE0izg3cBlLc2nAsvL5eXAonJ5IXCN7WHbG4D1wIIupRoRETtRZw/kM8DHee5F92fYHgKwvRU4tGyfCWxq2W5L2RYRETWp5Y6Ekt4DDNm+V1JjF5tWurPK4ODgjuVGo0GjsasQERH9p9ls0mw292gftdyRUNIngT8ChoH9genAN4HXAw3bQ5IGgNtsz5N0AWDbF5evXwUstf29new7dyRM3B6MnffcH7FzR8Ldsn2h7cNsHwGcDtxq+4+BG4Azy80+CFxfLq8ETpe0j6Q5wJHAmi6nHRERLWoZwtqFi4AVks4CNlIceYXtdZJWUByxtQ1YXEs3IyIidqhlCKuTMoSVuL0ZO++5P2JnCCsiIvpACkhERFSSAhIREZWkgERERCUpIBERUUkKSEREVJICEhERlaSAREREJZPtTPQJ8eSTT9adQkREBfsylW511JNnou+99/5djbl9+zDbt2+jH8+a7a+4dcbOe+6P2PW+5/Geid6TPZDh4W73QK4EzuhyzIiIemUOJCIiKkkBiYiISlJAIiKikhSQiIioJAUkIiIqqaWASJol6VZJP5J0n6TzyvZDJN0s6QFJN0k6uOU1SyStl3S/pBPryDsiIp5VVw9kGPiY7VcBbwbOlfRK4AJgte2jgFuBJQCSjqa4ve084BTgUk2ls20iInpQLQXE9lbb95bLvwLuB2YBpwLLy82WA4vK5YXANbaHbW8A1gMLupp0REQ8R+1zIJJmA68B7gRm2B6CosgAh5abzQQ2tbxsS9kWERE1qfVMdEkHAtcB59v+laTR5/BXPKd/sGW5UT4iIuJZzfJRXW0FRNLeFMXjStvXl81DkmbYHpI0ADxStm8BXt7y8lll2xgGJzzfiIje0uC5P67/27j3UOcQ1leAdbY/19K2EjizXP4gcH1L++mS9pE0BzgSWNOtRCMi4vlq6YFIOg74AHCfpHsohqouBC4GVkg6C9hIceQVttdJWgGsA7YBi91rlxGOiJhievJy7t2/HPLI1Xhz6enejltn7Lzn/og9tS7nXvtRWBERMTWlgERERCUpIBERUUkKSEREVJICEhERlaSAREREJSkgERFRSQpIRERUkgISERGVpIBEREQlKSAREVFJCkhERFSSAhIREZWkgERERCUpIBERUcmUKiCSTpb0Y0k/kfTndecTEdHPpkwBkbQX8NfAScCrgPdLemW9WU12zboTmESadScwiTTrTmASadadwJQ2ZQoIsABYb3uj7W3ANcCpNec0yTXrTmASadadwCTSrDuBSaRZdwJT2lQqIDOBTS3rm8u2iIiowd51J9AJBx303q7G27ZtM7/5TVdDRkTUTnZdN3AfH0lvAgZtn1yuXwDY9sWjtpsabygiYpKxrfFsP5UKyDTgAeAE4GFgDfB+2/fXmlhERJ+aMkNYtp+R9BHgZoq5m8tTPCIi6jNleiARETG5TKWjsMYkaZakWyX9SNJ9ks6rO6e6SdpL0t2SVtadS50kHSzpWkn3l38fb6w7p7pI+qikH0paK+kqSfvUnVO3SLpc0pCktS1th0i6WdIDkm6SdHCdOXbLGJ/Fp8v/I/dK+rqkg9rZV08UEGAY+JjtVwFvBs7NSYacD6yrO4lJ4HPAjbbnAa8G+nLYU9LLgD8F5ts+lmL4+vR6s+qqZRQnIbe6AFht+yjgVmBJ17Oqx84+i5uBV9l+DbCeNj+Lniggtrfavrdc/hXFl0TfniMiaRbwbuCyunOpU/kr6njbywBsD9v+Rc1p1Wka8EJJewMHAA/VnE/X2L4deHxU86nA8nJ5ObCoq0nVZGefhe3VtreXq3cCs9rZV08UkFaSZgOvAb5Xbya1+gzwcaDfJ7jmAI9KWlYO531J0v51J1UH2w8BlwAPAluAf7W9ut6saneo7SEofoQCh9acz2RxFvDtdjbsqQIi6UDgOuD8sifSdyS9Bxgqe2QqH/1qb2A+8L9tzweepBi26DuSXkTxi/tw4GXAgZL+sN6sJp1+/8GFpE8A22xf3c72PVNAym75dcCVtq+vO58aHQcslPRT4GvA2yVdUXNOddkMbLL9/XL9OoqC0o/eCfzU9mO2nwG+Abyl5pzqNiRpBoCkAeCRmvOplaQzKYa+2/5h0TMFBPgKsM725+pOpE62L7R9mO0jKCZJb7V9Rt151aEcntgkaW7ZdAL9e2DBg8CbJO0nSRSfRb8dUDC6R74SOLNc/iDQTz88n/NZSDqZYth7oe2n2t1JTxQQSccBHwDeIemecrz75LrziknhPOAqSfdSHIX1yZrzqYXtNRQ9sHuAf6T48vhSrUl1kaSrgX8A5kp6UNKHgIuAd0kaucLFRXXm2C1jfBZ/BRwI3FJ+f17a1r5yImFERFTREz2QiIjovhSQiIioJAUkIiIqSQGJiIhKUkAiIqKSFJCIiKgkBSQiIipJAYmIiEr+P71BWn/o4C2PAAAAAElFTkSuQmCC"},1875:function(s,e,a){a.d(e,{Z:function(){return l}});let l=a.p+"assets/images/_notebook_20_1-ea40789d2365d20a0725aca866680217.png"},1270:function(s,e,a){a.d(e,{Z:function(){return l}});let l=a.p+"assets/images/_notebook_22_1-210909ddb46467b78aa3f65c8ae519fd.png"},4707:function(s,e,a){a.d(e,{Z:function(){return l}});let l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEMCAYAAADqG+D0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAG2RJREFUeJzt3X20XXV95/H3ByJP8lB8gKsJTz6EBlrEIPGBihetgG150I4RdRURdLkUBWtnRsJ0hminU+laiFgLqz5hYMAIKAothZAFV8ZpNRRJQZKBVA0QMBcfEEVYmJDP/LF/lxxubpJzd7LPvvecz2uts7LP7+y9f9+zc8/5nt/D3lu2iYiImKwd2g4gIiKmpySQiIioJQkkIiJqSQKJiIhakkAiIqKWJJCIiKglCSQiImpJAomIiFqSQGK7k/RjSW/cwus/kHR0D+O5VNInt/D6FuOdqvrpOE8m1un6/9WPZrQdQAwe27/XdgyDYDod5+kUa2yUBBLPIul1wF8BTwHXALsAvw/cZfuSNmPrJznO0Q/ShRXPYvtfgPXAZ2x/2fbFtj8IvEPS8CR2NU/SPZJ+LulLknYae6GzC0LSxyX9h6RflW6Mkzt3Ul5fU15fKemYUv4iSddIekTSDyV9pGObV0q6Q9JjkhZTfTl3RdIcSbdKelTS3ZJOKOWnSbquY71Vkr7W8fwBSYd1W88AH+dXSvr3cnwXj8U7vltK0lxJ3y/7vqqs+8nN7Oerne87eicJJJ5F0nOAVwPfGffSd4GTN91is94FvBl4KXAw8JebWe8/gKNs7wl8AvjfkvYtscwGzgSOKK8fB6yWJOB64E7gRcCbgLMlvbnEfy2wCHgecDXwp90ELGkGcB1wI/BC4CzgCkkvB74N/EFZ70XAc4DXlucvAZ5r+67uDs1AH+e3A8cCBwGHAaeNX6Hs+xvAl8u+vwq8dQv7ecVE+4nmJYHEeK8G7rH9xLjyFwFPT2I/f2f7Ydu/BP6a6otuE7a/bnu0LF8NrALmlZefBnYCfk/SDNsP2P4xcCTwAtt/bftp26uBLwLvBF4DzLD92fLa14Hbu4z5NVSJ4Hzb623fCvwj8M5S768lHQ4cDdwEPFy+fI8G/s8kjg0M7nG+yPZoifd64PAJ1nkNsKPtz5V9Xwssq7GfaFgSSIz3RuDWzoLyS/QYYLmkt0la0MV+1nQs30/1xbgJSadKurN0RTwKHAq8AMD2D4GPAguBRyRdWX79HwDMlPSL8ngUWADsA7wYeGhcNfd3ES9l2wcn2HZmWb6N6jgcDYyUxzDwBqoWymRs6TiPSHqZpLdK+h+S5m5hP9PtOI92LD8B7D7BOhPte/z/Szf7iYYlgcR4xzDuiw14C/CI7cuBO6i6b7Zmv47lA4CHx68gaX/g88CHbO9te2/gHkBj69hebPv1wP6l6FNUXyY/sv288tjb9l62/wT4CRu/8MfsT3cenmDd/dn4ZfZtqoTxB2X5NqrkcTSTTyBbOs7XAyeUei8E/vMW9jMdj/PWTLTv/SZaMdqVBBLPkLQrMBf4vx1lBwJ/AfynSe7uTEkzJT0POBdYPME6zwU2AD+TtIOk9wLPTOeUNFvSMWWA9LfAk1TdLcuoupP+q6RdJO0o6VBJrwL+FVgv6SOSZkh6Gxu7arbme8Bvyn5nlMHsP+mI/dtUX/y72n6YqtvqeOD5VOMEY3FfKunLm6ukm+Ns+0Lby4BZwI+3EPN0PM5b86/A05LOLHWetB33HdtREkgAIOlI4Hzg18C7JL1P0l8A7wfeXvq/u2XgSmAJ1eDtKqr++c7Xsb0SuIBq4HgtVbdK56DyzlS/hH9K9cv6hcC5tjdQfbEfTvXl+gjwBWBP2+uAtwHvBX5ONdj69S7ipWx7AvBHwM+AzwF/Zvu+8voqquNzW3n+a+CHwHf87Ft77semg+NAreN8Ms8+duPjnnbHeWuvdez7fcCjVOM611NNed7afqKH1OQtbSXtTPVh24nqnJNrbH9C0t7A16ia3KuB+bYfK9ssAE6nmuJ4tu0lpXwu8BWqqYI32P5oY4HHZkk6ADjN9ifajmUqKjOIlgOH2Z7MYPhE+zqBapxlqCSvgSXpu8Althe1HUts1GgLxPZTwDG2X0n1K+YtkuYB5wBLbR8M3EI1MIekQ4D5wByq/uCLy8AiwCXAGbZnA7MlHddk7LEpSbtTdbEcIenQtuOZimyvs33odkgebwX+O9Wv+vnbJbhpRNLRkvYtXVjvoTrJ8sa244pna/xM9I5pijuX+gycRDX4CNU88hGqpHIisNj2eqp56KuoTpS6H9jD9tg0wcuomvY3NR1/bGT7caqukAvajqXflamr17YdR4sOBq4CdgN+BPzp2DTkmDoaTyCSdqCaufNS4O9t3y5p34456Wsl7VNWn0k1gDbmoVK2nmdPV1zDprM0IqJP2P4C1XhLTGGND6Lb3lC6sGZRtSYOZdNBsAyKRURMMz27mKLtX0kaoZr2ODrWCpE0RDW7A6oWR+d871mlbHPlm5CUZBQRUYNtbX2tjRptgUh6gaS9yvKuVNfsWUl1vaHTymrvAb5Vlq8DTpG0k6SDgJcBy2yvBR6TNK8Mqp/asc0mbOdhc95557Uew1R55FjkWORYbPlRR9MtkBcBi8o4yA7A12zfUKbkXSXpdKrLH8wHsL1C0lXACmAd1ZmzY+/sTJ49jTczMiIiWtRoArF9N9UZt+PLfwH84Wa2+RvgbyYov4NqKl9EREwBORO9jw0PD7cdwpSRY7FRjsVGORbbptEz0dsgyf32niIimiYJT6VB9IiI6F9JIBERUUsSSERE1JIEEhERtSSBRERELUkgERFRSxJIRETUkgQSERG1JIFEREQtSSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUsSSERE1JIEEhERtSSBRERELUkgERFRSxJIRETUkgQSERG1JIFEREQtSSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUujCUTSLEm3SLpH0t2SPlLKz5O0RtL3y+P4jm0WSFolaaWkYzvK50q6S9J9kj7TZNwRmzM0dCCSev4YGjqw7bcesQnZbm7n0hAwZHu5pN2BO4CTgHcAv7b96XHrzwGuBI4EZgFLgZfbtqTvAR+2fbukG4CLbN80QZ1u8j3FYJMEtPH3JfJ3HU2ShG1NZptGWyC219peXpYfB1YCM8vLEwV6ErDY9nrbq4FVwLySiPawfXtZ7zLg5CZjj4iILevZGIikA4HDge+Vog9LWi7pi5L2KmUzgQc7NnuolM0E1nSUr2FjIoqIiBb0JIGU7qtrgLNLS+Ri4CW2DwfWAhf0Io6IiNh+ZjRdgaQZVMnjctvfArD9045VvgBcX5YfAvbreG1WKdtc+YQWLlz4zPLw8DDDw8O144+I6EcjIyOMjIxs0z4aHUQHkHQZ8DPbH+soG7K9tiz/OXCk7XdJOgS4Ang1VRfVzWwcRP8ucBZwO/BPwGdt3zhBfRlEj8ZkED36VZ1B9EZbIJKOAt4N3C3pTqpP3rnAuyQdDmwAVgMfALC9QtJVwApgHfChjmxwJvAVYBfghomSR0RE9E7jLZBeSwskmpQWSPSrKTeNNyIi+lcSSERE1JIEEhERtSSBRERELUkgERFRSxJIRETUkgQSERG1JIFEREQtSSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUsSSERE1JIEEhERtSSBRERELUkgERFRSxJIRETUkgQSERG1JIFEREQtSSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUsSSERE1JIEEhERtSSBRERELUkgERFRS6MJRNIsSbdIukfS3ZLOKuV7S1oi6V5JN0naq2ObBZJWSVop6diO8rmS7pJ0n6TPNBl3RERsXdMtkPXAx2wfCrwWOFPS7wLnAEttHwzcAiwAkHQIMB+YA7wFuFiSyr4uAc6wPRuYLem4hmOPiIgtaDSB2F5re3lZfhxYCcwCTgIWldUWASeX5ROBxbbX214NrALmSRoC9rB9e1nvso5tIiKiBT0bA5F0IHA48F1gX9ujUCUZYJ+y2kzgwY7NHiplM4E1HeVrSllERLRkRi8qkbQ7cA1wtu3HJXncKuOfb5OFCxc+szw8PMzw8PD23H1ExLQ3MjLCyMjINu1D9nb97t60AmkG8I/AP9u+qJStBIZtj5buqVttz5F0DmDb55f1bgTOA+4fW6eUnwK8wfYHJ6jPTb+nGFzVkFwbf18if9fRJEnY1tbX3KgXXVhfBlaMJY/iOuC0svwe4Fsd5adI2knSQcDLgGWlm+sxSfPKoPqpHdtEREQLGm2BSDoKuA24m+pnm4FzgWXAVcB+VK2L+bZ/WbZZAJwBrKPq8lpSyo8AvgLsAtxg++zN1JkWSDQmLZDoV3VaII13YfVaEkg0KQkk+tVU7cKKiIg+lAQSERG1JIFEREQtSSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUtXCUTS7zcdSERETC/dtkAulrRM0oc67x4YERGDq6sEYvv1wLuprl11h6QrJb250cgiImJKm9S1sCTtSHUnwM8CvwIEnGv7G82EN3m5FlY0KdfCin7V2LWwJB0m6UKqW9K+ETih3JvjjcCFk440IiKmva5aIJK+DXwRuMb2k+Ne+zPblzcU36SlBRJNSgsk+lVjl3Mvt6R90vbT5fkOwC62n6gVaYOSQKJJSSDRr5q8nPtSYNeO57uVsoiIGFDdJpBdbD8+9qQs79ZMSBERMR10m0B+I2nu2JNye9knt7B+RET0uRldrvdR4GpJD1NN3R0C3tFYVBERMeV1fR6IpOcAB5en99pe11hU2yCD6NGkDKJHv2psFlbZ+euAA+lotdi+bDKV9UISSDQpCST6VZ0E0lUXlqTLgZcCy4GnS7GBKZdAIiKiN7odA3kVcEh+2kdExJhuZ2H9gGrgPCJasTOSWnkMDR3Y9puPKarbFsgLgBWSlgFPjRXaPrGRqCJinKdoZ+wFRkcn1S0eA6TbBLKwySAiImL6mcwsrAOAl9teKmk3YEfbv240uhoyCyua1OYsrLZaIJkBNhiavJz7+4FrgH8oRTOBb04uvIiI6CfdDqKfCRxFdRMpbK8C9tnaRpK+JGlU0l0dZedJWiPp++VxfMdrCyStkrRS0rEd5XMl3SXpPkmf6fbNRX8aGjqwtQHliNio2wTylO3fjj2RNIPu2tOXAsdNUP5p23PL48ayzznAfGAO8Baq+7CPfWIvAc6wPRuYLWmifcaAGB29n+rPr41HRIzpNoF8W9K5wK7lXuhXA9dvbSPb3wEeneCliX7KnQQstr3e9mpgFTBP0hCwh+3by3qXUd1WNyIiWtRtAjkH+ClwN/AB4AbgL7eh3g9LWi7pi5L2KmUzgQc71nmolM0E1nSUryllERHRoq6m8dreAHyhPLbVxcAnbVvS/wQuAN63Hfb7jIULFz6zPDw8zPDw8PbcfUTEtDcyMsLIyMg27aPbW9r+mAk6gG2/pIttDwCut33Yll6TdE61S59fXrsROA+4H7jV9pxSfgrwBtsf3Ex9mcbb59qbSgvtTafNNN5oVmMXU6S6FtaYXYC3A8/rNi46xjwkDdleW56+jeoyKQDXAVdIupCqi+plwLLSUnlM0jzgduBU4LNd1h0REQ3p+kTCTTaU7rB9xFbWuRIYBp4PjFK1KI4BDgc2AKuBD9geLesvAM4A1gFn215Syo8AvkKVvG6wffYW6kwLpM+lBdL7uvOZ6n+N3Q+k83a2VAPvrwI+aPsVkwuxeUkg/S8JpPd15zPV/5rswrqgY3k9Vcth/mQqioiI/lK7C2uqSguk/6UF0vu685nqf03ekfBjW3rd9qcnU2lEREx/k5mFdSTVTCmAE4BlVGeLR0TEAOp2EP024I/HLt8uaQ/gn2wf3XB8k5YurP6XLqze153PVP9r7HLuwL7Abzue/7aURUTEgOq2C+syYJmka8vzk4FFzYQUERHTwWTuSDgXeH15epvtOxuLahukC6v/pQur93XnM9X/muzCAtgN+JXti4A1kg6aVHQREdFXuh1EP49qJtbBtmdLejFwte2jmg5wstIC6X9pgfS+7nym+l+TLZC3AicCvwGw/TCwx+TCi4iIftJtAvlt+VlvAEnPbS6kiIiYDrpNIFdJ+gfgdyS9H1jK9rm5VERETFOTmYX1ZuBYqs7Ym2zf3GRgdWUMpP9lDKT3decz1f8auZy7pB2BpbaP2ZbgeiUJpP8lgfS+7nym+l8jg+i2nwY2SNqrdmQREdF3uj0T/XHgbkk3U2ZiAdg+q5GoIiJiyus2gXyjPCIiIoCtjIFI2t/2Az2MZ5tlDKT/ZQyk93XnM9X/mhgD+WbHzr9eK6qIiOhLW0sgndnoJU0GEhER08vWEog3sxwREQNua2MgT1PNuhKwK/DE2EuAbe/ZeISTlDGQ/pcxkN7Xnc9U/6szBrLFWVi2d9y2kCIiol9N5n4gERERz0gCiYiIWpJAIiKiliSQiIiopdEEIulLkkYl3dVRtrekJZLulXRT50UaJS2QtErSSknHdpTPlXSXpPskfabJmCMiojtNt0AuBY4bV3YO1eXhDwZuARYASDoEmA/MAd4CXKxqvibAJcAZtmcDsyWN32dERPRYownE9neAR8cVnwQsKsuLgJPL8onAYtvrba8GVgHzJA0Be9i+vax3Wcc2ERHRkjbGQPaxPQpgey2wTymfCTzYsd5DpWwmsKajfE0pi4iIFnV7OfcmbfdTXBcuXPjM8vDwMMPDw9u7ioiIaW1kZISRkZFt2kfX90SvXYF0AHC97cPK85XAsO3R0j11q+05ks6hujzK+WW9G4HzgPvH1inlpwBvsP3BzdSXS5n0uVzKpPd15zPV/xq5pe12IJ59Vd/rgNPK8nuAb3WUnyJpJ0kHAS8DlpVursckzSuD6qd2bBMRES1ptAtL0pXAMPB8SQ9QtSg+BVwt6XSq1sV8ANsrJF0FrADWAR/qaEqcCXwF2AW4wfaNTcYdERFb13gXVq+lC6v/pQur93XnM9X/pmoXVkRE9KEkkIiIqCUJJCIiakkCiYiIWpJAIiKiliSQiIioJQkkIiJqSQKJiIhakkAiIqKWJJCIiKglCSQiImpJAomIiFqSQCIiopYkkIiIqCUJJCIiakkCiYiIWpJAIiKiliSQiIiopdF7okdEP9i53Ea4t/bd9wDWrl3d83qje7knetQ2NHQgo6P3t1R77one/3XnXuy9VOee6EkgUVv1qzRfpv1db5t1J4H0Up0EkjGQiIioJQkkIiJqSQKJiIhakkAiIqKWTOPtA+3OhoqIQZVZWH1g8GZDDeaMpEF8z4P2WW5TnVlYaYFExBTVzgmMADvssBsbNjzR83qn28mTrbVAJK0GHgM2AOtsz5O0N/A14ABgNTDf9mNl/QXA6cB64GzbSzaz31ZaIO13Iw3Sr+LB/DWe9zwIdbfX6ppWJxJK+hFwhO1HO8rOB35u+28lfRzY2/Y5kg4BrgCOBGYBS4GXT5Qp2kog7XUjweB9wHOsB6PuwXzP0ymBtDkLSxPUfxKwqCwvAk4uyycCi22vt70aWAXM60WQERExsTYTiIGbJd0u6X2lbF/bowC21wL7lPKZwIMd2z5UyiIioiVtDqIfZfsnkl4ILJF0L5u2GTMFIyJiimotgdj+Sfn3p5K+SdUlNSppX9ujkoaAR8rqDwH7dWw+q5RNaOHChc8sDw8PMzw8vH2Dj4iY5kZGRhgZGdmmfbQyiC5pN2AH249Lei6wBPgE8CbgF7bP38wg+qupuq5uJoPonbW3VPeg1dtm3XnPg1H39BpEb6sFsi9wrSSXGK6wvUTSvwFXSToduB+YD2B7haSrgBXAOuBDA3e2YETEFJMz0bdfvQzir6XBqrfNuvOeB6Pu6dUCycUUIyKiliSQiIioJQkkIiJqSQKJiIhakkAiIqKWJJCIiKglCSQiImpJAomIiFqSQCIiopa+vKXttdde23YIERF9ry8vZbLnnidvfcXtaN26B3jyye8ziJddGKx626w773kw6p5elzLpywTS+//4y4FTGcQ/9sGqt826854Ho+7plUAyBhIREbX05RhIRMT0tHO5svf0kAQSETFlPEW73XaTky6siIioJQkkIiJqSQKJiIhakkAiIqKWJJCIiKglCSQiImpJAomIiFqSQCIiopYkkIiIqCUJJCIiakkCiYiIWpJAIiKiliSQiIioZVolEEnHS/p/ku6T9PG244mIGGTTJoFI2gH4HHAccCjwTkm/225UU91I2wFMISNtBzCFjLQdwBQy0nYA09q0SSDAPGCV7fttrwMWAye1HNMUN9J2AFPISNsBTCEjbQcwhYy0HcC0Np0SyEzgwY7na0pZRES0oC/vSLjnnif0tL5169bw5JM9rTIionWy27p94uRIeg2w0Pbx5fk5gG2fP2696fGGIiKmGNuTuq/tdEogOwL3Am8CfgIsA95pe2WrgUVEDKhp04Vl+2lJHwaWUI3dfCnJIyKiPdOmBRIREVPLdJqFtVmSZkm6RdI9ku6WdFbbMbVN0g6Svi/purZjaZOkvSRdLWll+ft4ddsxtUXSn0v6gaS7JF0haae2Y+oVSV+SNCrpro6yvSUtkXSvpJsk7dVmjL2ymWPxt+UzslzS1yXt2c2++iKBAOuBj9k+FHgtcGZOMuRsYEXbQUwBFwE32J4DvAIYyG5PSS8GPgLMtX0YVff1Ke1G1VOXUp2E3OkcYKntg4FbgAU9j6odEx2LJcChtg8HVtHlseiLBGJ7re3lZflxqi+JgT1HRNIs4I+AL7YdS5vKr6jX274UwPZ6279qOaw27Qg8V9IMYDfg4Zbj6Rnb3wEeHVd8ErCoLC8CTu5pUC2Z6FjYXmp7Q3n6XWBWN/vqiwTSSdKBwOHA99qNpFUXAv8FGPQBroOAn0m6tHTnfV7Srm0H1QbbDwMXAA8ADwG/tL203ahat4/tUah+hAL7tBzPVHE68M/drNhXCUTS7sA1wNmlJTJwJP0xMFpaZCqPQTUDmAv8ve25wBNU3RYDR9LvUP3iPgB4MbC7pHe1G9WUM+g/uJD034B1tq/sZv2+SSClWX4NcLntb7UdT4uOAk6U9CPgq8Axki5rOaa2rAEetP1v5fk1VAllEP0h8CPbv7D9NPAN4HUtx9S2UUn7AkgaAh5pOZ5WSTqNquu76x8WfZNAgC8DK2xf1HYgbbJ9ru39bb+EapD0Ftunth1XG0r3xIOSZpeiNzG4EwseAF4jaRdJojoWgzahYHyL/DrgtLL8HmCQfng+61hIOp6q2/tE2091u5O+SCCSjgLeDbxR0p2lv/v4tuOKKeEs4ApJy6lmYf2vluNphe1lVC2wO4F/p/ry+HyrQfWQpCuBfwFmS3pA0nuBTwFvljR2hYtPtRljr2zmWPwdsDtwc/n+vLirfeVEwoiIqKMvWiAREdF7SSAREVFLEkhERNSSBBIREbUkgURERC1JIBERUUsSSERE1JIEEhERtfx/t8CCaUQXJ5cAAAAASUVORK5CYII="},9724:function(s,e,a){a.d(e,{Z:function(){return l}});let l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAEMCAYAAADqG+D0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAGuhJREFUeJzt3X2UXXV97/H3ByIC8lAskmCigNUg4ANGDSrLdkB50CqgvSLiKuLTcikCVXsvhNpL7JPStRTQXlxVEQMXmgv4BJZCYOHUZXslEUGQ5EJaDZBABhVEKQgJ+dw/9m/gOJmHM3uyz54583mtdVb2+Z398N1nJvM5v9/eZ2/ZJiIiYrK2a7uAiIiYmRIgERFRSwIkIiJqSYBEREQtCZCIiKglARIREbUkQCIiopYESMw4ki6S9Fc92M7PJB0+zus/kfSHTdfRsb2e7Hev9et+zQYJkIiabL/E9vfarmPYRIHXxfKnSFol6beSvrota5sKSSdIWi3pEUlrJR3adk1RmdN2ATH9SXod8NfA48CVwI7AS4HbbH+xzdrGMhNrngY2UL1nRwE7tVwLAJKOAD4NHG97laS9264pnpYeSEzI9r8Dm4HzbH/V9gW2Pwy8U9JAN+uQdIak/5D06zL0c9yI138m6ROSfizpIUn/JGmH8torJN0s6WFJy6nCoPGai8WS7pD0S0kXDtfUUfPhXe7fGZLWl9fXSDqstO8t6UpJD0j6T0mndizT9X5Luhh4PnB12cafS3qxpO+W9/N2SW+d4D37lu2rgAcnelPG29/xfpaT3S9gKfBXtleVGu+3ff9E9UVvJEBiQpKeARwCfH/ESz8Ajtt6iVH9B3Co7d2ATwH/W9LcEfO8AzgS2A94OXBy2fY3gWXAs4ErgD/pUc0AJwJHAH8A7A98coz5xtw/SQuBU4BXltePAtZJEnA1cAuwN/AG4HRJR0x2v22fBNwDvKVs47yy7muB5wCnAZdKetEk9n08E/08t/pZwlM/l672S9J2wKuAvcrQ1T2SviDpmdtoH2KKEiDRjUOAO2w/OqJ9b+DJblZg++u2h8r0FcBaYPGI2c63PWT7V1R//A4GXgPMsf1520/a/jqwqhc1F1+wfV+p6W+pAmUrE+zfk8AOwEskzbF9j+2fAa8G9rT9t2Xf1gFfAd41hf1W+fe1wLNsn2N7s+3vAt8p656yLn6eo/0sh+vqdr/mAs+gCphDyzpewdghHj2WAIluHA58t7OhfHo+DLhV0tslLRlvBZJOknRLGdJ4CDgI2HPEbEMd048CuwDPpRqb73T3FGselPRCSW+T9D8lLRpnPetHbHfUMfjx9s/2fwJ/RjUc84Cky8pY/j7AfEkPlsdDwBJgryns97C9gXtHWX7+JNYxpi5+nqP9LIfr6na/Hiv/ft72A7YfBD4HvHlq1ce2kgCJbhzGiD/GwJuAB2xfAtxM9UlxVJKeD3wJ+IjtPWzvAdzB05+Wx3M/sGBE2/OnWPPVwFup/pCdC/z5OOt5Xsf0PsB9I2foZv9sL7f9+o7aP0P1B/6ntp9dHnvY3t32W6j2e+Qf+4n2u/PeDPeNqH14+ZF/vCdtG/w8u9qv0ntZP7J5kuVGgxIgMS5JOwGLgH/raNsX+ATw37pczbOALcAvJG0n6b3AS7pc9v8CmySdKmmOpLez9dDXpGu2fa7tlVTh9LNxVneKpPmSng2cBSyf7P5JWijpsHIg+QmqT9ZPAiuB30j6H5J2lLS9pIMkvars9+bJ7DewEXhBmb4JeLSse045ceAtY9Q/XOf2knYEtgfmSHqmpO0nu78TmOx+XQScKuk5kvYAPkY1JBbTQAIkxiTp1cA5wG+AEyV9QNIngA8C7yhj9hOyvQb4LNUB7I1Uwx0jD26P+snS9iaqMfD3Ar+kOjj79W1Y83FUxzZG3TxwGbCC6qDx2hHzusv9eyZVj+PnVD2D5wBn2d5C9Uf9YKoQewD4MrBb2e+3d7vfxWeAv5T0IHAqVS/rzcAvgH8A/tT2XeMs/0mq4aYzgHeX6b/Y6k2ZeH/H7CXU2K+/Bn4I3EXVy7kZ+Ltx5o8eUu5IGFMlaR/gZNufaruWySintQ4C82yvbbmciBmn0R5I6QLfVA623S7p7NK+h6QVku6UdJ2k3TuWWVJO2Vsj6ciO9kWSbpN0l6Tzmqw7uidpF6phoVdKOqjterol6W3AX1J9+j2+5XIiZqTGeyCSdrb9aBlL/Teq89H/BPil7b+XdAawh+0zJR0IXEp1euMC4AbgRbYt6Sbgo+XbqNdQnSZ4XaPFR0TEmBo/BtJxHv4zqS6dYuBYqi8SUf4d/mLXMcDyct76Osq55ZLmAbsOfxsVuJjJfRksIiK2scYDpJylcQvVwbbrSwjM7fgS0kaq896hOr2v89z1DaVtPr97Ot96ttH57BERUU8veiBbbL+CakhqcRknHzluliP5EREzTM+uxmv715IGgaOBIUlzbQ+V4akHymwb+N0vPy0obWO1b0VSwigiogbb3XwZ9ClNn4W15/AZVuXLXUcAa4CrKBdXA94DfLtMXwWcIGkHSfsBLwRWlmGuhyUtLpejOKljma3YzsPm7LPPbr2G6fLIe5H3Iu/F+I86mu6B7A0sK1fV3A74P7avkfQD4HJJ76O6Ds7xALZXS7ocWA1sorpUwvCenQJ8jerSz9fYvrbh2iMiYhyNBojt26kuKTGy/UHgjWMs82mqG8iMbL+Z6oZAERExDeRSJn1sYGCg7RKmjbwXT8t78bS8F1PTd5cykeR+26eIiKZJwtPpIHpERPSvBEhERNSSAImIiFoSIBERUUsCJCIiakmARERELQmQiIioJQESERG1JEAiIqKWBEhERNSSAImIiFoSIBERUUsCJCIiakmARERELQmQiIioJQESERG1JEAiIqKWBEhERNSSAImIiFoSIBERUUsCJCIiakmARERELQmQiIioJQESERG1JEAiIqKWBEhERNTSaIBIWiDpRkl3SLpd0qml/WxJ6yX9qDyO7lhmiaS1ktZIOrKjfZGk2yTdJem8JuuOiIiJyXZzK5fmAfNs3yppF+Bm4FjgncBvbH9uxPwHAJcBrwYWADcAL7JtSTcBH7W9StI1wPm2rxtlm25ynyIi+pEkbGsyyzTaA7G90fatZfoRYA0wv7w8WqHHAsttb7a9DlgLLC5BtKvtVWW+i4Hjmqw9IiLG17NjIJL2BQ4GbipNH5V0q6SvSNq9tM0H7u1YbENpmw+s72hfz9NBFNEz8+bti6SeP+bN27ftXY/YSk8CpAxfXQmcXnoiFwAvsH0wsBH4bC/qiJiqoaG7Aff8UW03YnqZ0/QGJM2hCo9LbH8bwPbPO2b5MnB1md4APK/jtQWlbaz2US1duvSp6YGBAQYGBmrXHxHRjwYHBxkcHJzSOho9iA4g6WLgF7Y/3tE2z/bGMv0x4NW2T5R0IHApcAjVENX1PH0Q/QfAacAq4J+Bz9u+dpTt5SB6NEYSVa+g51smv9fRpDoH0RvtgUg6FHg3cLukW6j+550FnCjpYGALsA74EIDt1ZIuB1YDm4CPdKTBKcDXgB2Ba0YLj4iI6J3GeyC9lh5INCk9kOhX0+403oiI6F8JkIiIqCUBEhERtSRAIiKilgRIRETUkgCJiIhaEiAREVFLAiQiImpJgERERC0JkIiIqCUBEhERtSRAIiKilgRIRETUkgCJiIhaEiAREVFLAiQiImpJgERERC0JkIiIqCUBEhERtSRAIiKilgRIRETUkgCJiIhaEiAREVFLAiQiImpJgERERC0JkIiIqCUBEhERtSRAIiKilgRIRETU0miASFog6UZJd0i6XdJppX0PSSsk3SnpOkm7dyyzRNJaSWskHdnRvkjSbZLuknRek3VHRMTEmu6BbAY+bvsg4LXAKZJeDJwJ3GB7f+BGYAmApAOB44EDgDcBF0hSWdcXgffbXggslHRUw7VHRMQ4Gg0Q2xtt31qmHwHWAAuAY4FlZbZlwHFl+hhgue3NttcBa4HFkuYBu9peVea7uGOZiIhoQc+OgUjaFzgY+AEw1/YQVCED7FVmmw/c27HYhtI2H1jf0b6+tEVEREvm9GIjknYBrgROt/2IJI+YZeTzKVm6dOlT0wMDAwwMDGzL1UdEzHiDg4MMDg5OaR2yt+nf7q03IM0BvgP8i+3zS9saYMD2UBme+q7tAySdCdj2OWW+a4GzgbuH5yntJwB/ZPvDo2zPTe9TzF7VIbk2fr9Efq+jSZKwrYnnfFovhrC+CqweDo/iKuDkMv0e4Nsd7SdI2kHSfsALgZVlmOthSYvLQfWTOpaJiIgWNNoDkXQo8D3gdqqPbQbOAlYClwPPo+pdHG/7V2WZJcD7gU1UQ14rSvsrga8BOwLX2D59jG2mBxKNSQ8k+lWdHkjjQ1i9lgCJJiVAol9N1yGsiIjoQwmQiIioJQESERG1JEAiIqKWBEhERNSSAImIiFoSIBERUUsCJCIiaukqQCS9tOlCIiJiZum2B3KBpJWSPtJ598CIiJi9ugoQ268H3k117aqbJV0m6YhGK4uIiGltUtfCkrQ91Z0APw/8GhBwlu1vNFPe5OVaWNGkXAsr+lVj18KS9DJJ51LdkvZw4K3l3hyHA+dOutKIiJjxuuqBSPpX4CvAlbYfG/Han9q+pKH6Ji09kGhSeiDRrxq7nHu5Je1jtp8sz7cDdrT9aK1KG5QAiSYlQKJfNXk59xuAnTqe71zaIiJiluo2QHa0/cjwkzK9czMlRUTETNBtgPyXpEXDT8rtZR8bZ/6IiOhzc7qc78+AKyTdR3Xq7jzgnY1VFRER017X3wOR9Axg//L0TtubGqtqCnIQPZqUg+jRrxo7C6us/HXAvnT0WmxfPJmN9UICJJqUAIl+VSdAuhrCknQJ8AfArcCTpdnAtAuQiIjojW6PgbwKODAf7SMiYli3Z2H9hOrAeUREBNB9D2RPYLWklcDjw422j2mkqoiImPa6DZClTRYREREzz2TOwtoHeJHtGyTtDGxv+zeNVldDzsKKJuUsrOhXTV7O/YPAlcA/lqb5wLcmV15ERPSTbg+inwIcSnUTKWyvBfaaaCFJF0oaknRbR9vZktZL+lF5HN3x2hJJayWtkXRkR/siSbdJukvSed3uXERENKfbAHnc9hPDTyTNobt+/EXAUaO0f872ovK4tqzzAOB44ADgTVT3YR/uTn0ReL/thcBCSaOtMyIieqjbAPlXSWcBO5V7oV8BXD3RQra/Dzw0ykujjbMdCyy3vdn2OmAtsFjSPGBX26vKfBdT3VY3IiJa1G2AnAn8HLgd+BBwDfDJKWz3o5JulfQVSbuXtvnAvR3zbCht84H1He3rS1tERLSoq9N4bW8BvlweU3UB8Fe2LelvgM8CH9gG633K0qVLn5oeGBhgYGBgW64+ImLGGxwcZHBwcErr6PaWtj9jlGMetl/QxbL7AFfbftl4r0k6s1qlzymvXQucDdwNfNf2AaX9BOCPbH94jO3lNN5oTE7jjX7V2MUUqa6FNWxH4B3As7uti45jHpLm2d5Ynr6d6jIpAFcBl0o6l2qI6oXAytJTeVjSYmAVcBLw+S63HRERDen6i4RbLSjdbPuVE8xzGTAA/D4wRNWjOAw4GNgCrAM+ZHuozL8EeD+wCTjd9orS/krga1ThdY3t08fZZnog0Zj0QKJfNXY/kM7b2VIdeH8V8GHbL59cic1LgESTEiDRr5ocwvpsx/Rmqp7D8ZPZUERE9JfaQ1jTVXog0aT0QKJfNXlHwo+P97rtz01moxERMfNN5iysV1OdKQXwVmAl1bfFIyJiFur2IPr3gD8evny7pF2Bf7b9hw3XN2kZwoomZQgr+lVjl3MH5gJPdDx/orRFRMQs1e0Q1sXASknfLM+PA5Y1U1JERMwEk7kj4SLg9eXp92zf0lhVU5AhrGhShrCiXzU5hAWwM/Br2+cD6yXtN6nqIiKir3R7EP1sqjOx9re9UNJzgStsH9p0gZOVHkg0KT2Q6FdN9kDeBhwD/BeA7fuAXSdXXkRE9JNuA+SJ8rHeAJKe1VxJERExE3QbIJdL+kfg9yR9ELiBbXNzqYiImKEmcxbWEcCRVPf2uM729U0WVleOgUSTcgwk+lUjl3OXtD1wg+3DplJcryRAokkJkOhXjRxEt/0ksEXS7rUri4iIvtPtN9EfAW6XdD3lTCwA26c1UlVEREx73QbIN8ojIiICmOAYiKTn276nh/VMWY6BRJNyDCT6VRPHQL7VsfKv16oqIiL60kQB0plGL2iykIiImFkmChCPMR0REbPcRMdAnqQ660rATsCjwy8Btr1b4xVOUo6BRJNyDCT6VZ1jIOOehWV7+6mVFBER3Zo3b1+Ghu5uu4yudX0pk5kiPZBoUnog0aT2fr+g/I5tux7ITLVixYqeb3PRokXsueeePd9uRERb+rIHsvvuR/R0m088cR/HHHMIy5df2NPtRu+lBxJNSg9kGnj44V73QC7ht7/tfa8nIqJNk7kn+qRJulDSkKTbOtr2kLRC0p2Sruu8SKOkJZLWSloj6ciO9kWSbpN0l6Tzmqw5IiK602iAABcBR41oO5Pq8vD7AzcCSwAkHQgcDxwAvAm4QFV/DuCLwPttLwQWShq5zoiI6LFGA8T294GHRjQfCywr08uA48r0McBy25ttrwPWAoslzQN2tb2qzHdxxzIREdGSpnsgo9nL9hCA7Y3AXqV9PnBvx3wbStt8YH1H+/rSFhERLZoOB9EbOOVgacf0QHlERMTTBsujvjYCZEjSXNtDZXjqgdK+AXhex3wLSttY7eNYuq1qjYjoUwP87ofrT016Db0YwhK/e1Xfq4CTy/R7gG93tJ8gaQdJ+wEvBFaWYa6HJS0uB9VP6lgmIiJa0mgPRNJlVBH3+5LuAc4GPgNcIel9wN1UZ15he7Wky4HVwCbgIx3XJDkF+BqwI3CN7WubrDsiIibWaIDYPnGMl944xvyfBj49SvvNwEu3YWkRETFFbZyFFRERfSABEhERtSRAIiKilgRIRETUkgCJiIhaEiAREVFLAiQiImpJgERERC0JkIiIqCUBEhERtSRAIiKilgRIRETUkgCJiIhapsMdCSMmZd68fRkaurvtMiJmvQRIzDhVeDRwJ+SuaOJZGvFMqvup9d7cufuwceO6VrYd01sCJGJGeJy2QnNoqK3QjOkux0AiIqKWBEhERNSSAImIiFoSIBERUUsOokdtOZ02YnZLgERt7Z1Om7OCIqaDBEhETKCd76Bst93ObNnyaM+3C/nuS7cSIH0gQ0nRrHa+g7Jli1rZLuS7L91KgPSBDCVFRBtyFlZERNSSHkhExFbau/bYTJIA2UauvfY7+YWL6BttXXtsZv0NaW0IS9I6ST+WdIuklaVtD0krJN0p6TpJu3fMv0TSWklrJB3ZVt1jefzxX1H9wrXxiIjovTaPgWwBBmy/wvbi0nYmcIPt/YEbgSUAkg4EjgcOAN4EXKB83I+IaFWbAaJRtn8ssKxMLwOOK9PHAMttb7a9DlgLLCYiIlrTZoAYuF7SKkkfKG1zbQ8B2N4I7FXa5wP3diy7obRFRERL2jyIfqjt+yU9B1gh6U62HtDPAH9ExDTVWoDYvr/8+3NJ36IakhqSNNf2kKR5wANl9g3A8zoWX1DaxrC0Y3qgPCIi4mmD5VGf7N5/yJe0M7Cd7UckPQtYAXwKeAPwoO1zJJ0B7GH7zHIQ/VLgEKqhq+uBF3mU4iW59x2XS4CTaPc+3W2dcjibttvmtrPPs2Pb7e6z7UmdnNRWD2Qu8M3qjz1zgEttr5D0Q+BySe8D7qY68wrbqyVdDqwGNgEfGS08IiKid1rpgTQpPZBstz+3nX2eHdueWT2QXAsrIiJqSYBEREQtCZCIiKglARIREbUkQCIiopYESERE1JIAiYiIWhIgERFRSwIkIiJqSYBEREQtCZCIiKglARIREbUkQCIiopYESERE1JIAiYiIWhIgERFRSwIkIiJqSYBEREQtCZCIiKglARIREbUkQCIiopYESERE1JIAiYiIWhIgERFRSwIkIiJqSYBEREQtCZCIiKglARIREbXMqACRdLSk/yfpLklntF1PRMRsNmMCRNJ2wD8ARwEHAe+S9OJ2q5ruBtsuYBoZbLuAaWSw7QKmkcG2C5jRZkyAAIuBtbbvtr0JWA4c23JN09xg2wVMI4NtFzCNDLZdwDQy2HYBM9pMCpD5wL0dz9eXtoiIaMGctgtowm67vbWn29u0aT2PPdbTTUZEtE62266hK5JeAyy1fXR5fiZg2+eMmG9m7FBExDRjW5OZfyYFyPbAncAbgPuBlcC7bK9ptbCIiFlqxgxh2X5S0keBFVTHbi5MeEREtGfG9EAiImJ6mUlnYY1J0gJJN0q6Q9Ltkk5ru6a2SdpO0o8kXdV2LW2StLukKyStKb8fh7RdU1skfUzSTyTdJulSSTu0XVOvSLpQ0pCk2zra9pC0QtKdkq6TtHubNfbKGO/F35f/I7dK+rqk3bpZV18ECLAZ+Ljtg4DXAqfkS4acDqxuu4hp4HzgGtsHAC8HZuWwp6TnAqcCi2y/jGr4+oR2q+qpi6i+hNzpTOAG2/sDNwJLel5VO0Z7L1YAB9k+GFhLl+9FXwSI7Y22by3Tj1D9kZi13xGRtAB4M/CVtmtpU/kU9XrbFwHY3mz71y2X1abtgWdJmgPsDNzXcj09Y/v7wEMjmo8FlpXpZcBxPS2qJaO9F7ZvsL2lPP0BsKCbdfVFgHSStC9wMHBTu5W06lzgvwOz/QDXfsAvJF1UhvO+JGmntotqg+37gM8C9wAbgF/ZvqHdqlq3l+0hqD6EAnu1XM908T7gX7qZsa8CRNIuwJXA6aUnMutI+mNgqPTIVB6z1RxgEfC/bC8CHqUatph1JP0e1SfufYDnArtIOrHdqqad2f6BC0l/AWyyfVk38/dNgJRu+ZXAJba/3XY9LToUOEbST4F/Ag6TdHHLNbVlPXCv7R+W51dSBcps9Ebgp7YftP0k8A3gdS3X1LYhSXMBJM0DHmi5nlZJOplq6LvrDxZ9EyDAV4HVts9vu5A22T7L9vNtv4DqIOmNtk9qu642lOGJeyUtLE1vYPaeWHAP8BpJO0oS1Xsx204oGNkjvwo4uUy/B5hNHzx/572QdDTVsPcxth/vdiV9ESCSDgXeDRwu6ZYy3n1023XFtHAacKmkW6nOwvq7lutphe2VVD2wW4AfU/3x+FKrRfWQpMuAfwcWSrpH0nuBzwBHSBq+wsVn2qyxV8Z4L74A7AJcX/5+XtDVuvJFwoiIqKMveiAREdF7CZCIiKglARIREbUkQCIiopYESERE1JIAiYiIWhIgERFRSwIkIiJq+f8KwJfCiHKoPQAAAABJRU5ErkJggg=="},65:function(s,e,a){a.d(e,{Z:function(){return r},a:function(){return t}});var l=a(7294);let n={},i=l.createContext(n);function t(s){let e=l.useContext(i);return l.useMemo(function(){return"function"==typeof s?s(e):{...e,...s}},[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(n):s.components||n:t(s.components),l.createElement(i.Provider,{value:e},s.children)}},4018:function(s){s.exports=JSON.parse('{"permalink":"/2016/05/the-unfair-casino","source":"@site/blog/2016-05-15-the-unfair-casino/index.mdx","title":"The unfair casino","description":"Trying to figure out how exactly two dice are loaded in a cheating casino.","date":"2016-05-15T12:00:00.000Z","tags":[],"readingTime":14.62,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/05/the-unfair-casino","title":"The unfair casino","date":"2016-05-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730679360000,"prevItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"},"nextItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"}}')}}]); \ No newline at end of file diff --git a/assets/js/621db11d.329bb35b.js b/assets/js/621db11d.329bb35b.js new file mode 100644 index 0000000..b83da20 --- /dev/null +++ b/assets/js/621db11d.329bb35b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9854"],{8448:function(e,t,n){n.r(t),n.d(t,{default:()=>j});var r=n("5893");n("7294");var s=n("7026"),i=n("2743"),l=n("4681"),u=n("6025");let a=()=>(0,u.I)({id:"theme.blog.authorsList.pageTitle",message:"Authors",description:"The title of the authors page"});var h=n("979"),o=n("4315"),c=n("4403"),d=n("1389");let g={authorListItem:"authorListItem_n3yI"};function f(e){let{author:t}=e;return(0,r.jsx)("li",{className:g.authorListItem,children:(0,r.jsx)(d.Z,{as:"h2",author:t,count:t.count})})}function p(e){let{authors:t}=e;return(0,r.jsx)("section",{className:(0,s.Z)("margin-vert--lg",g.authorsListSection),children:(0,r.jsx)("ul",{children:t.map(e=>(0,r.jsx)(f,{author:e},e.key))})})}function j(e){let{authors:t,sidebar:n}=e,u=a();return(0,r.jsxs)(i.FG,{className:(0,s.Z)(l.k.wrapper.blogPages,l.k.page.blogAuthorsListPage),children:[(0,r.jsx)(i.d,{title:u}),(0,r.jsx)(o.Z,{tag:"blog_authors_list"}),(0,r.jsxs)(h.Z,{sidebar:n,children:[(0,r.jsx)(c.Z,{as:"h1",children:u}),(0,r.jsx)(p,{authors:t})]})]})}},131:function(e,t,n){n.d(t,{Z:function(){return u}});var r=n(5893),s=n(7294),i=n(4403);function l(e){let{title:t,headingType:n,children:s}=e;return(0,r.jsxs)("div",{role:"group",children:[(0,r.jsx)(i.Z,{as:n,children:t}),s]})}let u=(0,s.memo)(function(e){let{items:t,yearGroupHeadingClassName:n,ListComponent:s}=e;return function(e,t){var n=[],s=[];function i(){if(0===s.length)return;let e=new Date(s[0].date).getFullYear(),i=function(e,t){var n=[],s=[];function i(){if(0===s.length)return;let e=s[0].title.split(":")[0];s=(s=s.map(e=>({...e,title:e.title.split(":")[1].trim()}))).reverse(),n.push((0,r.jsx)(r.Fragment,{children:(0,r.jsx)(l,{title:e,headingType:"h4",children:(0,r.jsx)("ul",{children:(0,r.jsx)(t,{items:s})})})})),s=[]}for(let l of e){if(l.title.includes(":")){s.push(l);continue}i(),n.push((0,r.jsx)(t,{items:[l]}))}return i(),n}(s,t);n.push((0,r.jsx)(r.Fragment,{children:(0,r.jsx)(l,{title:String(e),headingType:"h3",children:i})})),s=[]}for(let t of e){if(0===s.length){s.push(t);continue}let e=new Date(t.date).getFullYear();e!==new Date(s[0].date).getFullYear()&&i(),s.push(t)}return i(),n}(t,s)})}}]); \ No newline at end of file diff --git a/assets/js/6472.40189ba2.js b/assets/js/6472.40189ba2.js new file mode 100644 index 0000000..067d64c --- /dev/null +++ b/assets/js/6472.40189ba2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6472"],{3726:function(e,t,i){i.r(t),i.d(t,{default:()=>d});var n=i("5893");i("7294");var o=i("6025"),s=i("2743"),r=i("5654"),a=i("7026"),l=i("4403");function h(e){let{className:t}=e;return(0,n.jsx)("main",{className:(0,a.Z)("container margin-vert--xl",t),children:(0,n.jsx)("div",{className:"row",children:(0,n.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,n.jsx)(l.Z,{as:"h1",className:"hero__title",children:(0,n.jsx)(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,n.jsx)("p",{children:(0,n.jsx)(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,n.jsx)("p",{children:(0,n.jsx)(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}function d(){let e=(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.d,{title:e}),(0,n.jsx)(r.Z,{children:(0,n.jsx)(h,{})})]})}}}]); \ No newline at end of file diff --git a/assets/js/6fa48b14.90d2bd8d.js b/assets/js/6fa48b14.90d2bd8d.js new file mode 100644 index 0000000..b044cb3 --- /dev/null +++ b/assets/js/6fa48b14.90d2bd8d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1511"],{6836:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return o},default:function(){return p},frontMatter:function(){return a},metadata:function(){return r},toc:function(){return c}});var r=n(7497),i=n(5893),s=n(65);let a={slug:"2018/09/primitives-in-rust-are-weird",title:"Primitives in Rust are weird (and cool)",date:new Date("2018-09-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,u={authorsImageUrls:[void 0]},c=[];function l(e){let t={code:"code",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it\ncouldn't possibly run:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-rust",children:'fn main() {\n println!("{}", 8.to_string())\n}\n'})}),"\n",(0,i.jsx)(t.p,{children:"And to my complete befuddlement, it compiled, ran, and produced a completely sensible output."})]})}function p(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return a}});var r=n(7294);let i={},s=r.createContext(i);function a(e){let t=r.useContext(s);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),r.createElement(s.Provider,{value:t},e.children)}},7497:function(e){e.exports=JSON.parse('{"permalink":"/2018/09/primitives-in-rust-are-weird","source":"@site/blog/2018-09-01-primitives-in-rust-are-weird/index.mdx","title":"Primitives in Rust are weird (and cool)","description":"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it","date":"2018-09-01T12:00:00.000Z","tags":[],"readingTime":6.945,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/primitives-in-rust-are-weird","title":"Primitives in Rust are weird (and cool)","date":"2018-09-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"},"nextItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"}}')}}]); \ No newline at end of file diff --git a/assets/js/71d18034.0eabaf41.js b/assets/js/71d18034.0eabaf41.js new file mode 100644 index 0000000..ae4a51e --- /dev/null +++ b/assets/js/71d18034.0eabaf41.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4558"],{10:function(e,t,n){n.r(t),n.d(t,{assets:function(){return d},contentTitle:function(){return i},default:function(){return p},frontMatter:function(){return o},metadata:function(){return a},toc:function(){return c}});var a=n(9098),r=n(5893),s=n(65);let o={slug:"2018/01/captains-cookbook-part-2",title:"Captain's Cookbook: Practical usage",date:new Date("2018-01-16T13:00:00.000Z"),authors:["bspeice"],tags:[]},i=void 0,d={authorsImageUrls:[void 0]},c=[{value:"Attempt 1: Move the reference",id:"attempt-1-move-the-reference",level:2},{value:"Attempt 2: Put the <code>Reader</code> in a <code>Box</code>",id:"attempt-2-put-the-reader-in-a-box",level:2},{value:"Attempt 3: The <code>TypedReader</code>",id:"attempt-3-the-typedreader",level:2}];function h(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"A look at more practical usages of Cap'N Proto"}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"/2018/01/captains-cookbook-part-1",children:"Part 1"})," of this series took a look at a basic starting project\nwith Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty\nbasic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's\nsome documentation surrounding practical usage of the library."]}),"\n",(0,r.jsxs)(t.p,{children:["As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps\n",(0,r.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs",children:"here"}),". Our current example is going to build on\nthe code we wrote there; after the deserialization step, we'll try and send the ",(0,r.jsx)(t.code,{children:"point_reader"})," to a separate thread\nfor verification."]}),"\n",(0,r.jsxs)(t.p,{children:["I'm going to walk through the attempts as I made them and my thinking throughout.\nIf you want to skip to the final project, check out the code available ",(0,r.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_2",children:"here"})]}),"\n",(0,r.jsx)(t.h2,{id:"attempt-1-move-the-reference",children:"Attempt 1: Move the reference"}),"\n",(0,r.jsx)(t.p,{children:"As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-rust",children:"fn main() {\n\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from\n // somewhere else\n\n let deserialized = capnp::serialize::read_message(\n &mut buffer.as_slice(),\n capnp::message::ReaderOptions::new()\n ).unwrap();\n\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\n\n // By using `point_reader` inside the new thread, we're hoping that Rust can\n // safely move the reference and invalidate the original thread's usage.\n // Since the original thread doesn't use `point_reader` again, this should\n // be safe, right?\n let handle = std::thread:spawn(move || {\n\n assert_eq!(point_reader.get_x(), 12);\n\n assert_eq!(point_reader.get_y(), 14);\n });\n\n handle.join().unwrap()\n}\n"})}),"\n",(0,r.jsx)(t.p,{children:"Well, the Rust compiler doesn't really like this. We get four distinct errors back:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` \n --\x3e src/main.rs:31:18 \n | \n31 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely \n | \n\nerror[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` \n --\x3e src/main.rs:31:18 \n | \n31 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely \n | \n\nerror[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied \n --\x3e src/main.rs:31:18 \n | \n31 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely \n | \n\nerror[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` \n --\x3e src/main.rs:31:18 \n | \n31 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely \n | \n\nerror: aborting due to 4 previous errors\n"})}),"\n",(0,r.jsxs)(t.p,{children:["Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating.\nPay attention to the text that keeps on getting repeated though: ",(0,r.jsx)(t.code,{children:"XYZ cannot be sent between threads safely"}),"."]}),"\n",(0,r.jsxs)(t.p,{children:["This is a bit frustrating: we own the ",(0,r.jsx)(t.code,{children:"buffer"})," from which all the content was derived, and we don't have any\nunsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility\nof the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust\npreventing us from doing something that really should be legal?"]}),"\n",(0,r.jsxs)(t.p,{children:["This is what is known as ",(0,r.jsx)(t.a,{href:"https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html",children:"fighting the borrow checker"}),".\nLet our crusade begin."]}),"\n",(0,r.jsxs)(t.h2,{id:"attempt-2-put-the-reader-in-a-box",children:["Attempt 2: Put the ",(0,r.jsx)(t.code,{children:"Reader"})," in a ",(0,r.jsx)(t.code,{children:"Box"})]}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.a,{href:"https://doc.rust-lang.org/std/boxed/struct.Box.html",children:(0,r.jsx)(t.code,{children:"Box"})})," type allows us to convert a pointer we have\n(in our case the ",(0,r.jsx)(t.code,{children:"point_reader"}),') into an "owned" value, which should be easier to send across threads.\nOur next attempt looks something like this:']}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-rust",children:"fn main() {\n\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content\n // from somewhere else\n\n let deserialized = capnp::serialize::read_message(\n &mut buffer.as_slice(),\n capnp::message::ReaderOptions::new()\n ).unwrap();\n\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\n\n let boxed_reader = Box::new(point_reader);\n\n // Now that the reader is `Box`ed, we've proven ownership, and Rust can\n // move the ownership to the new thread, right?\n let handle = std::thread::spawn(move || {\n\n assert_eq!(boxed_reader.get_x(), 12);\n\n assert_eq!(boxed_reader.get_y(), 14);\n });\n\n handle.join().unwrap();\n}\n"})}),"\n",(0,r.jsx)(t.p,{children:"Spoiler alert: still doesn't work. Same errors still show up."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` \n --\x3e src/main.rs:33:18 \n | \n33 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely \n | \n\nerror[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` \n --\x3e src/main.rs:33:18 \n | \n33 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely \n | \n\nerror[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied \n --\x3e src/main.rs:33:18 \n | \n33 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely \n | \n\nerror[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` \n --\x3e src/main.rs:33:18 \n | \n33 | let handle = std::thread::spawn(move || { \n | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely \n | \n\nerror: aborting due to 4 previous errors\n"})}),"\n",(0,r.jsxs)(t.p,{children:["Let's be a little bit smarter about the exceptions this time though. What is that\n",(0,r.jsx)(t.a,{href:"https://doc.rust-lang.org/std/marker/trait.Send.html",children:(0,r.jsx)(t.code,{children:"std::marker::Send"})})," thing the compiler keeps telling us about?"]}),"\n",(0,r.jsxs)(t.p,{children:["The documentation is pretty clear; ",(0,r.jsx)(t.code,{children:"Send"})," is used to denote:"]}),"\n",(0,r.jsxs)(t.blockquote,{children:["\n",(0,r.jsx)(t.p,{children:"Types that can be transferred across thread boundaries."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"In our case, we are seeing the error messages for two reasons:"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["\n",(0,r.jsxs)(t.p,{children:["Pointers (",(0,r.jsx)(t.code,{children:"*const u8"}),") are not safe to send across thread boundaries. While we're nice in our code\nmaking sure that we wait on the child thread to finish before closing down, the Rust compiler can't make\nthat assumption, and so complains that we're not using this in a safe manner."]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"point_capnp::point::Reader"})," type is itself not safe to send across threads because it doesn't\nimplement the ",(0,r.jsx)(t.code,{children:"Send"})," trait. Which is to say, the things that make up a ",(0,r.jsx)(t.code,{children:"Reader"})," are themselves not thread-safe,\nso the ",(0,r.jsx)(t.code,{children:"Reader"})," is also not thread-safe."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"So, how are we to actually transfer a parsed Cap'N Proto message between threads?"}),"\n",(0,r.jsxs)(t.h2,{id:"attempt-3-the-typedreader",children:["Attempt 3: The ",(0,r.jsx)(t.code,{children:"TypedReader"})]}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"TypedReader"})," is a new API implemented in the Cap'N Proto ",(0,r.jsx)(t.a,{href:"https://crates.io/crates/capnp/0.8.14",children:"Rust code"}),".\nWe're interested in it here for two reasons:"]}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsxs)(t.li,{children:["\n",(0,r.jsxs)(t.p,{children:["It allows us to define an object where the ",(0,r.jsx)(t.em,{children:"object"})," owns the underlying data. In previous attempts,\nthe current context owned the data, but the ",(0,r.jsx)(t.code,{children:"Reader"})," itself had no such control."]}),"\n"]}),"\n",(0,r.jsxs)(t.li,{children:["\n",(0,r.jsxs)(t.p,{children:["We can compose the ",(0,r.jsx)(t.code,{children:"TypedReader"})," using objects that are safe to ",(0,r.jsx)(t.code,{children:"Send"})," across threads, guaranteeing\nthat we can transfer parsed messages across threads."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["The actual type info for the ",(0,r.jsx)(t.a,{href:"https://github.com/capnproto/capnproto-rust/blob/f0efc35d7e9bd8f97ca4fdeb7c57fd7ea348e303/src/message.rs#L181",children:(0,r.jsx)(t.code,{children:"TypedReader"})}),"\nis a bit complex. And to be honest, I'm still really not sure what the whole point of the\n",(0,r.jsx)(t.a,{href:"https://doc.rust-lang.org/std/marker/struct.PhantomData.html",children:(0,r.jsx)(t.code,{children:"PhantomData"})})," thing is either.\nMy impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto\nmessage represents. That is, technically the only thing we're storing is the untyped binary message;\n",(0,r.jsx)(t.code,{children:"PhantomData"})," just enforces the principle that the binary represents some specific object that has been parsed."]}),"\n",(0,r.jsx)(t.p,{children:"Either way, we can carefully construct something which is safe to move between threads:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-rust",children:"fn main() {\n\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else\n\n let deserialized = capnp::serialize::read_message(\n &mut buffer.as_slice(),\n capnp::message::ReaderOptions::new()\n ).unwrap();\n\n let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> =\n capnp::message::TypedReader::new(deserialized);\n\n // Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message\n // (which is 'static lifetime), this is now safe\n let handle = std::thread::spawn(move || {\n\n // The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader\n // object from it\n let point_root = point_reader.get().unwrap();\n\n assert_eq!(point_root.get_x(), 12);\n\n assert_eq!(point_root.get_y(), 14);\n });\n\n handle.join().unwrap();\n}\n"})}),"\n",(0,r.jsxs)(t.p,{children:["And while we've left Rust to do the dirty work of actually moving the ",(0,r.jsx)(t.code,{children:"point_reader"})," into the new thread,\nwe could also use things like ",(0,r.jsxs)(t.a,{href:"https://doc.rust-lang.org/std/sync/mpsc/index.html",children:[(0,r.jsx)(t.code,{children:"mpsc"})," channels"]})," to achieve a similar effect."]}),"\n",(0,r.jsx)(t.p,{children:"So now we're able to define basic Cap'N Proto messages, and send them all around our programs."})]})}function p(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},65:function(e,t,n){n.d(t,{Z:function(){return i},a:function(){return o}});var a=n(7294);let r={},s=a.createContext(r);function o(e){let t=a.useContext(s);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),a.createElement(s.Provider,{value:t},e.children)}},9098:function(e){e.exports=JSON.parse('{"permalink":"/2018/01/captains-cookbook-part-2","source":"@site/blog/2018-01-16-captains-cookbook-part-2/index.mdx","title":"Captain\'s Cookbook: Practical usage","description":"A look at more practical usages of Cap\'N Proto","date":"2018-01-16T13:00:00.000Z","tags":[],"readingTime":6.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-2","title":"Captain\'s Cookbook: Practical usage","date":"2018-01-16T13:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Hello!","permalink":"/2018/05/hello"},"nextItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"}}')}}]); \ No newline at end of file diff --git a/assets/js/724b3f70.bf6a608e.js b/assets/js/724b3f70.bf6a608e.js new file mode 100644 index 0000000..a33bd93 --- /dev/null +++ b/assets/js/724b3f70.bf6a608e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5747"],{7519:function(t,e,n){n.r(e),n.d(e,{assets:function(){return l},contentTitle:function(){return s},default:function(){return p},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return u}});var o=n(4024),r=n(5893),i=n(65);let a={slug:"2018/05/hello",title:"Hello!",date:new Date("2018-05-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,l={authorsImageUrls:[void 0]},u=[];function c(t){let e={p:"p",...(0,i.a)(),...t.components};return(0,r.jsx)(e.p,{children:"I'll do what I can to keep this short, there's plenty of other things we both should be doing right\nnow."})}function p(t={}){let{wrapper:e}={...(0,i.a)(),...t.components};return e?(0,r.jsx)(e,{...t,children:(0,r.jsx)(c,{...t})}):c(t)}},65:function(t,e,n){n.d(e,{Z:function(){return s},a:function(){return a}});var o=n(7294);let r={},i=o.createContext(r);function a(t){let e=o.useContext(i);return o.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:a(t.components),o.createElement(i.Provider,{value:e},t.children)}},4024:function(t){t.exports=JSON.parse('{"permalink":"/2018/05/hello","source":"@site/blog/2018-05-28-hello/index.mdx","title":"Hello!","description":"I\'ll do what I can to keep this short, there\'s plenty of other things we both should be doing right","date":"2018-05-28T12:00:00.000Z","tags":[],"readingTime":0.375,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/05/hello","title":"Hello!","date":"2018-05-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"},"nextItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"}}')}}]); \ No newline at end of file diff --git a/assets/js/72c73938.10945791.js b/assets/js/72c73938.10945791.js new file mode 100644 index 0000000..97faea7 --- /dev/null +++ b/assets/js/72c73938.10945791.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9658"],{8190:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return o},default:function(){return c},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return h}});var s=n(5419),i=n(5893),a=n(65);let r={slug:"2016/03/tweet-like-me",title:"Tweet like me",date:new Date("2016-03-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},h=[{value:"The Objective",id:"the-objective",level:2},{value:"The Data",id:"the-data",level:2},{value:"The Algorithm",id:"the-algorithm",level:2},{value:"Pulling it all together",id:"pulling-it-all-together",level:2},{value:"The results",id:"the-results",level:2},{value:"Moving on from here",id:"moving-on-from-here",level:2},{value:"For further reading",id:"for-further-reading",level:2}];function d(e){let t={a:"a",annotation:"annotation",code:"code",em:"em",h2:"h2",img:"img",li:"li",math:"math",mi:"mi",mn:"mn",mo:"mo",mover:"mover",mrow:"mrow",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"In which I try to create a robot that will tweet like I tweet."}),"\n",(0,i.jsx)(t.p,{children:"So, I'm taking a Machine Learning course this semester in school, and one of the topics we keep coming back to is natural language processing and the 'bag of words' data structure. That is, given a sentence:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.code,{children:"How much wood would a woodchuck chuck if a woodchuck could chuck wood?"})}),"\n",(0,i.jsx)(t.p,{children:"We can represent that sentence as the following list:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.code,{children:"{ How: 1 much: 1 wood: 2 would: 2 a: 2 woodchuck: 2 chuck: 2 if: 1 }"})}),"\n",(0,i.jsxs)(t.p,{children:["Ignoring ",(0,i.jsx)(t.em,{children:"where"})," the words happened, we're just interested in how ",(0,i.jsx)(t.em,{children:"often"}),' the words occurred. That got me thinking: I wonder what would happen if I built a robot that just imitated how often I said things? It\'s dangerous territory when computer scientists ask "what if," but I got curious enough I wanted to follow through.']}),"\n",(0,i.jsx)(t.h2,{id:"the-objective",children:"The Objective"}),"\n",(0,i.jsx)(t.p,{children:"Given an input list of Tweets, build up the following things:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:'The distribution of starting words; since there are no "prior" words to go from, we need to treat this as a special case.'}),"\n",(0,i.jsxs)(t.li,{children:["The distribution of words given a previous word; for example, every time I use the word ",(0,i.jsx)(t.code,{children:"woodchuck"})," in the example sentence, there is a 50% chance it is followed by ",(0,i.jsx)(t.code,{children:"chuck"})," and a 50% chance it is followed by ",(0,i.jsx)(t.code,{children:"could"}),". I need this distribution for all words."]}),"\n",(0,i.jsx)(t.li,{children:"The distribution of quantity of hashtags; Do I most often use just one? Two? Do they follow something like a Poisson distribution?"}),"\n",(0,i.jsx)(t.li,{children:"Distribution of hashtags; Given a number of hashtags, what is the actual content? I'll treat hashtags as separate from the content of a tweet."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"the-data",children:"The Data"}),"\n",(0,i.jsx)(t.p,{children:"I'm using as input my tweet history. I don't really use Twitter anymore, but it seems like a fun use of the dataset. I'd like to eventually build this to a point where I can imitate anyone on Twitter using their last 100 tweets or so, but I'll start with this as example code."}),"\n",(0,i.jsx)(t.h2,{id:"the-algorithm",children:"The Algorithm"}),"\n",(0,i.jsxs)(t.p,{children:["I'll be using the ",(0,i.jsx)(t.a,{href:"http://www.nltk.org/",children:"NLTK"})," library for doing a lot of the heavy lifting. First, let's import the data:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import pandas as pd\n\ntweets = pd.read_csv('tweets.csv')\ntext = tweets.text\n\n# Don't include tweets in reply to or mentioning people\nreplies = text.str.contains('@')\ntext_norep = text.loc[~replies]\n"})}),"\n",(0,i.jsx)(t.p,{children:"And now that we've got data, let's start crunching. First, tokenize and build out the distribution of first word:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"from nltk.tokenize import TweetTokenizer\ntknzr = TweetTokenizer()\ntokens = text_norep.map(tknzr.tokenize)\n\nfirst_words = tokens.map(lambda x: x[0])\nfirst_words_alpha = first_words[first_words.str.isalpha()]\nfirst_word_dist = first_words_alpha.value_counts() / len(first_words_alpha)\n"})}),"\n",(0,i.jsxs)(t.p,{children:["Next, we need to build out the conditional distributions. That is, what is the probability of the next word given the current word is ",(0,i.jsxs)(t.span,{className:"katex",children:[(0,i.jsx)(t.span,{className:"katex-mathml",children:(0,i.jsx)(t.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(t.semantics,{children:[(0,i.jsx)(t.mrow,{children:(0,i.jsx)(t.mi,{children:"X"})}),(0,i.jsx)(t.annotation,{encoding:"application/x-tex",children:"X"})]})})}),(0,i.jsx)(t.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(t.span,{className:"base",children:[(0,i.jsx)(t.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(t.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"})]})})]}),"? This one is a bit more involved. First, find all unique words, and then find what words proceed them. This can probably be done in a more efficient manner than I'm currently doing here, but we'll ignore that for the moment."]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"from functools import reduce\n\n# Get all possible words\nall_words = reduce(lambda x, y: x+y, tokens, [])\nunique_words = set(all_words)\nactual_words = set([x if x[0] != '.' else None for x in unique_words])\n\nword_dist = {}\nfor word in iter(actual_words):\n indices = [i for i, j in enumerate(all_words) if j == word]\n proceeding = [all_words[i+1] for i in indices]\n word_dist[word] = proceeding\n"})}),"\n",(0,i.jsx)(t.p,{children:"Now that we've got the tweet analysis done, it's time for the fun part: hashtags! Let's count how many hashtags are in each tweet, I want to get a sense of the distribution."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import matplotlib.pyplot as plt\n%matplotlib inline\n\nhashtags = text_norep.str.count('#')\nbins = hashtags.unique().max()\nhashtags.plot(kind='hist', bins=bins)\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" <matplotlib.axes._subplots.AxesSubplot at 0x18e59dc28d0>\n"})}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"png",src:n(3092).Z+"",width:"393",height:"256"})}),"\n",(0,i.jsxs)(t.p,{children:["That looks like a Poisson distribution, kind of as I expected. I'm guessing my number of hashtags per tweet is ",(0,i.jsxs)(t.span,{className:"katex",children:[(0,i.jsx)(t.span,{className:"katex-mathml",children:(0,i.jsx)(t.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(t.semantics,{children:[(0,i.jsxs)(t.mrow,{children:[(0,i.jsx)(t.mo,{children:"\u223C"}),(0,i.jsx)(t.mi,{children:"P"}),(0,i.jsx)(t.mi,{children:"o"}),(0,i.jsx)(t.mi,{children:"i"}),(0,i.jsx)(t.mo,{stretchy:"false",children:"("}),(0,i.jsx)(t.mn,{children:"1"}),(0,i.jsx)(t.mo,{stretchy:"false",children:")"})]}),(0,i.jsx)(t.annotation,{encoding:"application/x-tex",children:"\\sim Poi(1)"})]})})}),(0,i.jsxs)(t.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(t.span,{className:"base",children:[(0,i.jsx)(t.span,{className:"strut",style:{height:"0.3669em"}}),(0,i.jsx)(t.span,{className:"mrel",children:"\u223C"}),(0,i.jsx)(t.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(t.span,{className:"base",children:[(0,i.jsx)(t.span,{className:"strut",style:{height:"1em",verticalAlign:"-0.25em"}}),(0,i.jsx)(t.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(t.span,{className:"mord mathnormal",children:"o"}),(0,i.jsx)(t.span,{className:"mord mathnormal",children:"i"}),(0,i.jsx)(t.span,{className:"mopen",children:"("}),(0,i.jsx)(t.span,{className:"mord",children:"1"}),(0,i.jsx)(t.span,{className:"mclose",children:")"})]})]})]}),", but let's actually find the ",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Poisson_distribution#Maximum_likelihood",children:"most likely estimator"})," which in this case is just ",(0,i.jsxs)(t.span,{className:"katex",children:[(0,i.jsx)(t.span,{className:"katex-mathml",children:(0,i.jsx)(t.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(t.semantics,{children:[(0,i.jsx)(t.mrow,{children:(0,i.jsxs)(t.mover,{accent:"true",children:[(0,i.jsx)(t.mi,{children:"\u03BB"}),(0,i.jsx)(t.mo,{children:"\u02C9"})]})}),(0,i.jsx)(t.annotation,{encoding:"application/x-tex",children:"\\bar{\\lambda}"})]})})}),(0,i.jsx)(t.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(t.span,{className:"base",children:[(0,i.jsx)(t.span,{className:"strut",style:{height:"0.8312em"}}),(0,i.jsx)(t.span,{className:"mord accent",children:(0,i.jsx)(t.span,{className:"vlist-t",children:(0,i.jsx)(t.span,{className:"vlist-r",children:(0,i.jsxs)(t.span,{className:"vlist",style:{height:"0.8312em"},children:[(0,i.jsxs)(t.span,{style:{top:"-3em"},children:[(0,i.jsx)(t.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(t.span,{className:"mord mathnormal",children:"\u03BB"})]}),(0,i.jsxs)(t.span,{style:{top:"-3.2634em"},children:[(0,i.jsx)(t.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(t.span,{className:"accent-body",style:{left:"-0.25em"},children:(0,i.jsx)(t.span,{className:"mord",children:"\u02C9"})})]})]})})})})]})})]}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"mle = hashtags.mean()\nmle\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" 0.870236869207003\n"})}),"\n",(0,i.jsx)(t.p,{children:"Pretty close! So we can now simulate how many hashtags are in a tweet. Let's also find what hashtags are actually used:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"hashtags = [x for x in all_words if x[0] == '#']\nn_hashtags = len(hashtags)\n\nunique_hashtags = list(set([x for x in unique_words if x[0] == '#']))\nhashtag_dist = pd.DataFrame({'hashtags': unique_hashtags,\n 'prob': [all_words.count(h) / n_hashtags\n for h in unique_hashtags]})\nlen(hashtag_dist)\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" 603\n"})}),"\n",(0,i.jsx)(t.p,{children:"Turns out I have used 603 different hashtags during my time on Twitter. That means I was using a unique hashtag for about every third tweet."}),"\n",(0,i.jsx)(t.p,{children:"In better news though, we now have all the data we need to go about actually constructing tweets! The process will happen in a few steps:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Randomly select what the first word will be."}),"\n",(0,i.jsx)(t.li,{children:"Randomly select the number of hashtags for this tweet, and then select the actual hashtags."}),"\n",(0,i.jsx)(t.li,{children:"Fill in the remaining space of 140 characters with random words taken from my tweets."}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["And hopefully, we won't have anything too crazy come out the other end. The way we do the selection follows a ",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Multinomial_distribution",children:"Multinomial Distribution"}),": given a lot of different values with specific probability, pick one. Let's give a quick example:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"x: .33\ny: .5\nz: .17\n"})}),"\n",(0,i.jsxs)(t.p,{children:["That is, I pick ",(0,i.jsx)(t.code,{children:"x"})," with probability 33%, ",(0,i.jsx)(t.code,{children:"y"})," with probability 50%, and so on. In context of our sentence construction, I've built out the probabilities of specific words already - now I just need to simulate that distribution. Time for the engine to actually be developed!"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"import numpy as np\n\ndef multinom_sim(n, vals, probs):\n occurrences = np.random.multinomial(n, probs)\n results = occurrences * vals\n return ' '.join(results[results != ''])\n\ndef sim_n_hashtags(hashtag_freq):\n return np.random.poisson(hashtag_freq)\n\ndef sim_hashtags(n, hashtag_dist):\n return multinom_sim(n, hashtag_dist.hashtags, hashtag_dist.prob)\n\ndef sim_first_word(first_word_dist):\n probs = np.float64(first_word_dist.values)\n return multinom_sim(1, first_word_dist.reset_index()['index'], probs)\n\ndef sim_next_word(current, word_dist):\n dist = pd.Series(word_dist[current])\n probs = np.ones(len(dist)) / len(dist)\n return multinom_sim(1, dist, probs)\n"})}),"\n",(0,i.jsx)(t.h2,{id:"pulling-it-all-together",children:"Pulling it all together"}),"\n",(0,i.jsx)(t.p,{children:"I've now built out all the code I need to actually simulate a sentence written by me. Let's try doing an example with five words and a single hashtag:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"first = sim_first_word(first_word_dist)\nsecond = sim_next_word(first, word_dist)\nthird = sim_next_word(second, word_dist)\nfourth = sim_next_word(third, word_dist)\nfifth = sim_next_word(fourth, word_dist)\nhashtag = sim_hashtags(1, hashtag_dist)\n\n' '.join((first, second, third, fourth, fifth, hashtag))\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" 'My first all-nighter of friends #oldschool'\n"})}),"\n",(0,i.jsx)(t.p,{children:"Let's go ahead and put everything together! We're going to simulate a first word, simulate the hashtags, and then simulate to fill the gap until we've either taken up all the space or reached a period."}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"def simulate_tweet():\n chars_remaining = 140\n first = sim_first_word(first_word_dist)\n n_hash = sim_n_hashtags(mle)\n hashtags = sim_hashtags(n_hash, hashtag_dist)\n \n chars_remaining -= len(first) + len(hashtags)\n \n tweet = first\n current = first\n while chars_remaining > len(tweet) + len(hashtags) and current[0] != '.' and current[0] != '!':\n current = sim_next_word(current, word_dist)\n tweet += ' ' + current\n \n tweet = tweet[:-2] + tweet[-1]\n \n return ' '.join((tweet, hashtags)).strip()\n"})}),"\n",(0,i.jsx)(t.h2,{id:"the-results",children:"The results"}),"\n",(0,i.jsx)(t.p,{children:"And now for something completely different: twenty random tweets dreamed up by my computer and my Twitter data. Here you go:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:"for i in range(0, 20):\n print(simulate_tweet())\n print()\n"})}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" Also , I'm at 8 this morning. #thursdaysgohard #ornot\n \n Turns out of us breathe the code will want to my undergraduate career is becoming more night trying ? Religion is now as a chane #HYPE\n \n You know what recursion is to review the UNCC. #ornot\n \n There are really sore 3 bonfires in my first writing the library ground floor if awesome. #realtalk #impressed\n \n So we can make it out there's nothing but I'm not let us so hot I could think I may be good. #SwingDance\n \n Happy Christmas , at Harris Teeter to be be godly or Roman Catholic ). #4b392b#4b392b #Isaiah26\n \n For context , I in the most decisive factor of the same for homework. #accomplishment\n \n Freaking done. #loveyouall\n \n New blog post : Don't jump in a quiz in with a knife fight. #haskell #earlybirthday\n \n God shows me legitimately want to get some food and one day.\n \n Stormed the queen city. #mindblown\n \n The day of a cold at least outside right before the semester ..\n \n Finished with the way back. #winners\n \n Waking up , OJ , I feel like Nick Jonas today.\n \n First draft of so hard drive. #humansvszombies\n \n Eric Whitacre is the wise creation.\n \n Ethics paper first , music in close to everyone who just be posting up with my sin , and Jerry Springr #TheLittleThings\n \n Love that you know enough time I've eaten at 8 PM. #deepthoughts #stillblownaway\n \n Lead. #ThinkingTooMuch #Christmas\n \n Aamazing conference when you married #DepartmentOfRedundancyDepartment Yep , but there's a legitimate challenge.\n"})}),"\n",(0,i.jsxs)(t.p,{children:["...Which all ended up being a whole lot more nonsensical than I had hoped for. There are some good ones, so I'll call that an accomplishment! I was banking on grammar not being an issue: since my tweets use impeccable grammar, the program modeled off them should have pretty good grammar as well. There are going to be some hilarious edge cases (I'm looking at you, ",(0,i.jsx)(t.code,{children:"Ethics paper first, music in close to everyone"}),") that make no sense, and some hilarious edge cases (",(0,i.jsx)(t.code,{children:"Waking up, OJ, I feel like Nick Jonas today"}),") that make me feel like I should have a Twitter rap career. On the whole though, the structure came out alright."]}),"\n",(0,i.jsx)(t.h2,{id:"moving-on-from-here",children:"Moving on from here"}),"\n",(0,i.jsx)(t.p,{children:"During class we also talked about an interesting idea: trying to analyze corporate documents and corporate speech. I'd be interested to know what this analysis applied to something like a couple of bank press releases could do. By any means, the code needs some work to clean it up before I get that far."}),"\n",(0,i.jsx)(t.h2,{id:"for-further-reading",children:"For further reading"}),"\n",(0,i.jsxs)(t.p,{children:["I'm pretty confident I re-invented a couple wheels along the way - what I'm doing feels a lot like what ",(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Markov_chain_Monte_Carlo",children:"Markov Chain Monte Carlo"})," is intended to do. But I've never worked explicitly with that before, so more research is needed."]})]})}function c(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},3092:function(e,t,n){n.d(t,{Z:function(){return s}});let s="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYkAAAEACAYAAABGYoqtAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAEe1JREFUeJzt3X+s3XV9x/HnCzqRinadjt6NosA0CGYOUSsJM7tmG4pGYFuGuGkEMmOCTheThZZsazXZBOOcbguJUWYqw7CCIpi5UQi7Li5KmYKixdpkFrHQC1MHogQB3/vjfGsP9X7KObf33HNu7/ORnPT7/dzv95x3v/32vO7n8/2VqkKSpLkcNu4CJEmTy5CQJDUZEpKkJkNCktRkSEiSmgwJSVLTyEMiya4kX01ye5JtXdvqJFuT7EhyY5JVfctvSLIzyV1Jzhh1fZKktsXoSfwUmK6ql1TVuq5tPXBzVZ0I3AJsAEhyMnAucBJwJnB5kixCjZKkOSxGSGSOzzkb2NxNbwbO6abPAq6uqserahewE1iHJGksFiMkCrgpyW1J/qRrW1NVswBVtQc4ums/Brinb93dXZskaQxWLMJnnF5V9yX5ZWBrkh30gqOf9waRpAk08pCoqvu6Px9I8hl6w0ezSdZU1WySKeD+bvHdwLF9q6/t2p4kiaEiSfNQVUMd5x3pcFOSlUmO6qafAZwB3AncAJzfLfYW4Ppu+gbgvCRPS3I88Hxg21zvXVW+qti4cePYa5iUl9vCbeG2OPBrPkbdk1gDXNf95r8CuKqqtib5b2BLkguBu+md0URVbU+yBdgOPAZcVPP9m0mSDtpIQ6Kqvg2cMkf794HfaazzPuB9o6xLkjQYr7he4qanp8ddwsRwW+zjttjHbXFwshRHc5I4CiVJQ0pCTdKBa0nS0mZISJKaDAlJUpMhIUlqMiQkSU2GhCSpyZCQJDUZEpKkJkNCktS0rEJiauo4kgz1mpo6btxlS9LYLKvbcvQelz3sepn3LXYlaZJ4Ww5J0oIyJCRJTYaEJKnJkJAkNRkSkqQmQ0KS1GRISJKaDAlJUpMhIUlqMiQkSU2GhCSpyZCQJDUZEpKkJkNCktRkSEiSmgwJSVKTISFJajIkJElNhoQkqcmQkCQ1GRKSpCZDQpLUZEhIkpoWJSSSHJbkK0lu6OZXJ9maZEeSG5Os6lt2Q5KdSe5KcsZi1CdJmtti9STeBWzvm18P3FxVJwK3ABsAkpwMnAucBJwJXJ4ki1SjJGk/Iw+JJGuB1wIf62s+G9jcTW8GzummzwKurqrHq2oXsBNYN+oaJUlzW4yexN8Bfw5UX9uaqpoFqKo9wNFd+zHAPX3L7e7aJEljsGKUb57kdcBsVd2RZPoAi9YBfjanTZs2/Wx6enqa6ekDvb0kLT8zMzPMzMwc1Hukaujv58HfPPkb4E3A48CRwDOB64CXAdNVNZtkCviPqjopyXqgquqybv1/BzZW1a37vW/Np+7e4Y1h1wuj3EaStFiSUFVDHecd6XBTVV1SVc+tqhOA84BbqurNwGeB87vF3gJc303fAJyX5GlJjgeeD2wbZY2SpLaRDjcdwKXAliQXAnfTO6OJqtqeZAu9M6EeAy6aV5dBkrQgRjrcNCoON0nS8CZuuEmStLQZEpKkJkNCktRkSEiSmgwJSVKTISFJajIkJElNhoQkqcmQkCQ1GRKSpCZDQpLUZEhIkpoMCUlSkyEhSWoyJCRJTYaEJKnJkJAkNY3r8aUH7b3vfe9Qy69cuXJElUjSoWvJPr4U/nKodY444goeffRefHyppOVqPo8vXcIhMVzdq1adxoMP3oohIWm58hnXkqQFZUhIkpoMCUlSkyEhSWoyJCRJTYaEJKnJkJAkNRkSkqQmQ0KS1GRISJKaDAlJUpMhIUlqMiQkSU2GhCSpyZCQJDWNNCSSHJHk1iS3J7kzycaufXWSrUl2JLkxyaq+dTYk2ZnkriRnjLI+SdKBjTQkqupR4FVV9RLgFODMJOuA9cDNVXUicAuwASDJycC5wEnAmcDlSYZ6QIYkaeGMfLipqn7cTR5B75naBZwNbO7aNwPndNNnAVdX1eNVtQvYCawbdY2SpLkNFBJJfn2+H5DksCS3A3uAm6rqNmBNVc0CVNUe4Ohu8WOAe/pW3921SZLGYNCexOVJtiW5qP/4wSCq6qfdcNNaYF2SF/HzD5r2IdKSNIFWDLJQVb0yyQuAC4EvJ9kGfLyqbhr0g6rqoSQzwGuA2SRrqmo2yRRwf7fYbuDYvtXWdm1z2NQ3Pd29JEl7zczMMDMzc1DvkarBf4lPcji94wd/DzwEBLikqj7dWP45wGNV9WCSI4EbgUuB3wK+X1WXJbkYWF1V67sD11cBr6A3zHQT8ILar8gkNWznY9Wq03jwwVsZvtMShtlGkjSpklBVQ50MNFBPIsmLgQuA19H74n59VX0lya8CXwTmDAngV4DNSQ6jN7T1L1X1uSRfArYkuRC4m94ZTVTV9iRbgO3AY8BF+weEJGnxDNSTSPJ54GPAtVX1yH4/e3NVXTmi+lr12JOQpCGNrCdBrwfxSFU90X3QYcDTq+rHix0QkqTFM+jZTTcDR/bNr+zaJEmHsEFD4ulV9fDemW565WhKkiRNikFD4kdJTt07k+SlwCMHWF6SdAgY9JjEnwHXJLmX3mmvU8AbRlaVJGkiDHox3W1JXgic2DXtqKrHRleWJGkSDNqTAHg5cFy3zqndqVSfGElVkqSJMOjFdFcCvwbcATzRNRdgSEjSIWzQnsTLgJO9+lmSlpdBz276Or2D1ZKkZWTQnsRzgO3d3V8f3dtYVWeNpCpJ0kQYNCQ2jbIISdJkGvQU2M8neR6923bfnGQlcPhoS5Mkjdugjy99K3At8JGu6RjgM6MqSpI0GQY9cP124HR6Dxqiqnay77nUkqRD1KAh8WhV/WTvTJIV+FxqSTrkDRoSn09yCXBkkt8FrgE+O7qyJEmTYNCQWA88ANwJvA34HPAXoypKkjQZBnp86aTx8aWSNLyRPb40ybeZ49u1qk4Y5sMkSUvLMPdu2uvpwB8Cv7Tw5UiSJslAxySq6nt9r91V9SHgdSOuTZI0ZoMON53aN3sYvZ7FMM+ikCQtQYN+0f9t3/TjwC7g3AWvRpI0UQa9d9OrRl2IJGnyDDrc9O4D/byqPrgw5UiSJskwZze9HLihm389sA3YOYqiJEmTYdCQWAucWlU/BEiyCfjXqnrTqAqTJI3foLflWAP8pG/+J12bJOkQNmhP4hPAtiTXdfPnAJtHU5IkaVIMenbTXyf5N+CVXdMFVXX76MqSJE2CQYebAFYCD1XVh4HvJjl+RDVJkibEoI8v3QhcDGzomn4B+OdRFSVJmgyD9iR+DzgL+BFAVd0LPHNURUmSJsOgIfGT6j1UoQCSPGN0JUmSJsWgIbElyUeAX0zyVuBm4KOjK0uSNAkGvVX4B4BrgU8BJwJ/VVX/8FTrJVmb5JYk30hyZ5J3du2rk2xNsiPJjUlW9a2zIcnOJHclOWN+fy1J0kJ4yseXJjkcuHk+N/lLMgVMVdUdSY4CvgycDVwAfK+q3p/kYmB1Va1PcjJwFb1bgKyl12N5Qe1XpI8vlaThzefxpU/Zk6iqJ4Cf9v+2P6iq2lNVd3TTDwN30fvyP5t9F+NtpndxHvQOjl9dVY9X1S5694ZaN+znSpIWxqBXXD8M3JnkJroznACq6p2DflCS44BTgC8Ba6pqtnuPPUmO7hY7Bvhi32q7uzZJ0hgMGhKf7l7z0g01XQu8q6oe7g0XPYnjOZI0gQ4YEkmeW1Xfqap536cpyQp6AXFlVV3fNc8mWVNVs91xi/u79t3AsX2rr+3a5rCpb3q6e0mS9pqZmWFmZuag3uOAB66TfKWqTu2mP1VVfzD0BySfAP63qt7d13YZ8P2quqxx4PoV9IaZbsID15K0IOZz4Pqphpv63+yEeRR0OvDH9I5n3E7vG/oS4DJ6115cCNxN97zsqtqeZAuwHXgMuGj/gJAkLZ6nColqTA+kqv4LOLzx499prPM+4H3DfpYkaeE9VUj8RpKH6PUojuym6earqp410uokSWN1wJCoqlYvQJK0DAzzPAlJ0jJjSEiSmgwJSVKTISFJajIkJElNhoQkqcmQkCQ1GRKSpCZDQpLUZEhIkpoMCUlSkyEhSWoyJCRJTYaEJKnJkJAkNRkSkqQmQ0KS1GRISJKaDAlJUpMhIUlqMiQkSU2GhCSpyZCQJDUZEpKkJkNCktRkSEiSmgwJSVKTISFJajIkJElNhoQkqcmQkCQ1GRJP6QiSDP2amjpu3IVL0kFbMe4CJt+jQA291uxsFr4USVpk9iQkSU0jDYkkVySZTfK1vrbVSbYm2ZHkxiSr+n62IcnOJHclOWOUtUmSntqoexIfB169X9t64OaqOhG4BdgAkORk4FzgJOBM4PIkjtlI0hiNNCSq6gvAD/ZrPhvY3E1vBs7pps8Crq6qx6tqF7ATWDfK+iRJBzaOYxJHV9UsQFXtAY7u2o8B7ulbbnfXJkkak0k4u2n4U4cA2NQ3Pd29JEl7zczMMDMzc1DvMY6QmE2ypqpmk0wB93ftu4Fj+5Zb27U1bBpVfZJ0SJienmZ6evpn8+95z3uGfo/FGG5K99rrBuD8bvotwPV97ecleVqS44HnA9sWoT5JUsNIexJJPklvHOjZSb4DbAQuBa5JciFwN70zmqiq7Um2ANuBx4CLqmqeQ1GSpIWQpfg9nKSGPZSxatVpPPjgrQx/CCTzWKe33lLctpIOXUmoqqEuLfCKa0lSkyEhSWoyJCRJTYaEJKnJkJAkNRkSkqQmQ0KS1GRISJKaDAlJUpMhIUlqMiQkSU2GhCSpyZCQJDUZEpKkJkNCktRkSEiSmgwJSVKTISFJajIkJElNhoQkqcmQkCQ1GRKSpCZDQpLUZEhIkpoMCUlSkyExMkeQZKjX1NRx4y5akp5kxbgLOHQ9CtRQa8zOZjSlSNI82ZOQJDUZEpKkJkNCktRkSEiSmgwJSVKTISFJajIkJElNhoQkqWkiQyLJa5J8M8m3klw87nokabmauJBIchjwj8CrgRcBb0zywvFWNblmZmbGXcLEcFvs47bYx21xcCYuJIB1wM6quruqHgOuBs4ec00Ty/8A+7gt9nFb7OO2ODiTGBLHAPf0zX+3a9McPvCBDw19I0FvJihpUEv2Bn/Petbrh1r+kUe+OaJKFlLvzrHDG+5GguDNBKVRmJo6jtnZu4daZ82a57Fnz67RFLQAUjX8F8woJTkN2FRVr+nm1wNVVZf1LTNZRUvSElFVQ/2GOIkhcTiwA/ht4D5gG/DGqrprrIVJ0jI0ccNNVfVEkncAW+kdM7nCgJCk8Zi4noQkaXJM4tlNB+SFdvsk2ZXkq0luT7Jt3PUspiRXJJlN8rW+ttVJtibZkeTGJKvGWeNiaWyLjUm+m+Qr3es146xxsSRZm+SWJN9IcmeSd3bty2rfmGM7/GnXPvR+saR6Et2Fdt+id7ziXuA24LyqWgqnLi24JP8DvLSqfjDuWhZbkt8EHgY+UVUv7touA75XVe/vfoFYXVXrx1nnYmhsi43AD6vqg2MtbpElmQKmquqOJEcBX6Z3ndUFLKN94wDb4Q0MuV8stZ6EF9o9WVh6/4YLoqq+AOwfjmcDm7vpzcA5i1rUmDS2BfT2j2WlqvZU1R3d9MPAXcBaltm+0dgOe683G2q/WGpfMF5o92QF3JTktiRvHXcxE+DoqpqF3n8S4Ogx1zNu70hyR5KPHerDK3NJchxwCvAlYM1y3Tf6tsOtXdNQ+8VSCwk92elVdSrwWuDt3bCD9lk6Y6kL73LghKo6BdgDLLdhp6OAa4F3db9J778vLIt9Y47tMPR+sdRCYjfw3L75tV3bslRV93V/PgBcR284bjmbTbIGfjYme/+Y6xmbqnqg9h1w/Cjw8nHWs5iSrKD3xXhlVV3fNS+7fWOu7TCf/WKphcRtwPOTPC/J04DzgBvGXNNYJFnZ/ZZAkmcAZwBfH29Viy48eXz1BuD8bvotwPX7r3AIe9K26L4I9/p9lte+8U/A9qr6cF/bctw3fm47zGe/WFJnN0HvFFjgw+y70O7SMZc0FkmOp9d7KHoXRV61nLZFkk8C08CzgVlgI/AZ4BrgWOBu4Nyq+r9x1bhYGtviVfTGoX8K7ALetndM/lCW5HTgP4E76f3fKOASendu2MIy2TcOsB3+iCH3iyUXEpKkxbPUhpskSYvIkJAkNRkSkqQmQ0KS1GRISJKaDAlJUpMhIUlqMiQkSU3/DzepYDZSwMuQAAAAAElFTkSuQmCC"},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return r}});var s=n(7294);let i={},a=s.createContext(i);function r(e){let t=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(a.Provider,{value:t},e.children)}},5419:function(e){e.exports=JSON.parse('{"permalink":"/2016/03/tweet-like-me","source":"@site/blog/2016-03-28-tweet-like-me/index.mdx","title":"Tweet like me","description":"In which I try to create a robot that will tweet like I tweet.","date":"2016-03-28T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/tweet-like-me","title":"Tweet like me","date":"2016-03-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"},"nextItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"}}')}}]); \ No newline at end of file diff --git a/assets/js/761aff6b.101e026d.js b/assets/js/761aff6b.101e026d.js new file mode 100644 index 0000000..559982a --- /dev/null +++ b/assets/js/761aff6b.101e026d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7366"],{5623:function(e,n,t){t.r(n),t.d(n,{assets:function(){return i},contentTitle:function(){return l},default:function(){return d},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return c}});var s=t(5238),o=t(5893),a=t(65);let r={slug:"2019/02/a-heaping-helping",title:"Allocations in Rust: Dynamic memory",date:new Date("2019-02-07T12:00:00.000Z"),authors:["bspeice"],tags:[]},l=void 0,i={authorsImageUrls:[void 0]},c=[{value:"Smart pointers",id:"smart-pointers",level:2},{value:"Collections",id:"collections",level:2},{value:"Heap Alternatives",id:"heap-alternatives",level:2},{value:"Tracing Allocators",id:"tracing-allocators",level:2}];function h(e){let n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and\nsome languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how\nthe language uses dynamic memory (also referred to as the ",(0,o.jsx)(n.strong,{children:"heap"}),") is a system called ",(0,o.jsx)(n.em,{children:"ownership"}),".\nAnd as the docs mention, ownership\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html",children:"is Rust's most unique feature"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["The heap is used in two situations; when the compiler is unable to predict either the ",(0,o.jsx)(n.em,{children:"total size of\nmemory needed"}),", or ",(0,o.jsx)(n.em,{children:"how long the memory is needed for"}),", it allocates space in the heap."]}),"\n",(0,o.jsxs)(n.p,{children:["This happens\npretty frequently; if you want to download the Google home page, you won't know how large it is\nuntil your program runs. And when you're finished with Google, we deallocate the memory so it can be\nused to store other webpages. If you're interested in a slightly longer explanation of the heap,\ncheck out\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#the-stack-and-the-heap",children:"The Stack and the Heap"}),"\nin Rust's documentation."]}),"\n",(0,o.jsxs)(n.p,{children:["We won't go into detail on how the heap is managed; the\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html",children:"ownership documentation"}),' does a\nphenomenal job explaining both the "why" and "how" of memory management. Instead, we\'re going to\nfocus on understanding "when" heap allocations occur in Rust.']}),"\n",(0,o.jsx)(n.p,{children:"To start off, take a guess for how many allocations happen in the program below:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"fn main() {}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["It's obviously a trick question; while no heap allocations occur as a result of that code, the setup\nneeded to call ",(0,o.jsx)(n.code,{children:"main"})," does allocate on the heap. Here's a way to show it:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:'#![feature(integer_atomics)]\nuse std::alloc::{GlobalAlloc, Layout, System};\nuse std::sync::atomic::{AtomicU64, Ordering};\n\nstatic ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);\n\nstruct CountingAllocator;\n\nunsafe impl GlobalAlloc for CountingAllocator {\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\n ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst);\n System.alloc(layout)\n }\n\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\n System.dealloc(ptr, layout);\n }\n}\n\n#[global_allocator]\nstatic A: CountingAllocator = CountingAllocator;\n\nfn main() {\n let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst);\n println!("There were {} allocations before calling main!", x);\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["--\n",(0,o.jsx)(n.a,{href:"https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=fb5060025ba79fc0f906b65a4ef8eb8e",children:"Rust Playground"})]}),"\n",(0,o.jsxs)(n.p,{children:["As of the time of writing, there are five allocations that happen before ",(0,o.jsx)(n.code,{children:"main"})," is ever called."]}),"\n",(0,o.jsx)(n.p,{children:"But when we want to understand more practically where heap allocation happens, we'll follow this\nguide:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Smart pointers hold their contents in the heap"}),"\n",(0,o.jsx)(n.li,{children:"Collections are smart pointers for many objects at a time, and reallocate when they need to grow"}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:'Finally, there are two "addendum" issues that are important to address when discussing Rust and the\nheap:'}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Non-heap alternatives to many standard library types are available."}),"\n",(0,o.jsx)(n.li,{children:"Special allocators to track memory behavior should be used to benchmark code."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"smart-pointers",children:"Smart pointers"}),"\n",(0,o.jsx)(n.p,{children:'The first thing to note are the "smart pointer" types. When you have data that must outlive the\nscope in which it is declared, or your data is of unknown or dynamic size, you\'ll make use of these\ntypes.'}),"\n",(0,o.jsxs)(n.p,{children:["The term ",(0,o.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Smart_pointer",children:"smart pointer"})," comes from C++, and while it's\nclosely linked to a general design pattern of\n",(0,o.jsx)(n.a,{href:"https://en.cppreference.com/w/cpp/language/raii",children:'"Resource Acquisition Is Initialization"'}),", we'll\nuse it here specifically to describe objects that are responsible for managing ownership of data\nallocated on the heap. The smart pointers available in the ",(0,o.jsx)(n.code,{children:"alloc"})," crate should look mostly\nfamiliar:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/alloc/boxed/struct.Box.html",children:(0,o.jsx)(n.code,{children:"Box"})})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/alloc/rc/struct.Rc.html",children:(0,o.jsx)(n.code,{children:"Rc"})})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/alloc/sync/struct.Arc.html",children:(0,o.jsx)(n.code,{children:"Arc"})})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/alloc/borrow/enum.Cow.html",children:(0,o.jsx)(n.code,{children:"Cow"})})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/",children:"standard library"})," also defines some smart pointers to manage\nheap objects, though more than can be covered here. Some examples are:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/sync/struct.RwLock.html",children:(0,o.jsx)(n.code,{children:"RwLock"})})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/sync/struct.Mutex.html",children:(0,o.jsx)(n.code,{children:"Mutex"})})}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Finally, there is one ",(0,o.jsx)(n.a,{href:"https://www.merriam-webster.com/dictionary/gotcha",children:'"gotcha"'}),": ",(0,o.jsx)(n.strong,{children:"cell types"}),"\n(like ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html",children:(0,o.jsx)(n.code,{children:"RefCell"})}),") look and behave\nsimilarly, but ",(0,o.jsx)(n.strong,{children:"don't involve heap allocation"}),". The\n",(0,o.jsxs)(n.a,{href:"https://doc.rust-lang.org/stable/core/cell/index.html",children:[(0,o.jsx)(n.code,{children:"core::cell"})," docs"]})," have more information."]}),"\n",(0,o.jsxs)(n.p,{children:["When a smart pointer is created, the data it is given is placed in heap memory and the location of\nthat data is recorded in the smart pointer. Once the smart pointer has determined it's safe to\ndeallocate that memory (when a ",(0,o.jsx)(n.code,{children:"Box"})," has\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/std/boxed/index.html",children:"gone out of scope"})," or a reference count\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/alloc/rc/index.html",children:"goes to zero"}),"), the heap space is reclaimed. We can\nprove these types use heap memory by looking at code:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:'use std::rc::Rc;\nuse std::sync::Arc;\nuse std::borrow::Cow;\n\npub fn my_box() {\n // Drop at assembly line 1640\n Box::new(0);\n}\n\npub fn my_rc() {\n // Drop at assembly line 1650\n Rc::new(0);\n}\n\npub fn my_arc() {\n // Drop at assembly line 1660\n Arc::new(0);\n}\n\npub fn my_cow() {\n // Drop at assembly line 1672\n Cow::from("drop");\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["-- ",(0,o.jsx)(n.a,{href:"https://godbolt.org/z/4AMQug",children:"Compiler Explorer"})]}),"\n",(0,o.jsx)(n.h2,{id:"collections",children:"Collections"}),"\n",(0,o.jsxs)(n.p,{children:["Collection types use heap memory because their contents have dynamic size; they will request more\nmemory ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve",children:"when needed"}),", and can\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit",children:"release memory"})," when it's\nno longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In\na way, ",(0,o.jsx)(n.strong,{children:"collections are smart pointers for many objects at a time"}),". Common types that fall under\nthis umbrella are ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/alloc/vec/struct.Vec.html",children:(0,o.jsx)(n.code,{children:"Vec"})}),",\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html",children:(0,o.jsx)(n.code,{children:"HashMap"})}),", and\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/alloc/string/struct.String.html",children:(0,o.jsx)(n.code,{children:"String"})})," (not\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/primitive.str.html",children:(0,o.jsx)(n.code,{children:"str"})}),")."]}),"\n",(0,o.jsxs)(n.p,{children:["While collections store the objects they own in heap memory, ",(0,o.jsx)(n.em,{children:"creating new collections will not\nallocate on the heap"}),". This is a bit weird; if we call ",(0,o.jsx)(n.code,{children:"Vec::new()"}),", the assembly shows a\ncorresponding call to ",(0,o.jsx)(n.code,{children:"real_drop_in_place"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"pub fn my_vec() {\n // Drop in place at line 481\n Vec::<u8>::new();\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["-- ",(0,o.jsx)(n.a,{href:"https://godbolt.org/z/1WkNtC",children:"Compiler Explorer"})]}),"\n",(0,o.jsx)(n.p,{children:"But because the vector has no elements to manage, no calls to the allocator will ever be dispatched:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:'use std::alloc::{GlobalAlloc, Layout, System};\nuse std::sync::atomic::{AtomicBool, Ordering};\n\nfn main() {\n // Turn on panicking if we allocate on the heap\n DO_PANIC.store(true, Ordering::SeqCst);\n\n // Interesting bit happens here\n let x: Vec<u8> = Vec::new();\n drop(x);\n\n // Turn panicking back off, some deallocations occur\n // after main as well.\n DO_PANIC.store(false, Ordering::SeqCst);\n}\n\n#[global_allocator]\nstatic A: PanicAllocator = PanicAllocator;\nstatic DO_PANIC: AtomicBool = AtomicBool::new(false);\nstruct PanicAllocator;\n\nunsafe impl GlobalAlloc for PanicAllocator {\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\n if DO_PANIC.load(Ordering::SeqCst) {\n panic!("Unexpected allocation.");\n }\n System.alloc(layout)\n }\n\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\n if DO_PANIC.load(Ordering::SeqCst) {\n panic!("Unexpected deallocation.");\n }\n System.dealloc(ptr, layout);\n }\n}\n'})}),"\n",(0,o.jsxs)(n.p,{children:["--\n",(0,o.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=831a297d176d015b1f9ace01ae416cc6",children:"Rust Playground"})]}),"\n",(0,o.jsxs)(n.p,{children:["Other standard library types follow the same behavior; make sure to check out\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.new",children:(0,o.jsx)(n.code,{children:"HashMap::new()"})}),",\nand ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/string/struct.String.html#method.new",children:(0,o.jsx)(n.code,{children:"String::new()"})}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"heap-alternatives",children:"Heap Alternatives"}),"\n",(0,o.jsx)(n.p,{children:"While it is a bit strange to speak of the stack after spending time with the heap, it's worth\npointing out that some heap-allocated objects in Rust have stack-based counterparts provided by\nother crates. If you have need of the functionality, but want to avoid allocating, there are\ntypically alternatives available."}),"\n",(0,o.jsxs)(n.p,{children:["When it comes to some standard library smart pointers\n(",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/sync/struct.RwLock.html",children:(0,o.jsx)(n.code,{children:"RwLock"})})," and\n",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/sync/struct.Mutex.html",children:(0,o.jsx)(n.code,{children:"Mutex"})}),"), stack-based alternatives are\nprovided in crates like ",(0,o.jsx)(n.a,{href:"https://crates.io/crates/parking_lot",children:"parking_lot"})," and\n",(0,o.jsx)(n.a,{href:"https://crates.io/crates/spin",children:"spin"}),". You can check out\n",(0,o.jsx)(n.a,{href:"https://docs.rs/lock_api/0.1.5/lock_api/struct.RwLock.html",children:(0,o.jsx)(n.code,{children:"lock_api::RwLock"})}),",\n",(0,o.jsx)(n.a,{href:"https://docs.rs/lock_api/0.1.5/lock_api/struct.Mutex.html",children:(0,o.jsx)(n.code,{children:"lock_api::Mutex"})}),", and\n",(0,o.jsx)(n.a,{href:"https://mvdnes.github.io/rust-docs/spin-rs/spin/struct.Once.html",children:(0,o.jsx)(n.code,{children:"spin::Once"})})," if you're in need\nof synchronization primitives."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.a,{href:"https://crates.io/crates/thread-id",children:"thread_id"})," may be necessary if you're implementing an allocator\nbecause ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/thread/struct.ThreadId.html",children:(0,o.jsx)(n.code,{children:"thread::current().id()"})})," uses a\n",(0,o.jsxs)(n.a,{href:"https://doc.rust-lang.org/stable/src/std/sys_common/thread_info.rs.html#17-36",children:[(0,o.jsx)(n.code,{children:"thread_local!"})," structure"]}),"\nthat needs heap allocation."]}),"\n",(0,o.jsx)(n.h2,{id:"tracing-allocators",children:"Tracing Allocators"}),"\n",(0,o.jsxs)(n.p,{children:["When writing performance-sensitive code, there's no alternative to measuring your code. If you\ndidn't write a benchmark,\n",(0,o.jsx)(n.a,{href:"https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=263",children:"you don't care about it's performance"}),"\nYou should never rely on your instincts when\n",(0,o.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NH1Tta7purM",children:"a microsecond is an eternity"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Similarly, there's great work going on in Rust with allocators that keep track of what they're doing\n(like ",(0,o.jsx)(n.a,{href:"https://crates.io/crates/alloc_counter",children:(0,o.jsx)(n.code,{children:"alloc_counter"})}),"). When it comes to tracking heap\nbehavior, it's easy to make mistakes; please write tests and make sure you have tools to guard\nagainst future issues."]})]})}function d(e={}){let{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},65:function(e,n,t){t.d(n,{Z:function(){return l},a:function(){return r}});var s=t(7294);let o={},a=s.createContext(o);function r(e){let n=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(a.Provider,{value:n},e.children)}},5238:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/a-heaping-helping","source":"@site/blog/2019-02-07-a-heaping-helping/index.mdx","title":"Allocations in Rust: Dynamic memory","description":"Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and","date":"2019-02-07T12:00:00.000Z","tags":[],"readingTime":5.86,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/a-heaping-helping","title":"Allocations in Rust: Dynamic memory","date":"2019-02-07T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"},"nextItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/76b3b3f5.c2e17148.js b/assets/js/76b3b3f5.c2e17148.js new file mode 100644 index 0000000..cef5759 --- /dev/null +++ b/assets/js/76b3b3f5.c2e17148.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8987"],{3699:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return i},metadata:function(){return o},toc:function(){return c}});var o=n(6954),a=n(5893),r=n(65);let i={slug:"2018/12/allocation-safety",title:"QADAPT - debug_assert! for allocations",date:new Date("2018-12-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,l={authorsImageUrls:[void 0]},c=[];function u(e){let t={a:"a",blockquote:"blockquote",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I think it's part of the human condition to ignore perfectly good advice when it comes our way. A\nbit over a month ago, I was dispensing sage wisdom for the ages:"}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsxs)(t.p,{children:["I had a really great idea: build a custom allocator that allows you to track your own allocations.\nI gave it a shot, but learned very quickly: ",(0,a.jsx)(t.strong,{children:"never write your own allocator."})]}),"\n",(0,a.jsxs)(t.p,{children:["-- ",(0,a.jsx)(t.a,{href:"/2018/10/case-study-optimization",children:"me"})]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"I proceeded to ignore it, because we never really learn from our mistakes."})]})}function d(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return i}});var o=n(7294);let a={},r=o.createContext(a);function i(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(r.Provider,{value:t},e.children)}},6954:function(e){e.exports=JSON.parse('{"permalink":"/2018/12/allocation-safety","source":"@site/blog/2018-12-15-allocation-safety/index.mdx","title":"QADAPT - debug_assert! for allocations","description":"I think it\'s part of the human condition to ignore perfectly good advice when it comes our way. A","date":"2018-12-15T12:00:00.000Z","tags":[],"readingTime":4.775,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/allocation-safety","title":"QADAPT - debug_assert! for allocations","date":"2018-12-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"},"nextItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"}}')}}]); \ No newline at end of file diff --git a/assets/js/77bf0009.fdc32348.js b/assets/js/77bf0009.fdc32348.js new file mode 100644 index 0000000..8ee07a1 --- /dev/null +++ b/assets/js/77bf0009.fdc32348.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6240"],{5615:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return o},default:function(){return c},frontMatter:function(){return s},metadata:function(){return a},toc:function(){return h}});var a=n(3184),i=n(5893),r=n(65);let s={slug:"2019/05/making-bread",title:"Making bread",date:new Date("2019-05-03T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},h=[];function d(e){let t={a:"a",img:"img",p:"p",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:['Having recently started my "gardening leave" between positions, I have some more personal time\navailable. I\'m planning to stay productive, contributing to some open-source projects, but it also\noccurred to me that despite ',(0,i.jsx)(t.a,{href:"https://speice.io/2018/05/hello.html",children:"talking about"}),' bread pics, this\nblog has been purely technical. Maybe I\'ll change the site title from "The Old Speice Guy" to "Bites\nand Bytes"?']}),"\n",(0,i.jsx)(t.p,{children:"Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on\nsome lighter material. I recently learned two critically important lessons: first, the temperature\nof the dough when you put the yeast in makes a huge difference."}),"\n",(0,i.jsx)(t.p,{children:"Previously, when I wasn't paying attention to dough temperature:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Whole weat dough",src:n(8184).Z+"",width:"432",height:"549"})}),"\n",(0,i.jsx)(t.p,{children:"Compared with what happens when I put the dough in the microwave for a defrost cycle because the\nwater I used wasn't warm enough:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"White dough",src:n(3579).Z+"",width:"432",height:"438"})}),"\n",(0,i.jsx)(t.p,{children:"I mean, just look at the bubbles!"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"White dough with bubbles",src:n(1484).Z+"",width:"432",height:"428"})}),"\n",(0,i.jsx)(t.p,{children:"After shaping the dough, I've got two loaves ready:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Shaped loaves",src:n(4334).Z+"",width:"864",height:"486"})}),"\n",(0,i.jsx)(t.p,{children:"Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from\ndrying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the\nbottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot\nto add the water and learned my second lesson: never add room-temperature water to a glass dish\nthat's currently at 500 degrees."}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Shattered glass dish",src:n(2619).Z+"",width:"864",height:"486"})}),"\n",(0,i.jsx)(t.p,{children:"Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected\nto be doing during my garden leave."}),"\n",(0,i.jsx)(t.p,{children:"In the end, the bread crust wasn't great, but the bread itself turned out pretty alright:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"Baked bread",src:n(8379).Z+"",width:"864",height:"486"})}),"\n",(0,i.jsx)(t.p,{children:"I've been writing a lot more during this break, so I'm looking forward to sharing that in the\nfuture. In the mean-time, I'm planning on making a sandwich."})]})}function c(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8379:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/final-product-607f96e84dada915fa422a7e5d524ca1.jpg"},4334:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/shaped-loaves-cea15e9ccef6b180525abaee2d288880.jpg"},2619:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/shattered-glass-0b56af0302f7a8c3295bf43cbab77ffe.jpg"},1484:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/white-dough-rising-after-fold-d7a27f12c1d2be572807105d6d7321f3.jpg"},3579:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/white-dough-rising-before-fold-c5a4424f9a5227f1f8e86b13b436782c.jpg"},8184:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/whole-wheat-not-rising-922d19641c91922b7634fff1d6f15e6d.jpg"},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return s}});var a=n(7294);let i={},r=a.createContext(i);function s(e){let t=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:t},e.children)}},3184:function(e){e.exports=JSON.parse('{"permalink":"/2019/05/making-bread","source":"@site/blog/2019-05-03-making-bread/index.mdx","title":"Making bread","description":"Having recently started my \\"gardening leave\\" between positions, I have some more personal time","date":"2019-05-03T12:00:00.000Z","tags":[],"readingTime":1.61,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/05/making-bread","title":"Making bread","date":"2019-05-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"},"nextItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"}}')}}]); \ No newline at end of file diff --git a/assets/js/78d2eb38.6ac70e04.js b/assets/js/78d2eb38.6ac70e04.js new file mode 100644 index 0000000..8cbb4a8 --- /dev/null +++ b/assets/js/78d2eb38.6ac70e04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8977"],{5155:function(t,e,n){n.r(e),n.d(e,{assets:function(){return u},contentTitle:function(){return s},default:function(){return p},frontMatter:function(){return a},metadata:function(){return r},toc:function(){return l}});var r=n(845),i=n(5893),o=n(65);let a={slug:"2018/06/dateutil-parser-to-rust",title:"What I learned porting dateutil to Rust",date:new Date("2018-06-25T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},l=[];function c(t){let e={a:"a",p:"p",...(0,o.a)(),...t.components};return(0,i.jsxs)(e.p,{children:["I've mostly been a lurker in Rust for a while, making a couple small contributions here and there.\nSo launching ",(0,i.jsx)(e.a,{href:"https://github.com/bspeice/dtparse",children:"dtparse"})," feels like nice step towards becoming a\nfunctioning member of society. But not too much, because then you know people start asking you to\npay bills, and ain't nobody got time for that."]})}function p(t={}){let{wrapper:e}={...(0,o.a)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(c,{...t})}):c(t)}},65:function(t,e,n){n.d(e,{Z:function(){return s},a:function(){return a}});var r=n(7294);let i={},o=r.createContext(i);function a(t){let e=r.useContext(o);return r.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:a(t.components),r.createElement(o.Provider,{value:e},t.children)}},845:function(t){t.exports=JSON.parse('{"permalink":"/2018/06/dateutil-parser-to-rust","source":"@site/blog/2018-06-25-dateutil-parser-to-rust/index.mdx","title":"What I learned porting dateutil to Rust","description":"I\'ve mostly been a lurker in Rust for a while, making a couple small contributions here and there.","date":"2018-06-25T12:00:00.000Z","tags":[],"readingTime":6.99,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/06/dateutil-parser-to-rust","title":"What I learned porting dateutil to Rust","date":"2018-06-25T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"},"nextItem":{"title":"Hello!","permalink":"/2018/05/hello"}}')}}]); \ No newline at end of file diff --git a/assets/js/7ba60abf.8ef0d9fb.js b/assets/js/7ba60abf.8ef0d9fb.js new file mode 100644 index 0000000..6a2f605 --- /dev/null +++ b/assets/js/7ba60abf.8ef0d9fb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7702"],{9085:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return u},default:function(){return f},frontMatter:function(){return o},metadata:function(){return i},toc:function(){return l}});var i=n(3071),r=n(5893),a=n(65);let o={slug:"2016/02/profitability-using-the-investment-formula",title:"Profitability using the investment formula",date:new Date("2016-02-26T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,s={authorsImageUrls:[void 0]},l=[];function c(e){let t={p:"p",...(0,a.a)(),...e.components};return(0,r.jsx)(t.p,{children:"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?"})}function f(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return o}});var i=n(7294);let r={},a=i.createContext(r);function o(e){let t=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:t},e.children)}},3071:function(e){e.exports=JSON.parse('{"permalink":"/2016/02/profitability-using-the-investment-formula","source":"@site/blog/2016-02-26-profitability-using-the-investment-formula/index.mdx","title":"Profitability using the investment formula","description":"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?","date":"2016-02-26T12:00:00.000Z","tags":[],"readingTime":7.675,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/profitability-using-the-investment-formula","title":"Profitability using the investment formula","date":"2016-02-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"},"nextItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"}}')}}]); \ No newline at end of file diff --git a/assets/js/814f3328.1f5daeee.js b/assets/js/814f3328.1f5daeee.js new file mode 100644 index 0000000..9ca07ef --- /dev/null +++ b/assets/js/814f3328.1f5daeee.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["106"],{4200:function(t){t.exports=JSON.parse('{"title":"All posts","items":[{"title":"The webpack industrial complex","permalink":"/2011/11/webpack-industrial-complex","unlisted":false,"date":"2022-11-20T12:00:00.000Z","frontMatter":{"slug":"2011/11/webpack-industrial-complex","title":"The webpack industrial complex","date":"2022-11-20T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Release the GIL","permalink":"/2019/12/release-the-gil","unlisted":false,"date":"2019-12-14T12:00:00.000Z","frontMatter":{"slug":"2019/12/release-the-gil","title":"Release the GIL","date":"2019-12-14T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout","unlisted":false,"date":"2019-09-28T12:00:00.000Z","frontMatter":{"slug":"2019/09/binary-format-shootout","title":"Binary format shootout","date":"2019-09-28T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems","unlisted":false,"date":"2019-07-01T12:00:00.000Z","frontMatter":{"slug":"2019/06/high-performance-systems","title":"On building high performance systems","date":"2019-07-01T12:00:00.000Z","last_updated":{"date":"2019-09-21T12:00:00.000Z"},"authors":["bspeice"],"tags":[]}},{"title":"Making bread","permalink":"/2019/05/making-bread","unlisted":false,"date":"2019-05-03T12:00:00.000Z","frontMatter":{"slug":"2019/05/making-bread","title":"Making bread","date":"2019-05-03T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary","unlisted":false,"date":"2019-02-09T12:00:00.000Z","frontMatter":{"slug":"2019/02/summary","title":"Allocations in Rust: Summary","date":"2019-02-09T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations","unlisted":false,"date":"2019-02-08T12:00:00.000Z","frontMatter":{"title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","last_updated":{"date":"2019-02-10T12:00:00.000Z"},"tags":[]}},{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping","unlisted":false,"date":"2019-02-07T12:00:00.000Z","frontMatter":{"slug":"2019/02/a-heaping-helping","title":"Allocations in Rust: Dynamic memory","date":"2019-02-07T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up","unlisted":false,"date":"2019-02-06T12:00:00.000Z","frontMatter":{"slug":"2019/02/stacking-up","title":"Allocations in Rust: Fixed memory","date":"2019-02-06T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world","unlisted":false,"date":"2019-02-05T12:00:00.000Z","frontMatter":{"slug":"2019/02/the-whole-world","title":"Allocations in Rust: Global memory","date":"2019-02-05T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust","unlisted":false,"date":"2019-02-04T12:00:00.000Z","frontMatter":{"slug":"2019/02/understanding-allocations-in-rust","title":"Allocations in Rust: Foreword","date":"2019-02-04T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety","unlisted":false,"date":"2018-12-15T12:00:00.000Z","frontMatter":{"slug":"2018/12/allocation-safety","title":"QADAPT - debug_assert! for allocations","date":"2018-12-15T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means","unlisted":false,"date":"2018-12-04T12:00:00.000Z","frontMatter":{"slug":"2018/12/what-small-business-really-means","title":"More \\"what companies really mean\\"","date":"2018-12-04T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization","unlisted":false,"date":"2018-10-08T12:00:00.000Z","frontMatter":{"slug":"2018/10/case-study-optimization","title":"A case study in heaptrack","date":"2018-10-08T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps","unlisted":false,"date":"2018-09-15T12:00:00.000Z","frontMatter":{"slug":"2018/09/isomorphic-apps","title":"Isomorphic desktop apps with Rust","date":"2018-09-15T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird","unlisted":false,"date":"2018-09-01T12:00:00.000Z","frontMatter":{"slug":"2018/09/primitives-in-rust-are-weird","title":"Primitives in Rust are weird (and cool)","date":"2018-09-01T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust","unlisted":false,"date":"2018-06-25T12:00:00.000Z","frontMatter":{"slug":"2018/06/dateutil-parser-to-rust","title":"What I learned porting dateutil to Rust","date":"2018-06-25T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Hello!","permalink":"/2018/05/hello","unlisted":false,"date":"2018-05-28T12:00:00.000Z","frontMatter":{"slug":"2018/05/hello","title":"Hello!","date":"2018-05-28T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2","unlisted":false,"date":"2018-01-16T13:00:00.000Z","frontMatter":{"slug":"2018/01/captains-cookbook-part-2","title":"Captain\'s Cookbook: Practical usage","date":"2018-01-16T13:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1","unlisted":false,"date":"2018-01-16T12:00:00.000Z","frontMatter":{"slug":"2018/01/captains-cookbook-part-1","title":"Captain\'s Cookbook: Project setup","date":"2018-01-16T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression","unlisted":false,"date":"2016-11-01T12:00:00.000Z","frontMatter":{"slug":"2016/11/pca-audio-compression","title":"PCA audio compression","date":"2016-11-01T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting","unlisted":false,"date":"2016-10-22T12:00:00.000Z","frontMatter":{"slug":"2016/10/rustic-repodcasting","title":"A Rustic re-podcasting server","date":"2016-10-22T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases","unlisted":false,"date":"2016-06-08T12:00:00.000Z","frontMatter":{"slug":"2016/06/event-studies-and-earnings-releases","title":"Event studies and earnings releases","date":"2016-06-08T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino","unlisted":false,"date":"2016-05-15T12:00:00.000Z","frontMatter":{"slug":"2016/05/the-unfair-casino","title":"The unfair casino","date":"2016-05-15T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Tick tock...","permalink":"/2016/04/tick-tock","unlisted":false,"date":"2016-04-06T12:00:00.000Z","frontMatter":{"slug":"2016/04/tick-tock","title":"Tick tock...","date":"2016-04-06T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me","unlisted":false,"date":"2016-03-28T12:00:00.000Z","frontMatter":{"slug":"2016/03/tweet-like-me","title":"Tweet like me","date":"2016-03-28T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness","unlisted":false,"date":"2016-03-05T12:00:00.000Z","frontMatter":{"slug":"2016/03/predicting-santander-customer-happiness","title":"Predicting Santander customer happiness","date":"2016-03-05T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula","unlisted":false,"date":"2016-02-26T12:00:00.000Z","frontMatter":{"slug":"2016/02/profitability-using-the-investment-formula","title":"Profitability using the investment formula","date":"2016-02-26T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker","unlisted":false,"date":"2016-02-03T12:00:00.000Z","frontMatter":{"slug":"2016/02/guaranteed-money-maker","title":"Guaranteed money maker","date":"2016-02-03T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle","unlisted":false,"date":"2016-01-23T12:00:00.000Z","frontMatter":{"slug":"2016/01/cloudy-in-seattle","title":"Cloudy in Seattle","date":"2016-01-23T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather","unlisted":false,"date":"2016-01-01T12:00:00.000Z","frontMatter":{"slug":"2016/01/complaining-about-the-weather","title":"Complaining about the weather","date":"2016-01-01T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer","unlisted":false,"date":"2015-12-26T12:00:00.000Z","frontMatter":{"slug":"2015/12/testing-cramer","title":"Testing Cramer","date":"2015-12-26T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable","unlisted":false,"date":"2015-11-27T12:00:00.000Z","frontMatter":{"slug":"2015/11/autocallable","title":"Autocallable Bonds","date":"2015-11-27T12:00:00.000Z","authors":["bspeice"],"tags":[]}},{"title":"Welcome, and an algorithm","permalink":"/2015/11/welcome","unlisted":false,"date":"2015-11-19T12:00:00.000Z","frontMatter":{"slug":"2015/11/welcome","title":"Welcome, and an algorithm","date":"2015-11-19T12:00:00.000Z","last_update":{"date":"2015-12-05T12:00:00.000Z"},"authors":["bspeice"],"tags":[]}}]}')}}]); \ No newline at end of file diff --git a/assets/js/818287cf.09f82d49.js b/assets/js/818287cf.09f82d49.js new file mode 100644 index 0000000..a443e8e --- /dev/null +++ b/assets/js/818287cf.09f82d49.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5095"],{2181:function(s,e,n){n.r(e),n.d(e,{assets:function(){return c},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return l},metadata:function(){return a},toc:function(){return m}});var a=n(1915),t=n(5893),i=n(65);let l={slug:"2015/11/welcome",title:"Welcome, and an algorithm",date:new Date("2015-11-19T12:00:00.000Z"),last_update:{date:new Date("2015-12-05T12:00:00.000Z")},authors:["bspeice"],tags:[]},r=void 0,c={authorsImageUrls:[void 0]},m=[{value:"Trading Competition Optimization",id:"trading-competition-optimization",level:2},{value:"Calculating the Return",id:"calculating-the-return",level:2},{value:"Calculating the Sharpe ratio",id:"calculating-the-sharpe-ratio",level:2},{value:"Calculating the drawdown",id:"calculating-the-drawdown",level:2}];function h(s){let e={a:"a",annotation:"annotation",code:"code",h1:"h1",h2:"h2",hr:"hr",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mover:"mover",mrow:"mrow",mstyle:"mstyle",msub:"msub",mtable:"mtable",mtd:"mtd",mtext:"mtext",mtr:"mtr",p:"p",path:"path",pre:"pre",semantics:"semantics",span:"span",strong:"strong",svg:"svg",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.a)(),...s.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(e.p,{children:"Hello! Glad to meet you. I'm currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I'm working on!"}),"\n",(0,t.jsx)(e.p,{children:"To start things off, Columbia has been hosting a trading competition that myself and another partner are competing in. I'm including a notebook of the algorithm that we're using, just to give a simple overview of a miniature algorithm."}),"\n",(0,t.jsx)(e.p,{children:"The competition is scored in 3 areas:"}),"\n",(0,t.jsxs)(e.ul,{children:["\n",(0,t.jsx)(e.li,{children:"Total return"}),"\n",(0,t.jsx)(e.li,{children:(0,t.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Sharpe_ratio",children:"Sharpe ratio"})}),"\n",(0,t.jsx)(e.li,{children:"Maximum drawdown"}),"\n"]}),"\n",(0,t.jsx)(e.p,{children:"Our algorithm uses a basic momentum strategy: in the given list of potential portfolios, pick the stocks that have been performing well in the past 30 days. Then, optimize for return subject to the drawdown being below a specific level. We didn't include the Sharpe ratio as a constraint, mostly because we were a bit late entering the competition."}),"\n",(0,t.jsx)(e.p,{children:"I'll be updating this post with the results of our algorithm as they come along!"}),"\n",(0,t.jsx)(e.hr,{}),"\n",(0,t.jsxs)(e.p,{children:[(0,t.jsx)(e.strong,{children:"UPDATE 12/5/2015"}),": Now that the competition has ended, I wanted to update how the algorithm performed. Unfortunately, it didn't do very well. I'm planning to make some tweaks over the coming weeks, and do another forward test in January."]}),"\n",(0,t.jsxs)(e.ul,{children:["\n",(0,t.jsx)(e.li,{children:"After week 1: Down .1%"}),"\n",(0,t.jsx)(e.li,{children:"After week 2: Down 1.4%"}),"\n",(0,t.jsx)(e.li,{children:"After week 3: Flat"}),"\n"]}),"\n",(0,t.jsx)(e.p,{children:"And some statistics for all teams participating in the competition:"}),"\n",(0,t.jsxs)(e.table,{children:[(0,t.jsx)(e.thead,{children:(0,t.jsxs)(e.tr,{children:[(0,t.jsx)(e.th,{children:"Statistic"}),(0,t.jsx)(e.th,{children:"Value"})]})}),(0,t.jsxs)(e.tbody,{children:[(0,t.jsxs)(e.tr,{children:[(0,t.jsx)(e.td,{children:"Max Return"}),(0,t.jsx)(e.td,{children:"74.1%"})]}),(0,t.jsxs)(e.tr,{children:[(0,t.jsx)(e.td,{children:"Min Return"}),(0,t.jsx)(e.td,{children:"-97.4%"})]}),(0,t.jsxs)(e.tr,{children:[(0,t.jsx)(e.td,{children:"Average Return"}),(0,t.jsx)(e.td,{children:"-.1%"})]}),(0,t.jsxs)(e.tr,{children:[(0,t.jsx)(e.td,{children:"Std Dev of Returns"}),(0,t.jsx)(e.td,{children:"19.6%"})]})]})]}),"\n",(0,t.jsx)(e.hr,{}),"\n",(0,t.jsx)(e.h2,{id:"trading-competition-optimization",children:"Trading Competition Optimization"}),"\n",(0,t.jsx)(e.p,{children:(0,t.jsx)(e.strong,{children:"Goal: Max return given maximum Sharpe and Drawdown"})}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{className:"language-python",children:"from IPython.display import display\nimport Quandl\nfrom datetime import datetime, timedelta\n\ntickers = ['XOM', 'CVX', 'CLB', 'OXY', 'SLB']\nmarket_ticker = 'GOOG/NYSE_VOO'\nlookback = 30\nd_col = 'Close'\n\ndata = {tick: Quandl.get('YAHOO/{}'.format(tick))[-lookback:] for tick in tickers}\nmarket = Quandl.get(market_ticker)\n"})}),"\n",(0,t.jsx)(e.h2,{id:"calculating-the-return",children:"Calculating the Return"}),"\n",(0,t.jsx)(e.p,{children:"We first want to know how much each ticker returned over the prior period."}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{className:"language-python",children:"returns = {tick: data[tick][d_col].pct_change() for tick in tickers}\n\ndisplay({tick: returns[tick].mean() for tick in tickers})\n"})}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{children:" {'CLB': -0.0016320202164526894,\n 'CVX': 0.0010319531629488911,\n 'OXY': 0.00093418904454400551,\n 'SLB': 0.00098431254720448159,\n 'XOM': 0.00044165797556096868}\n"})}),"\n",(0,t.jsx)(e.h2,{id:"calculating-the-sharpe-ratio",children:"Calculating the Sharpe ratio"}),"\n",(0,t.jsxs)(e.p,{children:["Sharpe: ",(0,t.jsxs)(e.span,{className:"katex",children:[(0,t.jsx)(e.span,{className:"katex-mathml",children:(0,t.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,t.jsxs)(e.semantics,{children:[(0,t.jsx)(e.mrow,{children:(0,t.jsxs)(e.mfrac,{children:[(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mi,{children:"R"}),(0,t.jsx)(e.mo,{children:"\u2212"}),(0,t.jsxs)(e.msub,{children:[(0,t.jsx)(e.mi,{children:"R"}),(0,t.jsx)(e.mi,{children:"M"})]})]}),(0,t.jsx)(e.mi,{children:"\u03C3"})]})}),(0,t.jsx)(e.annotation,{encoding:"application/x-tex",children:"{R - R_M \\over \\sigma}"})]})})}),(0,t.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,t.jsxs)(e.span,{className:"base",children:[(0,t.jsx)(e.span,{className:"strut",style:{height:"1.2336em",verticalAlign:"-0.345em"}}),(0,t.jsx)(e.span,{className:"mord",children:(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,t.jsx)(e.span,{className:"mfrac",children:(0,t.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,t.jsxs)(e.span,{className:"vlist-r",children:[(0,t.jsxs)(e.span,{className:"vlist",style:{height:"0.8886em"},children:[(0,t.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,t.jsx)(e.span,{className:"mord mtight",children:(0,t.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"\u03C3"})})})]}),(0,t.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,t.jsxs)(e.span,{style:{top:"-3.4103em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,t.jsxs)(e.span,{className:"mord mtight",children:[(0,t.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.00773em"},children:"R"}),(0,t.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,t.jsxs)(e.span,{className:"mord mtight",children:[(0,t.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.00773em"},children:"R"}),(0,t.jsx)(e.span,{className:"msupsub",children:(0,t.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,t.jsxs)(e.span,{className:"vlist-r",children:[(0,t.jsx)(e.span,{className:"vlist",style:{height:"0.3448em"},children:(0,t.jsxs)(e.span,{style:{top:"-2.3567em",marginLeft:"-0.0077em",marginRight:"0.0714em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,t.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,t.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.10903em"},children:"M"})})]})}),(0,t.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsx)(e.span,{className:"vlist",style:{height:"0.1433em"},children:(0,t.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,t.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,t.jsx)(e.span,{})})})]})}),(0,t.jsx)(e.span,{className:"mclose nulldelimiter"})]})})]})})]})]}),"\n",(0,t.jsx)(e.p,{children:"We use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive."}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{className:"language-python",children:"market_returns = market.pct_change()\n\nsharpe = lambda ret: (ret.mean() - market_returns[d_col].mean()) / ret.std()\nsharpes = {tick: sharpe(returns[tick]) for tick in tickers}\n\ndisplay(sharpes)\n"})}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{children:" {'CLB': -0.10578734457846127,\n 'CVX': 0.027303529817677398,\n 'OXY': 0.022622210057414487,\n 'SLB': 0.026950946344858676,\n 'XOM': -0.0053519259698605499}\n"})}),"\n",(0,t.jsx)(e.h2,{id:"calculating-the-drawdown",children:"Calculating the drawdown"}),"\n",(0,t.jsx)(e.p,{children:"This one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change?"}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{className:"language-python",children:"drawdown = lambda ret: ret.abs().max()\ndrawdowns = {tick: drawdown(returns[tick]) for tick in tickers}\n\ndisplay(drawdowns)\n"})}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{children:" {'CLB': 0.043551495607375035,\n 'CVX': 0.044894389686214398,\n 'OXY': 0.051424517867144637,\n 'SLB': 0.034774627850375328,\n 'XOM': 0.035851524605672758}\n"})}),"\n",(0,t.jsx)(e.h1,{id:"performing-the-optimization",children:"Performing the optimization"}),"\n",(0,t.jsx)(e.span,{className:"katex-display",children:(0,t.jsxs)(e.span,{className:"katex",children:[(0,t.jsx)(e.span,{className:"katex-mathml",children:(0,t.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,t.jsxs)(e.semantics,{children:[(0,t.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,t.jsxs)(e.mtr,{children:[(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mi,{children:"m"}),(0,t.jsx)(e.mi,{children:"a"}),(0,t.jsx)(e.mi,{children:"x"}),(0,t.jsx)(e.mtext,{children:"\xa0\xa0"})]})})}),(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mrow,{}),(0,t.jsx)(e.mi,{children:"\u03BC"}),(0,t.jsx)(e.mo,{children:"\u22C5"}),(0,t.jsx)(e.mi,{children:"\u03C9"})]})})})]}),(0,t.jsxs)(e.mtr,{children:[(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mi,{children:"s"}),(0,t.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,t.jsx)(e.mi,{children:"t"}),(0,t.jsx)(e.mi,{mathvariant:"normal",children:"."}),(0,t.jsx)(e.mtext,{children:"\xa0\xa0"})]})})}),(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mrow,{}),(0,t.jsxs)(e.mover,{accent:"true",children:[(0,t.jsx)(e.mn,{children:"1"}),(0,t.jsx)(e.mo,{children:"\u20D7"})]}),(0,t.jsx)(e.mi,{children:"\u03C9"}),(0,t.jsx)(e.mo,{children:"="}),(0,t.jsx)(e.mn,{children:"1"})]})})})]}),(0,t.jsxs)(e.mtr,{children:[(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsx)(e.mrow,{})})}),(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mrow,{}),(0,t.jsxs)(e.mover,{accent:"true",children:[(0,t.jsx)(e.mi,{children:"S"}),(0,t.jsx)(e.mo,{children:"\u20D7"})]}),(0,t.jsx)(e.mi,{children:"\u03C9"}),(0,t.jsx)(e.mo,{children:"\u2265"}),(0,t.jsx)(e.mi,{children:"s"})]})})})]}),(0,t.jsxs)(e.mtr,{children:[(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsx)(e.mrow,{})})}),(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mrow,{}),(0,t.jsxs)(e.mover,{accent:"true",children:[(0,t.jsx)(e.mi,{children:"D"}),(0,t.jsx)(e.mo,{children:"\u20D7"})]}),(0,t.jsx)(e.mo,{children:"\u22C5"}),(0,t.jsx)(e.mi,{mathvariant:"normal",children:"\u2223"}),(0,t.jsx)(e.mi,{children:"\u03C9"}),(0,t.jsx)(e.mi,{mathvariant:"normal",children:"\u2223"}),(0,t.jsx)(e.mo,{children:"\u2264"}),(0,t.jsx)(e.mi,{children:"d"})]})})})]}),(0,t.jsxs)(e.mtr,{children:[(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsx)(e.mrow,{})})}),(0,t.jsx)(e.mtd,{children:(0,t.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mrow,{}),(0,t.jsxs)(e.mrow,{children:[(0,t.jsx)(e.mo,{fence:"true",children:"\u2223"}),(0,t.jsx)(e.mi,{children:"\u03C9"}),(0,t.jsx)(e.mo,{fence:"true",children:"\u2223"})]}),(0,t.jsx)(e.mo,{children:"\u2264"}),(0,t.jsx)(e.mi,{children:"l"})]})})})]})]}),(0,t.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nmax\\ \\ & \\mu \\cdot \\omega\\\\\ns.t.\\ \\ & \\vec{1} \\omega = 1\\\\\n& \\vec{S} \\omega \\ge s\\\\\n& \\vec{D} \\cdot | \\omega | \\le d\\\\\n& \\left|\\omega\\right| \\le l\\\\\n\\end{align*}"})]})})}),(0,t.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,t.jsxs)(e.span,{className:"base",children:[(0,t.jsx)(e.span,{className:"strut",style:{height:"7.8401em",verticalAlign:"-3.6701em"}}),(0,t.jsx)(e.span,{className:"mord",children:(0,t.jsxs)(e.span,{className:"mtable",children:[(0,t.jsx)(e.span,{className:"col-align-r",children:(0,t.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,t.jsxs)(e.span,{className:"vlist-r",children:[(0,t.jsxs)(e.span,{className:"vlist",style:{height:"4.17em"},children:[(0,t.jsxs)(e.span,{style:{top:"-6.33em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord mathnormal",children:"ma"}),(0,t.jsx)(e.span,{className:"mord mathnormal",children:"x"}),(0,t.jsx)(e.span,{className:"mspace",children:"\xa0"}),(0,t.jsx)(e.span,{className:"mspace",children:"\xa0"})]})]}),(0,t.jsxs)(e.span,{style:{top:"-4.7426em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord mathnormal",children:"s"}),(0,t.jsx)(e.span,{className:"mord",children:"."}),(0,t.jsx)(e.span,{className:"mord mathnormal",children:"t"}),(0,t.jsx)(e.span,{className:"mord",children:"."}),(0,t.jsx)(e.span,{className:"mspace",children:"\xa0"}),(0,t.jsx)(e.span,{className:"mspace",children:"\xa0"})]})]}),(0,t.jsxs)(e.span,{style:{top:"-3.1163em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord"})]}),(0,t.jsxs)(e.span,{style:{top:"-1.4899em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord"})]}),(0,t.jsxs)(e.span,{style:{top:"0.0101em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord"})]})]}),(0,t.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsx)(e.span,{className:"vlist",style:{height:"3.6701em"},children:(0,t.jsx)(e.span,{})})})]})}),(0,t.jsx)(e.span,{className:"col-align-l",children:(0,t.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,t.jsxs)(e.span,{className:"vlist-r",children:[(0,t.jsxs)(e.span,{className:"vlist",style:{height:"4.17em"},children:[(0,t.jsxs)(e.span,{style:{top:"-6.33em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord"}),(0,t.jsx)(e.span,{className:"mord mathnormal",children:"\u03BC"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,t.jsx)(e.span,{className:"mbin",children:"\u22C5"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C9"})]})]}),(0,t.jsxs)(e.span,{style:{top:"-4.7426em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord"}),(0,t.jsx)(e.span,{className:"mord accent",children:(0,t.jsx)(e.span,{className:"vlist-t",children:(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsxs)(e.span,{className:"vlist",style:{height:"0.9274em"},children:[(0,t.jsxs)(e.span,{style:{top:"-3em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord",children:"1"})]}),(0,t.jsxs)(e.span,{style:{top:"-3.2134em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"accent-body",style:{left:"-0.2355em"},children:(0,t.jsx)(e.span,{className:"overlay",style:{height:"0.714em",width:"0.471em"},children:(0,t.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.471em",height:"0.714em",style:{width:"0.471em"},viewBox:"0 0 471 714",preserveAspectRatio:"xMinYMin",children:(0,t.jsx)(e.path,{d:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z"})})})})]})]})})})}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C9"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mrel",children:"="}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mord",children:"1"})]})]}),(0,t.jsxs)(e.span,{style:{top:"-3.1163em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord"}),(0,t.jsx)(e.span,{className:"mord accent",children:(0,t.jsx)(e.span,{className:"vlist-t",children:(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsxs)(e.span,{className:"vlist",style:{height:"0.9663em"},children:[(0,t.jsxs)(e.span,{style:{top:"-3em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.05764em"},children:"S"})]}),(0,t.jsxs)(e.span,{style:{top:"-3.2523em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"accent-body",style:{left:"-0.1522em"},children:(0,t.jsx)(e.span,{className:"overlay",style:{height:"0.714em",width:"0.471em"},children:(0,t.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.471em",height:"0.714em",style:{width:"0.471em"},viewBox:"0 0 471 714",preserveAspectRatio:"xMinYMin",children:(0,t.jsx)(e.path,{d:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z"})})})})]})]})})})}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C9"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",children:"s"})]})]}),(0,t.jsxs)(e.span,{style:{top:"-1.4899em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord"}),(0,t.jsx)(e.span,{className:"mord accent",children:(0,t.jsx)(e.span,{className:"vlist-t",children:(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsxs)(e.span,{className:"vlist",style:{height:"0.9663em"},children:[(0,t.jsxs)(e.span,{style:{top:"-3em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"D"})]}),(0,t.jsxs)(e.span,{style:{top:"-3.2523em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsx)(e.span,{className:"accent-body",style:{left:"-0.1799em"},children:(0,t.jsx)(e.span,{className:"overlay",style:{height:"0.714em",width:"0.471em"},children:(0,t.jsx)(e.svg,{xmlns:"http://www.w3.org/2000/svg",width:"0.471em",height:"0.714em",style:{width:"0.471em"},viewBox:"0 0 471 714",preserveAspectRatio:"xMinYMin",children:(0,t.jsx)(e.path,{d:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z"})})})})]})]})})})}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,t.jsx)(e.span,{className:"mbin",children:"\u22C5"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,t.jsx)(e.span,{className:"mord",children:"\u2223"}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C9"}),(0,t.jsx)(e.span,{className:"mord",children:"\u2223"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",children:"d"})]})]}),(0,t.jsxs)(e.span,{style:{top:"0.0101em"},children:[(0,t.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,t.jsxs)(e.span,{className:"mord",children:[(0,t.jsx)(e.span,{className:"mord"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,t.jsxs)(e.span,{className:"minner",children:[(0,t.jsx)(e.span,{className:"mopen delimcenter",style:{top:"0em"},children:"\u2223"}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.03588em"},children:"\u03C9"}),(0,t.jsx)(e.span,{className:"mclose delimcenter",style:{top:"0em"},children:"\u2223"})]}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,t.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,t.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.01968em"},children:"l"})]})]})]}),(0,t.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,t.jsx)(e.span,{className:"vlist-r",children:(0,t.jsx)(e.span,{className:"vlist",style:{height:"3.6701em"},children:(0,t.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,t.jsx)(e.p,{children:"We want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don't have huge long/short positions."}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{className:"language-python",children:"import numpy as np\nfrom scipy.optimize import minimize\n\n#sharpe_limit = .1\ndrawdown_limit = .05\nleverage = 250\n\n# Use the map so we can guarantee we maintain the correct order\n\n# So we can write as upper-bound\n# sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1 \ndd_a = np.array(list(map(lambda tick: drawdowns[tick], tickers)))\n\n# Because minimizing\nreturns_a = np.array(list(map(lambda tick: returns[tick].mean(), tickers))) \n\nmeets_sharpe = lambda x: sum(abs(x) * sharpe_a) - sharpe_limit\ndef meets_dd(x):\n portfolio = sum(abs(x))\n if portfolio < .1:\n # If there are no stocks in the portfolio,\n # we can accidentally induce division by 0,\n # or division by something small enough to cause infinity\n return 0\n \n return drawdown_limit - sum(abs(x) * dd_a) / sum(abs(x))\n\nis_portfolio = lambda x: sum(x) - 1\n\ndef within_leverage(x):\n return leverage - sum(abs(x))\n\nobjective = lambda x: sum(x * returns_a) * -1 # Because we're minimizing\nbounds = ((None, None),) * len(tickers)\nx = np.zeros(len(tickers))\n\nconstraints = [\n {\n 'type': 'eq',\n 'fun': is_portfolio\n }, {\n 'type': 'ineq',\n 'fun': within_leverage\n #}, {\n # 'type': 'ineq',\n # 'fun': meets_sharpe\n }, {\n 'type': 'ineq',\n 'fun': meets_dd\n }\n]\n\noptimal = minimize(objective, x, bounds=bounds, constraints=constraints,\n options={'maxiter': 500})\n\n# Optimization time!\ndisplay(optimal.message)\n\ndisplay(\"Holdings: {}\".format(list(zip(tickers, optimal.x))))\n\n# multiply by -100 to scale, and compensate for minimizing\nexpected_return = optimal.fun * -100\ndisplay(\"Expected Return: {:.3f}%\".format(expected_return))\n\nexpected_drawdown = sum(abs(optimal.x) * dd_a) / sum(abs(optimal.x)) * 100\ndisplay(\"Expected Max Drawdown: {0:.2f}%\".format(expected_drawdown))\n\n# TODO: Calculate expected Sharpe\n"})}),"\n",(0,t.jsx)(e.pre,{children:(0,t.jsx)(e.code,{children:" 'Optimization terminated successfully.'\n \"Holdings: [('XOM', 5.8337945679814904),\n ('CVX', 42.935064321851307),\n ('CLB', -124.5),\n ('OXY', 36.790387773552119),\n ('SLB', 39.940753336615096)]\"\n 'Expected Return: 32.375%'\n 'Expected Max Drawdown: 4.34%'\n"})})]})}function d(s={}){let{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,t.jsx)(e,{...s,children:(0,t.jsx)(h,{...s})}):h(s)}},65:function(s,e,n){n.d(e,{Z:function(){return r},a:function(){return l}});var a=n(7294);let t={},i=a.createContext(t);function l(s){let e=a.useContext(i);return a.useMemo(function(){return"function"==typeof s?s(e):{...e,...s}},[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(t):s.components||t:l(s.components),a.createElement(i.Provider,{value:e},s.children)}},1915:function(s){s.exports=JSON.parse('{"permalink":"/2015/11/welcome","source":"@site/blog/2015-11-14-welcome/index.mdx","title":"Welcome, and an algorithm","description":"Hello! Glad to meet you. I\'m currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I\'m working on!","date":"2015-11-19T12:00:00.000Z","tags":[],"readingTime":4.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/welcome","title":"Welcome, and an algorithm","date":"2015-11-19T12:00:00.000Z","last_update":{"date":"2015-12-05T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1449316800000,"prevItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}}')}}]); \ No newline at end of file diff --git a/assets/js/84329d6a.ef47a922.js b/assets/js/84329d6a.ef47a922.js new file mode 100644 index 0000000..8cf441d --- /dev/null +++ b/assets/js/84329d6a.ef47a922.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2433"],{5241:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return m},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return l}});var o=n(610),i=n(5893),r=n(65);let a={slug:"2019/02/summary",title:"Allocations in Rust: Summary",date:new Date("2019-02-09T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},l=[];function c(e){let t={code:"code",p:"p",...(0,r.a)(),...e.components};return(0,i.jsxs)(t.p,{children:["While there's a lot of interesting detail captured in this series, it's often helpful to have a\ndocument that answers some \"yes/no\" questions. You may not care about what an ",(0,i.jsx)(t.code,{children:"Iterator"})," looks like\nin assembly, you just need to know whether it allocates an object on the heap or not. And while Rust\nwill prioritize the fastest behavior it can, here are the rules for each memory type:"]})}function m(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return a}});var o=n(7294);let i={},r=o.createContext(i);function a(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:t},e.children)}},610:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/summary","source":"@site/blog/2019-02-09-summary/index.mdx","title":"Allocations in Rust: Summary","description":"While there\'s a lot of interesting detail captured in this series, it\'s often helpful to have a","date":"2019-02-09T12:00:00.000Z","tags":[],"readingTime":1.095,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/summary","title":"Allocations in Rust: Summary","date":"2019-02-09T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Making bread","permalink":"/2019/05/making-bread"},"nextItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"}}')}}]); \ No newline at end of file diff --git a/assets/js/857496c7.71360a70.js b/assets/js/857496c7.71360a70.js new file mode 100644 index 0000000..953925a --- /dev/null +++ b/assets/js/857496c7.71360a70.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5168"],{1200:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return l},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return u}});var o=n(9810),i=n(5893),r=n(65);let a={slug:"2016/11/pca-audio-compression",title:"PCA audio compression",date:new Date("2016-11-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function p(e){let t={p:"p",...(0,r.a)(),...e.components};return(0,i.jsx)(t.p,{children:"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure."})}function l(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return a}});var o=n(7294);let i={},r=o.createContext(i);function a(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(r.Provider,{value:t},e.children)}},9810:function(e){e.exports=JSON.parse('{"permalink":"/2016/11/pca-audio-compression","source":"@site/blog/2016-11-01-PCA-audio-compression/index.mdx","title":"PCA audio compression","description":"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.","date":"2016-11-01T12:00:00.000Z","tags":[],"readingTime":10.39,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/11/pca-audio-compression","title":"PCA audio compression","date":"2016-11-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"},"nextItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"}}')}}]); \ No newline at end of file diff --git a/assets/js/85b3a5ed.c46f1e8b.js b/assets/js/85b3a5ed.c46f1e8b.js new file mode 100644 index 0000000..2c71739 --- /dev/null +++ b/assets/js/85b3a5ed.c46f1e8b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1874"],{2763:function(e,n,t){t.r(n),t.d(n,{assets:function(){return l},contentTitle:function(){return i},default:function(){return d},frontMatter:function(){return o},metadata:function(){return s},toc:function(){return c}});var s=t(2340),r=t(5893),a=t(65);let o={slug:"2019/02/stacking-up",title:"Allocations in Rust: Fixed memory",date:new Date("2019-02-06T12:00:00.000Z"),authors:["bspeice"],tags:[]},i=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Structs",id:"structs",level:2},{value:"Function arguments",id:"function-arguments",level:2},{value:"Enums",id:"enums",level:2},{value:"Arrays",id:"arrays",level:2},{value:"Closures",id:"closures",level:2},{value:"Generics",id:"generics",level:2},{value:"Copy types",id:"copy-types",level:2},{value:"Iterators",id:"iterators",level:2}];function h(e){let n={a:"a",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"const"})," and ",(0,r.jsx)(n.code,{children:"static"})," are perfectly fine, but it's relatively rare that we know at compile-time about\neither values or references that will be the same for the duration of our program. Put another way,\nit's not often the case that either you or your compiler knows how much memory your entire program\nwill ever need."]}),"\n",(0,r.jsx)(n.p,{children:'However, there are still some optimizations the compiler can do if it knows how much memory\nindividual functions will need. Specifically, the compiler can make use of "stack" memory (as\nopposed to "heap" memory) which can be managed far faster in both the short- and long-term.'}),"\n",(0,r.jsxs)(n.p,{children:["When requesting memory, the ",(0,r.jsxs)(n.a,{href:"http://www.cs.virginia.edu/~evans/cs216/guides/x86.html",children:[(0,r.jsx)(n.code,{children:"push"})," instruction"]}),"\ncan typically complete in ",(0,r.jsx)(n.a,{href:"https://agner.org/optimize/instruction_tables.ods",children:"1 or 2 cycles"})," (<1ns\non modern CPUs). Contrast that to heap memory which requires an allocator (specialized\nsoftware to track what memory is in use) to reserve space. When you're finished with stack memory,\nthe ",(0,r.jsx)(n.code,{children:"pop"})," instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory\nfragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have\nbeen used to design allocators:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)",children:"Garbage Collection"}),"\nstrategies like ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Tracing_garbage_collection",children:"Tracing"})," (used in\n",(0,r.jsx)(n.a,{href:"https://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html",children:"Java"}),") and\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Reference_counting",children:"Reference counting"})," (used in\n",(0,r.jsx)(n.a,{href:"https://docs.python.org/3/extending/extending.html#reference-counts",children:"Python"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["Thread-local structures to prevent locking the allocator in\n",(0,r.jsx)(n.a,{href:"https://jamesgolick.com/2013/5/19/how-tcmalloc-works.html",children:"tcmalloc"})]}),"\n",(0,r.jsxs)(n.li,{children:["Arena structures used in ",(0,r.jsx)(n.a,{href:"http://jemalloc.net/",children:"jemalloc"}),", which\n",(0,r.jsx)(n.a,{href:"https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#jemalloc-is-removed-by-default",children:"until recently"}),"\nwas the primary allocator for Rust programs!"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["But no matter how fast your allocator is, the principle remains: the fastest allocator is the one\nyou never use. As such, we're not going to discuss how exactly the\n",(0,r.jsxs)(n.a,{href:"http://www.cs.virginia.edu/~evans/cs216/guides/x86.html",children:[(0,r.jsx)(n.code,{children:"push"})," and ",(0,r.jsx)(n.code,{children:"pop"})," instructions work"]}),", but\nwe'll focus instead on the conditions that enable the Rust compiler to use faster stack-based\nallocation for variables."]}),"\n",(0,r.jsxs)(n.p,{children:["So, ",(0,r.jsx)(n.strong,{children:"how do we know when Rust will or will not use stack allocation for objects we create?"}),"\nLooking at other languages, it's often easy to delineate between stack and heap. Managed memory\nlanguages (Python, Java,\n",(0,r.jsx)(n.a,{href:"https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/",children:"C#"}),") place\neverything on the heap. JIT compilers (",(0,r.jsx)(n.a,{href:"https://www.pypy.org/",children:"PyPy"}),",\n",(0,r.jsx)(n.a,{href:"https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html",children:"HotSpot"}),") may optimize\nsome heap allocations away, but you should never assume it will happen. C makes things clear with\ncalls to special functions (like ",(0,r.jsx)(n.a,{href:"https://linux.die.net/man/3/malloc",children:"malloc(3)"}),") needed to access\nheap memory. Old C++ has the ",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/a/655086/1454178",children:(0,r.jsx)(n.code,{children:"new"})})," keyword, though\nmodern C++/C++11 is more complicated with ",(0,r.jsx)(n.a,{href:"https://en.cppreference.com/w/cpp/language/raii",children:"RAII"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["For Rust, we can summarize as follows: ",(0,r.jsx)(n.strong,{children:'stack allocation will be used for everything that doesn\'t\ninvolve "smart pointers" and collections'}),'. We\'ll skip over a precise definition of the term "smart\npointer" for now, and instead discuss what we should watch for to understand when stack and heap\nmemory regions are used:']}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Stack manipulation instructions (",(0,r.jsx)(n.code,{children:"push"}),", ",(0,r.jsx)(n.code,{children:"pop"}),", and ",(0,r.jsx)(n.code,{children:"add"}),"/",(0,r.jsx)(n.code,{children:"sub"})," of the ",(0,r.jsx)(n.code,{children:"rsp"})," register) indicate\nallocation of stack memory:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"pub fn stack_alloc(x: u32) -> u32 {\n // Space for `y` is allocated by subtracting from `rsp`,\n // and then populated\n let y = [1u8, 2, 3, 4];\n // Space for `y` is deallocated by adding back to `rsp`\n x\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/5WSgc9",children:"Compiler Explorer"})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch\nfor ",(0,r.jsx)(n.code,{children:"call core::ptr::real_drop_in_place"}),", and infer that a heap allocation happened in the recent\npast:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"pub fn heap_alloc(x: usize) -> usize {\n // Space for elements in a vector has to be allocated\n // on the heap, and is then de-allocated once the\n // vector goes out of scope\n let y: Vec<u8> = Vec::with_capacity(x);\n x\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/epfgoQ",children:"Compiler Explorer"})," (",(0,r.jsx)(n.code,{children:"real_drop_in_place"})," happens on line 1317)\n",(0,r.jsxs)("small",{children:["Note: While the\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/ops/trait.Drop.html",children:[(0,r.jsx)(n.code,{children:"Drop"})," trait"]})," is\n",(0,r.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87edf374d8983816eb3d8cfeac657b46",children:"called for stack-allocated objects"}),",\nthe Rust standard library only defines ",(0,r.jsx)(n.code,{children:"Drop"})," implementations for types that involve heap\nallocation."]})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["If you don't want to inspect the assembly, use a custom allocator that's able to track and alert\nwhen heap allocations occur. Crates like\n",(0,r.jsx)(n.a,{href:"https://crates.io/crates/alloc_counter",children:(0,r.jsx)(n.code,{children:"alloc_counter"})})," are designed for exactly this purpose."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"With all that in mind, let's talk about situations in which we're guaranteed to use stack memory:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Structs are created on the stack."}),"\n",(0,r.jsxs)(n.li,{children:["Function arguments are passed on the stack, meaning the\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/reference/attributes.html#inline-attribute",children:[(0,r.jsx)(n.code,{children:"#[inline]"})," attribute"]})," will\nnot change the memory region used."]}),"\n",(0,r.jsx)(n.li,{children:"Enums and unions are stack-allocated."}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/std/primitive.array.html",children:"Arrays"})," are always stack-allocated."]}),"\n",(0,r.jsx)(n.li,{children:"Closures capture their arguments on the stack."}),"\n",(0,r.jsx)(n.li,{children:"Generics will use stack allocation, even with dynamic dispatch."}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Copy.html",children:(0,r.jsx)(n.code,{children:"Copy"})})," types are guaranteed to be\nstack-allocated, and copying them will be done in stack memory."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/iter/trait.Iterator.html",children:[(0,r.jsx)(n.code,{children:"Iterator"}),"s"]})," in the standard library are\nstack-allocated even when iterating over heap-based collections."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"structs",children:"Structs"}),"\n",(0,r.jsxs)(n.p,{children:["The simplest case comes first. When creating vanilla ",(0,r.jsx)(n.code,{children:"struct"})," objects, we use stack memory to hold\ntheir contents:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"struct Point {\n x: u64,\n y: u64,\n}\n\nstruct Line {\n a: Point,\n b: Point,\n}\n\npub fn make_line() {\n // `origin` is stored in the first 16 bytes of memory\n // starting at location `rsp`\n let origin = Point { x: 0, y: 0 };\n // `point` makes up the next 16 bytes of memory\n let point = Point { x: 1, y: 2 };\n\n // When creating `ray`, we just move the content out of\n // `origin` and `point` into the next 32 bytes of memory\n let ray = Line { a: origin, b: point };\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/vri9BE",children:"Compiler Explorer"})]}),"\n",(0,r.jsxs)(n.p,{children:["Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the\n",(0,r.jsx)(n.code,{children:"sub rsp, 64"})," instruction indicates we're still working with the stack."]}),"\n",(0,r.jsx)(n.h2,{id:"function-arguments",children:"Function arguments"}),"\n",(0,r.jsxs)(n.p,{children:['Have you ever wondered how functions communicate with each other? Like, once the variables are given\nto you, everything\'s fine. But how do you "give" those variables to another function? How do you get\nthe results back afterward? The answer: the compiler arranges memory and assembly instructions using\na pre-determined ',(0,r.jsx)(n.a,{href:"http://llvm.org/docs/LangRef.html#calling-conventions",children:"calling convention"}),". This\nconvention governs the rules around where arguments needed by a function will be located (either in\nmemory offsets relative to the stack pointer ",(0,r.jsx)(n.code,{children:"rsp"}),", or in other registers), and where the results\ncan be found once the function has finished. And when multiple languages agree on what the calling\nconventions are, you can do things like having ",(0,r.jsx)(n.a,{href:"https://blog.filippo.io/rustgo/",children:"Go call Rust code"}),"!"]}),"\n",(0,r.jsx)(n.p,{children:"Put simply: it's the compiler's job to figure out how to call other functions, and you can assume\nthat the compiler is good at its job."}),"\n",(0,r.jsx)(n.p,{children:"We can see this in action using a simple example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"struct Point {\n x: i64,\n y: i64,\n}\n\n// We use integer division operations to keep\n// the assembly clean, understanding the result\n// isn't accurate.\nfn distance(a: &Point, b: &Point) -> i64 {\n // Immediately subtract from `rsp` the bytes needed\n // to hold all the intermediate results - this is\n // the stack allocation step\n\n // The compiler used the `rdi` and `rsi` registers\n // to pass our arguments, so read them in\n let x1 = a.x;\n let x2 = b.x;\n let y1 = a.y;\n let y2 = b.y;\n\n // Do the actual math work\n let x_pow = (x1 - x2) * (x1 - x2);\n let y_pow = (y1 - y2) * (y1 - y2);\n let squared = x_pow + y_pow;\n squared / squared\n\n // Our final result will be stored in the `rax` register\n // so that our caller knows where to retrieve it.\n // Finally, add back to `rsp` the stack memory that is\n // now ready to be used by other functions.\n}\n\npub fn total_distance() {\n let start = Point { x: 1, y: 2 };\n let middle = Point { x: 3, y: 4 };\n let end = Point { x: 5, y: 6 };\n\n let _dist_1 = distance(&start, &middle);\n let _dist_2 = distance(&middle, &end);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/Qmx4ST",children:"Compiler Explorer"})]}),"\n",(0,r.jsxs)(n.p,{children:["As a consequence of function arguments never using heap memory, we can also infer that functions\nusing the ",(0,r.jsx)(n.code,{children:"#[inline]"})," attributes also do not heap allocate. But better than inferring, we can look\nat the assembly to prove it:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"struct Point {\n x: i64,\n y: i64,\n}\n\n// Note that there is no `distance` function in the assembly output,\n// and the total line count goes from 229 with inlining off\n// to 306 with inline on. Even still, no heap allocations occur.\n#[inline(always)]\nfn distance(a: &Point, b: &Point) -> i64 {\n let x1 = a.x;\n let x2 = b.x;\n let y1 = a.y;\n let y2 = b.y;\n\n let x_pow = (a.x - b.x) * (a.x - b.x);\n let y_pow = (a.y - b.y) * (a.y - b.y);\n let squared = x_pow + y_pow;\n squared / squared\n}\n\npub fn total_distance() {\n let start = Point { x: 1, y: 2 };\n let middle = Point { x: 3, y: 4 };\n let end = Point { x: 5, y: 6 };\n\n let _dist_1 = distance(&start, &middle);\n let _dist_2 = distance(&middle, &end);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/30Sh66",children:"Compiler Explorer"})]}),"\n",(0,r.jsxs)(n.p,{children:["Finally, passing by value (arguments with type\n",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Copy.html",children:(0,r.jsx)(n.code,{children:"Copy"})}),") and passing by reference (either\nmoving ownership or passing a pointer) may have slightly different layouts in assembly, but will\nstill use either stack memory or CPU registers:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"pub struct Point {\n x: i64,\n y: i64,\n}\n\n// Moving values\npub fn distance_moved(a: Point, b: Point) -> i64 {\n let x1 = a.x;\n let x2 = b.x;\n let y1 = a.y;\n let y2 = b.y;\n\n let x_pow = (x1 - x2) * (x1 - x2);\n let y_pow = (y1 - y2) * (y1 - y2);\n let squared = x_pow + y_pow;\n squared / squared\n}\n\n// Borrowing values has two extra `mov` instructions on lines 21 and 22\npub fn distance_borrowed(a: &Point, b: &Point) -> i64 {\n let x1 = a.x;\n let x2 = b.x;\n let y1 = a.y;\n let y2 = b.y;\n\n let x_pow = (x1 - x2) * (x1 - x2);\n let y_pow = (y1 - y2) * (y1 - y2);\n let squared = x_pow + y_pow;\n squared / squared\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/06hGiv",children:"Compiler Explorer"})]}),"\n",(0,r.jsx)(n.h2,{id:"enums",children:"Enums"}),"\n",(0,r.jsxs)(n.p,{children:["If you've ever worried that wrapping your types in\n",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/core/option/enum.Option.html",children:(0,r.jsx)(n.code,{children:"Option"})})," or\n",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/core/result/enum.Result.html",children:(0,r.jsx)(n.code,{children:"Result"})})," would finally make them\nlarge enough that Rust decides to use heap allocation instead, fear no longer: ",(0,r.jsx)(n.code,{children:"enum"})," and union\ntypes don't use heap allocation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"enum MyEnum {\n Small(u8),\n Large(u64)\n}\n\nstruct MyStruct {\n x: MyEnum,\n y: MyEnum,\n}\n\npub fn enum_compare() {\n let x = MyEnum::Small(0);\n let y = MyEnum::Large(0);\n\n let z = MyStruct { x, y };\n\n let opt = Option::Some(z);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/HK7zBx",children:"Compiler Explorer"})]}),"\n",(0,r.jsxs)(n.p,{children:["Because the size of an ",(0,r.jsx)(n.code,{children:"enum"})," is the size of its largest element plus a flag, the compiler can\npredict how much memory is used no matter which variant of an enum is currently stored in a\nvariable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great\nway to show this in assembly, so I'll instead point you to the\n",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums",children:(0,r.jsx)(n.code,{children:"core::mem::size_of"})}),"\ndocumentation."]}),"\n",(0,r.jsx)(n.h2,{id:"arrays",children:"Arrays"}),"\n",(0,r.jsx)(n.p,{children:"The array type is guaranteed to be stack allocated, which is why the array size must be declared.\nInterestingly enough, this can be used to cause safe Rust programs to crash:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"// 256 bytes\n#[derive(Default)]\nstruct TwoFiftySix {\n _a: [u64; 32]\n}\n\n// 8 kilobytes\n#[derive(Default)]\nstruct EightK {\n _a: [TwoFiftySix; 32]\n}\n\n// 256 kilobytes\n#[derive(Default)]\nstruct TwoFiftySixK {\n _a: [EightK; 32]\n}\n\n// 8 megabytes - exceeds space typically provided for the stack,\n// though the kernel can be instructed to allocate more.\n// On Linux, you can check stack size using `ulimit -s`\n#[derive(Default)]\nstruct EightM {\n _a: [TwoFiftySixK; 32]\n}\n\nfn main() {\n // Because we already have things in stack memory\n // (like the current function call stack), allocating another\n // eight megabytes of stack memory crashes the program\n let _x = EightM::default();\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["--\n",(0,r.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=587a6380a4914bcbcef4192c90c01dc4",children:"Rust Playground"})]}),"\n",(0,r.jsx)(n.p,{children:"There aren't any security implications of this (no memory corruption occurs), but it's good to note\nthat the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to\noverflow the stack."}),"\n",(0,r.jsx)(n.h2,{id:"closures",children:"Closures"}),"\n",(0,r.jsxs)(n.p,{children:["Rules for how anonymous functions capture their arguments are typically language-specific. In Java,\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html",children:"Lambda Expressions"})," are\nactually objects created on the heap that capture local primitives by copying, and capture local\nnon-primitives as (",(0,r.jsx)(n.code,{children:"final"}),") references.\n",(0,r.jsx)(n.a,{href:"https://docs.python.org/3.7/reference/expressions.html#lambda",children:"Python"})," and\n",(0,r.jsx)(n.a,{href:"https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/",children:"JavaScript"}),"\nboth bind ",(0,r.jsx)(n.em,{children:"everything"})," by reference normally, but Python can also\n",(0,r.jsx)(n.a,{href:"https://stackoverflow.com/a/235764/1454178",children:"capture values"})," and JavaScript has\n",(0,r.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions",children:"Arrow functions"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"In Rust, arguments to closures are the same as arguments to other functions; closures are simply\nfunctions that don't have a declared name. Some weird ordering of the stack may be required to\nhandle them, but it's the compiler's responsiblity to figure that out."}),"\n",(0,r.jsx)(n.p,{children:"Each example below has the same effect, but a different assembly implementation. In the simplest\ncase, we immediately run a closure returned by another function. Because we don't store a reference\nto the closure, the stack memory needed to store the captured values is contiguous:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"fn my_func() -> impl FnOnce() {\n let x = 24;\n // Note that this closure in assembly looks exactly like\n // any other function; you even use the `call` instruction\n // to start running it.\n move || { x; }\n}\n\npub fn immediate() {\n my_func()();\n my_func()();\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/mgJ2zl",children:"Compiler Explorer"}),", 25 total assembly instructions"]}),"\n",(0,r.jsx)(n.p,{children:"If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory\nof the original function. Getting the details right is a bit harder, so the instruction count goes\nup even though this code is functionally equivalent to our original example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"pub fn simple_reference() {\n let x = my_func();\n let y = my_func();\n y();\n x();\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/K_dj5n",children:"Compiler Explorer"}),", 55 total assembly instructions"]}),"\n",(0,r.jsx)(n.p,{children:"Even things like variable order can make a difference in instruction count:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"pub fn complex() {\n let x = my_func();\n let y = my_func();\n x();\n y();\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/p37qFl",children:"Compiler Explorer"}),", 70 total assembly instructions"]}),"\n",(0,r.jsx)(n.p,{children:"In every circumstance though, the compiler ensured that no heap allocations were necessary."}),"\n",(0,r.jsx)(n.h2,{id:"generics",children:"Generics"}),"\n",(0,r.jsxs)(n.p,{children:["Traits in Rust come in two broad forms: static dispatch (monomorphization, ",(0,r.jsx)(n.code,{children:"impl Trait"}),") and dynamic\ndispatch (trait objects, ",(0,r.jsx)(n.code,{children:"dyn Trait"}),"). While dynamic dispatch is often ",(0,r.jsx)(n.em,{children:"associated"})," with trait\nobjects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"trait GetInt {\n fn get_int(&self) -> u64;\n}\n\n// vtable stored at section L__unnamed_1\nstruct WhyNotU8 {\n x: u8\n}\nimpl GetInt for WhyNotU8 {\n fn get_int(&self) -> u64 {\n self.x as u64\n }\n}\n\n// vtable stored at section L__unnamed_2\nstruct ActualU64 {\n x: u64\n}\nimpl GetInt for ActualU64 {\n fn get_int(&self) -> u64 {\n self.x\n }\n}\n\n// `&dyn` declares that we want to use dynamic dispatch\n// rather than monomorphization, so there is only one\n// `retrieve_int` function that shows up in the final assembly.\n// If we used generics, there would be one implementation of\n// `retrieve_int` for each type that implements `GetInt`.\npub fn retrieve_int(u: &dyn GetInt) {\n // In the assembly, we just call an address given to us\n // in the `rsi` register and hope that it was set up\n // correctly when this function was invoked.\n let x = u.get_int();\n}\n\npub fn do_call() {\n // Note that even though the vtable for `WhyNotU8` and\n // `ActualU64` includes a pointer to\n // `core::ptr::real_drop_in_place`, it is never invoked.\n let a = WhyNotU8 { x: 0 };\n let b = ActualU64 { x: 0 };\n\n retrieve_int(&a);\n retrieve_int(&b);\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/u_yguS",children:"Compiler Explorer"})]}),"\n",(0,r.jsx)(n.p,{children:"It's hard to imagine practical situations where dynamic dispatch would be used for objects that\naren't heap allocated, but it technically can be done."}),"\n",(0,r.jsx)(n.h2,{id:"copy-types",children:"Copy types"}),"\n",(0,r.jsxs)(n.p,{children:["Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs\n",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/stable/core/marker/trait.Copy.html",children:"go into detail"})," far better than can\nbe addressed here, so I'll leave them to do the job. From a memory perspective though, their\nguideline is reasonable:\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/stable/core/marker/trait.Copy.html#when-should-my-type-be-copy",children:["if your type can implemement ",(0,r.jsx)(n.code,{children:"Copy"}),", it should"]}),".\nWhile there are potential speed tradeoffs to ",(0,r.jsx)(n.em,{children:"benchmark"})," when discussing ",(0,r.jsx)(n.code,{children:"Copy"})," (move semantics for\nstack objects vs. copying stack pointers vs. copying stack ",(0,r.jsx)(n.code,{children:"struct"}),"s), ",(0,r.jsxs)(n.em,{children:["it's impossible for ",(0,r.jsx)(n.code,{children:"Copy"}),"\nto introduce a heap allocation"]}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["But why is this the case? Fundamentally, it's because the language controls what ",(0,r.jsx)(n.code,{children:"Copy"})," means -\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone",children:['"the behavior of ',(0,r.jsx)(n.code,{children:"Copy"}),' is not overloadable"']}),"\nbecause it's a marker trait. From there we'll note that a type\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Copy.html#when-can-my-type-be-copy",children:["can implement ",(0,r.jsx)(n.code,{children:"Copy"})]}),"\nif (and only if) its components implement ",(0,r.jsx)(n.code,{children:"Copy"}),", and that\n",(0,r.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Copy.html#implementors",children:["no heap-allocated types implement ",(0,r.jsx)(n.code,{children:"Copy"})]}),".\nThus, assignments involving heap types are always move semantics, and new heap allocations won't\noccur because of implicit operator behavior."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"#[derive(Clone)]\nstruct Cloneable {\n x: Box<u64>\n}\n\n// error[E0204]: the trait `Copy` may not be implemented for this type\n#[derive(Copy, Clone)]\nstruct NotCopyable {\n x: Box<u64>\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/VToRuK",children:"Compiler Explorer"})]}),"\n",(0,r.jsx)(n.h2,{id:"iterators",children:"Iterators"}),"\n",(0,r.jsxs)(n.p,{children:["In managed memory languages (like\n",(0,r.jsx)(n.a,{href:"https://www.youtube.com/watch?v=bSkpMdDe4g4&feature=youtu.be&t=357",children:"Java"}),"), there's a subtle\ndifference between these two code samples:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'public static int sum_for(List<Long> vals) {\n long sum = 0;\n // Regular for loop\n for (int i = 0; i < vals.length; i++) {\n sum += vals[i];\n }\n return sum;\n}\n\npublic static int sum_foreach(List<Long> vals) {\n long sum = 0;\n // "Foreach" loop - uses iteration\n for (Long l : vals) {\n sum += l;\n }\n return sum;\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["In the ",(0,r.jsx)(n.code,{children:"sum_for"})," function, nothing terribly interesting happens. In ",(0,r.jsx)(n.code,{children:"sum_foreach"}),", an object of type\n",(0,r.jsx)(n.a,{href:"https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html",children:(0,r.jsx)(n.code,{children:"Iterator"})}),"\nis allocated on the heap, and will eventually be garbage-collected. This isn't a great design;\niterators are often transient objects that you need during a function and can discard once the\nfunction ends. Sounds exactly like the issue stack-allocated objects address, no?"]}),"\n",(0,r.jsxs)(n.p,{children:["In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in\nheap memory, but the iterator itself\n(",(0,r.jsx)(n.a,{href:"https://doc.rust-lang.org/std/slice/struct.Iter.html",children:(0,r.jsx)(n.code,{children:"Iter"})}),") doesn't need to use the heap. In\neach of the examples below we iterate over a collection, but never use heap allocation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-rust",children:"use std::collections::HashMap;\n// There's a lot of assembly generated, but if you search in the text,\n// there are no references to `real_drop_in_place` anywhere.\n\npub fn sum_vec(x: &Vec<u32>) {\n let mut s = 0;\n // Basic iteration over vectors doesn't need allocation\n for y in x {\n s += y;\n }\n}\n\npub fn sum_enumerate(x: &Vec<u32>) {\n let mut s = 0;\n // More complex iterators are just fine too\n for (_i, y) in x.iter().enumerate() {\n s += y;\n }\n}\n\npub fn sum_hm(x: &HashMap<u32, u32>) {\n let mut s = 0;\n // And it's not just Vec, all types will allocate the iterator\n // on stack memory\n for y in x.values() {\n s += y;\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["-- ",(0,r.jsx)(n.a,{href:"https://godbolt.org/z/FTT3CT",children:"Compiler Explorer"})]})]})}function d(e={}){let{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},65:function(e,n,t){t.d(n,{Z:function(){return i},a:function(){return o}});var s=t(7294);let r={},a=s.createContext(r);function o(e){let n=s.useContext(a);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(a.Provider,{value:n},e.children)}},2340:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/stacking-up","source":"@site/blog/2019-02-06-stacking-up/index.mdx","title":"Allocations in Rust: Fixed memory","description":"const and static are perfectly fine, but it\'s relatively rare that we know at compile-time about","date":"2019-02-06T12:00:00.000Z","tags":[],"readingTime":15.165,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/stacking-up","title":"Allocations in Rust: Fixed memory","date":"2019-02-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"},"nextItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"}}')}}]); \ No newline at end of file diff --git a/assets/js/868a7989.8d7c3544.js b/assets/js/868a7989.8d7c3544.js new file mode 100644 index 0000000..ce2b0de --- /dev/null +++ b/assets/js/868a7989.8d7c3544.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5969"],{3807:function(e,t,n){n.r(t),n.d(t,{default:function(){return c}});var s=n(5893),u=n(4819);let c=()=>(0,s.jsx)(u.Z,{children:(0,s.jsx)("meta",{httpEquiv:"Refresh",content:"0; url='/atom.xml'"})})}}]); \ No newline at end of file diff --git a/assets/js/88eed8c4.1f2da266.js b/assets/js/88eed8c4.1f2da266.js new file mode 100644 index 0000000..779e831 --- /dev/null +++ b/assets/js/88eed8c4.1f2da266.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1652"],{4257:function(e,n,t){t.r(n),t.d(n,{assets:function(){return c},contentTitle:function(){return a},default:function(){return h},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return o}});var s=t(1495),i=t(5893),l=t(65);let r={slug:"2019/02/the-whole-world",title:"Allocations in Rust: Global memory",date:new Date("2019-02-05T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,c={authorsImageUrls:[void 0]},o=[{value:"<code>const</code> values",id:"const-values",level:2},{value:"Read-Only",id:"read-only",level:3},{value:"Initialization",id:"initialization",level:3},{value:"Copying",id:"copying",level:3},{value:"<code>static</code> values",id:"static-values",level:2},{value:"Memory Uniqueness",id:"memory-uniqueness",level:3},{value:"Initialization",id:"initialization-1",level:3},{value:"The <code>Sync</code> marker",id:"the-sync-marker",level:3},{value:"Interior mutability",id:"interior-mutability",level:3}];function d(e){let n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["The first memory type we'll look at is pretty special: when Rust can prove that a ",(0,i.jsx)(n.em,{children:"value"})," is fixed\nfor the life of a program (",(0,i.jsx)(n.code,{children:"const"}),"), and when a ",(0,i.jsx)(n.em,{children:"reference"})," is unique for the life of a program\n(",(0,i.jsx)(n.code,{children:"static"})," as a declaration, not\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#the-static-lifetime",children:(0,i.jsx)(n.code,{children:"'static"})})," as a\nlifetime), we can make use of global memory. This special section of data is embedded directly in\nthe program binary so that variables are ready to go once the program loads; no additional\ncomputation is necessary."]}),"\n",(0,i.jsxs)(n.p,{children:["Understanding the value/reference distinction is important for reasons we'll go into below, and\nwhile the\n",(0,i.jsx)(n.a,{href:"https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md",children:"full specification"})," for\nthese two keywords is available, we'll take a hands-on approach to the topic."]}),"\n",(0,i.jsxs)(n.h2,{id:"const-values",children:[(0,i.jsx)(n.code,{children:"const"})," values"]}),"\n",(0,i.jsxs)(n.p,{children:["When a ",(0,i.jsx)(n.em,{children:"value"}),' is guaranteed to be unchanging in your program (where "value" may be scalars,\n',(0,i.jsx)(n.code,{children:"struct"}),"s, etc.), you can declare it ",(0,i.jsx)(n.code,{children:"const"}),". This tells the compiler that it's safe to treat the\nvalue as never changing, and enables some interesting optimizations; not only is there no\ninitialization cost to creating the value (it is loaded at the same time as the executable parts of\nyour program), but the compiler can also copy the value around if it speeds up the code."]}),"\n",(0,i.jsxs)(n.p,{children:["The points we need to address when talking about ",(0,i.jsx)(n.code,{children:"const"})," are:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Const"})," values are stored in read-only memory - it's impossible to modify."]}),"\n",(0,i.jsxs)(n.li,{children:["Values resulting from calling a ",(0,i.jsx)(n.code,{children:"const fn"})," are materialized at compile-time."]}),"\n",(0,i.jsxs)(n.li,{children:["The compiler may (or may not) copy ",(0,i.jsx)(n.code,{children:"const"})," values wherever it chooses."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"read-only",children:"Read-Only"}),"\n",(0,i.jsxs)(n.p,{children:['The first point is a bit strange - "read-only memory."\n',(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants",children:"The Rust book"}),"\nmentions in a couple places that using ",(0,i.jsx)(n.code,{children:"mut"})," with constants is illegal, but it's also important to\ndemonstrate just how immutable they are. ",(0,i.jsx)(n.em,{children:"Typically"})," in Rust you can use\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/book/ch15-05-interior-mutability.html",children:"interior mutability"})," to modify\nthings that aren't declared ",(0,i.jsx)(n.code,{children:"mut"}),".\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/std/cell/struct.RefCell.html",children:(0,i.jsx)(n.code,{children:"RefCell"})})," provides an example of this\npattern in action:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'use std::cell::RefCell;\n\nfn my_mutator(cell: &RefCell<u8>) {\n // Even though we\'re given an immutable reference,\n // the `replace` method allows us to modify the inner value.\n cell.replace(14);\n}\n\nfn main() {\n let cell = RefCell::new(25);\n // Prints out 25\n println!("Cell: {:?}", cell);\n my_mutator(&cell);\n // Prints out 14\n println!("Cell: {:?}", cell);\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8e4bea1a718edaff4507944e825a54b2",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["When ",(0,i.jsx)(n.code,{children:"const"})," is involved though, interior mutability is impossible:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'use std::cell::RefCell;\n\nconst CELL: RefCell<u8> = RefCell::new(25);\n\nfn my_mutator(cell: &RefCell<u8>) {\n cell.replace(14);\n}\n\nfn main() {\n // First line prints 25 as expected\n println!("Cell: {:?}", &CELL);\n my_mutator(&CELL);\n // Second line *still* prints 25\n println!("Cell: {:?}", &CELL);\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88fe98110c33c1b3a51e341f48b8ae00",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["And a second example using ",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/std/sync/struct.Once.html",children:(0,i.jsx)(n.code,{children:"Once"})}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'use std::sync::Once;\n\nconst SURPRISE: Once = Once::new();\n\nfn main() {\n // This is how `Once` is supposed to be used\n SURPRISE.call_once(|| println!("Initializing..."));\n // Because `Once` is a `const` value, we never record it\n // having been initialized the first time, and this closure\n // will also execute.\n SURPRISE.call_once(|| println!("Initializing again???"));\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c3cc5979b5e5434eca0f9ec4a06ee0ed",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["When the\n",(0,i.jsxs)(n.a,{href:"https://github.com/rust-lang/rfcs/blob/26197104b7bb9a5a35db243d639aee6e46d35d75/text/0246-const-vs-static.md",children:[(0,i.jsx)(n.code,{children:"const"})," specification"]}),"\nrefers to ",(0,i.jsx)(n.a,{href:"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf",children:'"rvalues"'}),", this\nbehavior is what they refer to. ",(0,i.jsx)(n.a,{href:"https://github.com/rust-lang/rust-clippy",children:"Clippy"})," will treat this\nas an error, but it's still something to be aware of."]}),"\n",(0,i.jsx)(n.h3,{id:"initialization",children:"Initialization"}),"\n",(0,i.jsxs)(n.p,{children:["The next thing to mention is that ",(0,i.jsx)(n.code,{children:"const"})," values are loaded into memory ",(0,i.jsx)(n.em,{children:"as part of your program\nbinary"}),". Because of this, any ",(0,i.jsx)(n.code,{children:"const"}),' values declared in your program will be "realized" at\ncompile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may\nbe able to prefetch the value), but that\'s it.']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"use std::cell::RefCell;\n\nconst CELL: RefCell<u32> = RefCell::new(24);\n\npub fn multiply(value: u32) -> u32 {\n // CELL is stored at `.L__unnamed_1`\n value * (*CELL.get_mut())\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["-- ",(0,i.jsx)(n.a,{href:"https://godbolt.org/z/Th8boO",children:"Compiler Explorer"})]}),"\n",(0,i.jsxs)(n.p,{children:["The compiler creates one ",(0,i.jsx)(n.code,{children:"RefCell"}),", uses it everywhere, and never needs to call the ",(0,i.jsx)(n.code,{children:"RefCell::new"}),"\nfunction."]}),"\n",(0,i.jsx)(n.h3,{id:"copying",children:"Copying"}),"\n",(0,i.jsxs)(n.p,{children:["If it's helpful though, the compiler can choose to copy ",(0,i.jsx)(n.code,{children:"const"})," values."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"const FACTOR: u32 = 1000;\n\npub fn multiply(value: u32) -> u32 {\n // See assembly line 4 for the `mov edi, 1000` instruction\n value * FACTOR\n}\n\npub fn multiply_twice(value: u32) -> u32 {\n // See assembly lines 22 and 29 for `mov edi, 1000` instructions\n value * FACTOR * FACTOR\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["-- ",(0,i.jsx)(n.a,{href:"https://godbolt.org/z/ZtS54X",children:"Compiler Explorer"})]}),"\n",(0,i.jsxs)(n.p,{children:["In this example, the ",(0,i.jsx)(n.code,{children:"FACTOR"})," value is turned into the ",(0,i.jsx)(n.code,{children:"mov edi, 1000"})," instruction in both the\n",(0,i.jsx)(n.code,{children:"multiply"})," and ",(0,i.jsx)(n.code,{children:"multiply_twice"}),' functions; the "1000" value is never "stored" anywhere, as it\'s\nsmall enough to inline into the assembly instructions.']}),"\n",(0,i.jsxs)(n.p,{children:["Finally, getting the address of a ",(0,i.jsx)(n.code,{children:"const"})," value is possible, but not guaranteed to be unique\n(because the compiler can choose to copy values). I was unable to get non-unique pointers in my\ntesting (even using different crates), but the specifications are clear enough: ",(0,i.jsxs)(n.em,{children:["don't rely on\npointers to ",(0,i.jsx)(n.code,{children:"const"})," values being consistent"]}),". To be frank, caring about locations for ",(0,i.jsx)(n.code,{children:"const"})," values\nis almost certainly a code smell."]}),"\n",(0,i.jsxs)(n.h2,{id:"static-values",children:[(0,i.jsx)(n.code,{children:"static"})," values"]}),"\n",(0,i.jsxs)(n.p,{children:["Static variables are related to ",(0,i.jsx)(n.code,{children:"const"})," variables, but take a slightly different approach. When we\ndeclare that a ",(0,i.jsx)(n.em,{children:"reference"})," is unique for the life of a program, you have a ",(0,i.jsx)(n.code,{children:"static"})," variable\n(unrelated to the ",(0,i.jsx)(n.code,{children:"'static"})," lifetime). Because of the reference/value distinction with\n",(0,i.jsx)(n.code,{children:"const"}),"/",(0,i.jsx)(n.code,{children:"static"}),', static variables behave much more like typical "global" variables.']}),"\n",(0,i.jsxs)(n.p,{children:["But to understand ",(0,i.jsx)(n.code,{children:"static"}),", here's what we'll look at:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"static"})," variables are globally unique locations in memory."]}),"\n",(0,i.jsxs)(n.li,{children:["Like ",(0,i.jsx)(n.code,{children:"const"}),", ",(0,i.jsx)(n.code,{children:"static"})," variables are loaded at the same time as your program being read into\nmemory."]}),"\n",(0,i.jsxs)(n.li,{children:["All ",(0,i.jsx)(n.code,{children:"static"})," variables must implement the\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Sync.html",children:(0,i.jsx)(n.code,{children:"Sync"})})," marker trait."]}),"\n",(0,i.jsxs)(n.li,{children:["Interior mutability is safe and acceptable when using ",(0,i.jsx)(n.code,{children:"static"})," variables."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"memory-uniqueness",children:"Memory Uniqueness"}),"\n",(0,i.jsxs)(n.p,{children:["The single biggest difference between ",(0,i.jsx)(n.code,{children:"const"})," and ",(0,i.jsx)(n.code,{children:"static"})," is the guarantees provided about\nuniqueness. Where ",(0,i.jsx)(n.code,{children:"const"})," variables may or may not be copied in code, ",(0,i.jsx)(n.code,{children:"static"})," variables are\nguarantee to be unique. If we take a previous ",(0,i.jsx)(n.code,{children:"const"})," example and change it to ",(0,i.jsx)(n.code,{children:"static"}),", the\ndifference should be clear:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"static FACTOR: u32 = 1000;\n\npub fn multiply(value: u32) -> u32 {\n // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used\n value * FACTOR\n}\n\npub fn multiply_twice(value: u32) -> u32 {\n // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used\n value * FACTOR * FACTOR\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["-- ",(0,i.jsx)(n.a,{href:"https://godbolt.org/z/uxmiRQ",children:"Compiler Explorer"})]}),"\n",(0,i.jsxs)(n.p,{children:["Where ",(0,i.jsx)(n.a,{href:"#copying",children:"previously"})," there were plenty of references to multiplying by 1000, the new\nassembly refers to ",(0,i.jsx)(n.code,{children:"FACTOR"})," as a named memory location instead. No initialization work needs to be\ndone, but the compiler can no longer prove the value never changes during execution."]}),"\n",(0,i.jsx)(n.h3,{id:"initialization-1",children:"Initialization"}),"\n",(0,i.jsx)(n.p,{children:"Next, let's talk about initialization. The simplest case is initializing static variables with\neither scalar or struct notation:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'#[derive(Debug)]\nstruct MyStruct {\n x: u32\n}\n\nstatic MY_STRUCT: MyStruct = MyStruct {\n // You can even reference other statics\n // declared later\n x: MY_VAL\n};\n\nstatic MY_VAL: u32 = 24;\n\nfn main() {\n println!("Static MyStruct: {:?}", MY_STRUCT);\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b538dbc46076f12db047af4f4403ee6e",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["Things can get a bit weirder when using ",(0,i.jsx)(n.code,{children:"const fn"})," though. In most cases, it just works:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'#[derive(Debug)]\nstruct MyStruct {\n x: u32\n}\n\nimpl MyStruct {\n const fn new() -> MyStruct {\n MyStruct { x: 24 }\n }\n}\n\nstatic MY_STRUCT: MyStruct = MyStruct::new();\n\nfn main() {\n println!("const fn Static MyStruct: {:?}", MY_STRUCT);\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8c796a6e7fc273c12115091b707b0255",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["However, there's a caveat: you're currently not allowed to use ",(0,i.jsx)(n.code,{children:"const fn"})," to initialize static\nvariables of types that aren't marked ",(0,i.jsx)(n.code,{children:"Sync"}),". For example,\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.new",children:(0,i.jsx)(n.code,{children:"RefCell::new()"})})," is a\n",(0,i.jsx)(n.code,{children:"const fn"}),", but because\n",(0,i.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/cell/struct.RefCell.html#impl-Sync",children:[(0,i.jsx)(n.code,{children:"RefCell"})," isn't ",(0,i.jsx)(n.code,{children:"Sync"})]}),", you'll\nget an error at compile time:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"use std::cell::RefCell;\n\n// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely\nstatic MY_LOCK: RefCell<u8> = RefCell::new(0);\n"})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c76ef86e473d07117a1700e21fd45560",children:"Rust Playground"})]}),"\n",(0,i.jsxs)(n.p,{children:["It's likely that this will\n",(0,i.jsx)(n.a,{href:"https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md",children:"change in the future"})," though."]}),"\n",(0,i.jsxs)(n.h3,{id:"the-sync-marker",children:["The ",(0,i.jsx)(n.code,{children:"Sync"})," marker"]}),"\n",(0,i.jsxs)(n.p,{children:["Which leads well to the next point: static variable types must implement the\n",(0,i.jsxs)(n.a,{href:"https://doc.rust-lang.org/std/marker/trait.Sync.html",children:[(0,i.jsx)(n.code,{children:"Sync"})," marker"]}),". Because they're globally\nunique, it must be safe for you to access static variables from any thread at any time. Most\n",(0,i.jsx)(n.code,{children:"struct"})," definitions automatically implement the ",(0,i.jsx)(n.code,{children:"Sync"})," trait because they contain only elements\nwhich themselves implement ",(0,i.jsx)(n.code,{children:"Sync"})," (read more in the\n",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/nomicon/send-and-sync.html",children:"Nomicon"}),"). This is why earlier examples could\nget away with initializing statics, even though we never included an ",(0,i.jsx)(n.code,{children:"impl Sync for MyStruct"})," in the\ncode. To demonstrate this property, Rust refuses to compile our earlier example if we add a\nnon-",(0,i.jsx)(n.code,{children:"Sync"})," element to the ",(0,i.jsx)(n.code,{children:"struct"})," definition:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"use std::cell::RefCell;\n\nstruct MyStruct {\n x: u32,\n y: RefCell<u8>,\n}\n\n// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely\nstatic MY_STRUCT: MyStruct = MyStruct {\n x: 8,\n y: RefCell::new(8)\n};\n"})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=40074d0248f056c296b662dbbff97cfc",children:"Rust Playground"})]}),"\n",(0,i.jsx)(n.h3,{id:"interior-mutability",children:"Interior mutability"}),"\n",(0,i.jsxs)(n.p,{children:["Finally, while ",(0,i.jsx)(n.code,{children:"static mut"})," variables are allowed, mutating them is an ",(0,i.jsx)(n.code,{children:"unsafe"})," operation. If we\nwant to stay in ",(0,i.jsx)(n.code,{children:"safe"})," Rust, we can use interior mutability to accomplish similar goals:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'use std::sync::Once;\n\n// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once\nstatic INIT: Once = Once::new();\n\nfn main() {\n // Note that while `INIT` is declared immutable, we\'re still allowed\n // to mutate its interior\n INIT.call_once(|| println!("Initializing..."));\n // This code won\'t panic, as the interior of INIT was modified\n // as part of the previous `call_once`\n INIT.call_once(|| panic!("INIT was called twice!"));\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["--\n",(0,i.jsx)(n.a,{href:"https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3ba003a981a7ed7400240caadd384d59",children:"Rust Playground"})]})]})}function h(e={}){let{wrapper:n}={...(0,l.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},65:function(e,n,t){t.d(n,{Z:function(){return a},a:function(){return r}});var s=t(7294);let i={},l=s.createContext(i);function r(e){let n=s.useContext(l);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(l.Provider,{value:n},e.children)}},1495:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/the-whole-world","source":"@site/blog/2019-02-05-the-whole-world/index.mdx","title":"Allocations in Rust: Global memory","description":"The first memory type we\'ll look at is pretty special: when Rust can prove that a value is fixed","date":"2019-02-05T12:00:00.000Z","tags":[],"readingTime":7.485,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/the-whole-world","title":"Allocations in Rust: Global memory","date":"2019-02-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"},"nextItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"}}')}}]); \ No newline at end of file diff --git a/assets/js/89fbf712.0cbe55d4.js b/assets/js/89fbf712.0cbe55d4.js new file mode 100644 index 0000000..3a10af7 --- /dev/null +++ b/assets/js/89fbf712.0cbe55d4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4794"],{3775:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return u},default:function(){return p},frontMatter:function(){return i},metadata:function(){return a},toc:function(){return c}});var a=n(8279),o=n(5893),r=n(65);let i={slug:"2015/11/autocallable",title:"Autocallable Bonds",date:new Date("2015-11-27T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,l={authorsImageUrls:[void 0]},c=[];function s(e){let t={p:"p",...(0,r.a)(),...e.components};return(0,o.jsx)(t.p,{children:"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products."})}function p(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(s,{...e})}):s(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return i}});var a=n(7294);let o={},r=a.createContext(o);function i(e){let t=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),a.createElement(r.Provider,{value:t},e.children)}},8279:function(e){e.exports=JSON.parse('{"permalink":"/2015/11/autocallable","source":"@site/blog/2015-11-27-autocallable/index.mdx","title":"Autocallable Bonds","description":"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.","date":"2015-11-27T12:00:00.000Z","tags":[],"readingTime":11.085,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/autocallable","title":"Autocallable Bonds","date":"2015-11-27T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"},"nextItem":{"title":"Welcome, and an algorithm","permalink":"/2015/11/welcome"}}')}}]); \ No newline at end of file diff --git a/assets/js/8fedb115.e520b846.js b/assets/js/8fedb115.e520b846.js new file mode 100644 index 0000000..c9eaff0 --- /dev/null +++ b/assets/js/8fedb115.e520b846.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4593"],{5959:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return r},default:function(){return p},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return u}});var o=n(9395),i=n(5893),s=n(65);let a={title:"Allocations in Rust: Compiler optimizations",description:"A lot. The answer is a lot.",date:new Date("2019-02-08T12:00:00.000Z"),last_updated:{date:new Date("2019-02-10T12:00:00.000Z")},tags:[]},r=void 0,l={authorsImageUrls:[]},u=[];function c(e){let t={p:"p",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Up to this point, we've been discussing memory usage in the Rust language by focusing on simple\nrules that are mostly right for small chunks of code. We've spent time showing how those rules work\nthemselves out in practice, and become familiar with reading the assembly code needed to see each\nmemory type (global, stack, heap) in action."}),"\n",(0,i.jsx)(t.p,{children:"Throughout the series so far, we've put a handicap on the code. In the name of consistent and\nunderstandable results, we've asked the compiler to pretty please leave the training wheels on. Now\nis the time where we throw out all the rules and take off the kid gloves. As it turns out, both the\nRust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them\ndo their job."})]})}function p(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return a}});var o=n(7294);let i={},s=o.createContext(i);function a(e){let t=o.useContext(s);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}},9395:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/08/compiler-optimizations","source":"@site/blog/2019-02-08-compiler-optimizations/index.mdx","title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","tags":[],"readingTime":3.695,"hasTruncateMarker":true,"authors":[],"frontMatter":{"title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","last_updated":{"date":"2019-02-10T12:00:00.000Z"},"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"},"nextItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"}}')}}]); \ No newline at end of file diff --git a/assets/js/92079dc1.4088067f.js b/assets/js/92079dc1.4088067f.js new file mode 100644 index 0000000..871d742 --- /dev/null +++ b/assets/js/92079dc1.4088067f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9366"],{3244:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return i},default:function(){return d},frontMatter:function(){return s},metadata:function(){return a},toc:function(){return c}});var a=n(7133),r=n(5893),o=n(65);let s={slug:"2016/01/complaining-about-the-weather",title:"Complaining about the weather",date:new Date("2016-01-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},i="Tracking Precipitation Chances",l={authorsImageUrls:[void 0]},c=[];function h(e){let t={a:"a",code:"code",h1:"h1",img:"img",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"Figuring out whether people should be complaining about the recent weather in North Carolina."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"from bokeh.plotting import figure, output_notebook, show\nfrom bokeh.palettes import PuBuGn9 as Palette\nimport pandas as pd\nimport numpy as np\nfrom datetime import datetime\nimport pickle\n\noutput_notebook()\n"})}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"BokehJS successfully loaded.\n"})}),"\n",(0,r.jsx)(t.p,{children:"I'm originally from North Carolina, and I've been hearing a lot of people talking about how often it's been raining recently. They're excited for any day that has sun."}),"\n",(0,r.jsx)(t.p,{children:"So I got a bit curious: Has North Carolina over the past few months actually had more cloudy and rainy days recently than in previous years? This shouldn't be a particularly challenging task, but I'm interested to know if people's perceptions actually reflect reality."}),"\n",(0,r.jsxs)(t.p,{children:["The data we'll use comes from ",(0,r.jsx)(t.a,{href:"https://forecast.io",children:"forecast.io"}),", since they can give us a cloud cover percentage. I've gone ahead and retrieved the data to a pickle file, and included the ",(0,r.jsx)(t.a,{href:"#Generating-the-Forecast-file",children:"code that was used to generate it"}),'. First up: What was the average cloud cover in North Carolina during August - November, and how many days were cloudy? We\'re going to assume that a "cloudy" day is defined as any day in which the cloud cover is above 50%.']}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"city_forecasts = pickle.load(open('city_forecasts.p', 'rb'))\nforecast_df = pd.DataFrame.from_dict(city_forecasts)\n"})}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"cary_forecast = forecast_df['cary']\nyears = range(1990, 2016)\nmonths = range(7, 12)\nmonths_str = ['July', 'August', 'September', 'October', 'November']\n\ndef safe_cover(frame):\n if frame and 'cloudCover' in frame:\n return frame['cloudCover']\n else:\n return np.NaN\n\ndef monthly_avg_cloudcover(year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates))\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\n return np.nanmean(cloud_cover_vals), cloud_cover_samples\n\n\nmonthly_cover_vals = [[monthly_avg_cloudcover(y, m)[0] for y in years] for m in months]\n\nf = figure(title='Monthly Average Cloud Cover',\n x_range=(1990, 2015),\n x_axis_label='Year')\nfor x in range(0, len(months)):\n f.line(years, monthly_cover_vals[x], legend=months_str[x], color=Palette[x])\nshow(f)\n"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly average cloud cover chart",src:n(3754).Z+"",width:"600",height:"600"})}),"\n",(0,r.jsx)(t.p,{children:"As we can see from the chart above, on the whole the monthly average cloud cover has been generally trending down over time. The average cloud cover is also lower than it was last year - it seems people are mostly just complaining. There are some data issues that start in 2012 that we need to be aware of - the cloud cover percentage doesn't exist for all days. Even so, the data that we have seems to reflect the wider trend, so we'll assume for now that the missing data doesn't skew our results."}),"\n",(0,r.jsx)(t.p,{children:"There's one more metric we want to check though - how many cloudy days were there? This is probably a better gauge of sentiment than the average monthly cover."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"def monthly_cloudy_days(year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates))\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\n cloudy_days = [cover > .5 for cover in cloud_cover_vals]\n return np.count_nonzero(cloudy_days), cloud_cover_samples\n\nmonthly_days_vals = [[monthly_cloudy_days(y, m)[0] for y in years] for m in months]\nmonthly_cover_samples = [[monthly_cloudy_days(y, m)[1] for y in years] for m in months]\n\nf = figure(title='Monthly Cloudy Days',\n x_range=(1990, 2015),\n x_axis_label='Year')\nfor x in range(0, len(months)):\n f.line(years, monthly_days_vals[x], legend=months_str[x], color=Palette[x])\nshow(f)\n\nf = figure(title='Monthly Cloud Cover Samples',\n x_range=(1990, 2015),\n x_axis_label='Year',\n height=300)\nfor x in range(0, len(months)):\n f.line(years, monthly_cover_samples[x], legend=months_str[x], color=Palette[x])\nshow(f)\n"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly cloudy days chart",src:n(8469).Z+"",width:"600",height:"600"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly cloud cover samples chart",src:n(3918).Z+"",width:"600",height:"300"})}),"\n",(0,r.jsx)(t.p,{children:"On the whole, the number of cloudy days seems to reflect the trend with average cloud cover - it's actually becoming more sunny as time progresses. That said, we need to be careful in how we view this number - because there weren't as many samples in 2015 as previous years, the number of days can get thrown off. In context though, even if most days not recorded were in fact cloudy, the overall count for 2015 would still be lower than previous years."}),"\n",(0,r.jsx)(t.p,{children:"In addition to checking cloud cover, I wanted to check precipitation data as well - what is the average precipitation chance over a month, and how many days during a month is rain likely? The thinking is that days with a high-precipitation chance will also be days in which it is cloudy or depressing."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"def safe_precip(frame):\n if frame and 'precipProbability' in frame:\n return frame['precipProbability']\n else:\n return np.NaN\n\ndef monthly_avg_precip(year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n precip_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates))\n precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))\n return np.nanmean(precip_vals), precip_samples\n\nmonthly_avg_precip_vals = [[monthly_avg_precip(y, m)[0] for y in years] for m in months]\n\nf = figure(title='Monthly Average Precipitation Chance',\n x_range=(1990, 2015),\n x_axis_label='Year')\nfor x in range(0, len(months)):\n f.line(years, monthly_avg_precip_vals[x], legend=months_str[x], color=Palette[x])\nshow(f)\n"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly average precipitation chance chart",src:n(6814).Z+"",width:"600",height:"600"})}),"\n",(0,r.jsx)(t.p,{children:'As we can see from the chart, the average chance of precipitation over a month more or less stays within a band of 0 - .1 for all months over all years. This is further evidence that the past few months are no more cloudy or rainy than previous years. Like the cloud cover though, we still want to get a count of all the rainy days, in addition to the average chance. We\'ll define a "rainy day" as any day in which the chance of rain is greater than 25%.'}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"def monthly_rainy_days(year, month):\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\n end=datetime(year, month + 1, 1, 12),\n freq='D', closed='left')\n precip_prob_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates))\n precip_prob_samples = len(list(filter(lambda x: x is not np.NaN, precip_prob_vals)))\n precip_days = [prob > .25 for prob in precip_prob_vals]\n return np.count_nonzero(precip_days), precip_prob_samples\n\nmonthly_precip_days_vals = [[monthly_rainy_days(y, m)[0] for y in years] for m in months]\nmonthly_precip_samples = [[monthly_rainy_days(y, m)[1] for y in years] for m in months]\n\nf = figure(title='Monthly Rainy Days',\n x_range=(1990, 2015),\n x_axis_label='Year')\nfor x in range(0, len(months)):\n f.line(years, monthly_precip_days_vals[x], legend=months_str[x], color=Palette[x])\nshow(f)\n\nf = figure(title='Monthly Rainy Days Samples',\n x_range=(1990, 2015),\n x_axis_label='Year',\n height=300)\nfor x in range(0, len(months)):\n f.line(years, monthly_precip_samples[x], legend=months_str[x], color=Palette[x])\nshow(f)\n"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly rainy days chart",src:n(3118).Z+"",width:"600",height:"600"})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Monthly rainy days samples chart",src:n(966).Z+"",width:"600",height:"300"})}),"\n",(0,r.jsx)(t.p,{children:"After trying to find the number of days that are rainy, we can see that November hit its max value for rainy days in 2015. However, that value is 6, as compared to a previous maximum of 5. While it is a new record, the value isn't actually all that different. And for other months, the values are mostly in-line with the averages."}),"\n",(0,r.jsx)(t.h1,{id:"summary-and-conclusions",children:"Summary and Conclusions"}),"\n",(0,r.jsx)(t.p,{children:"After having looked at forecast data for Cary, it appears that the months of July - November this year in terms of weather were at worst on par with prior years, if not slightly more sunny. This seems to be a case of confirmation bias: someone complains about a string of cloudy or rainy days, and suddenly you start noticing them more."}),"\n",(0,r.jsx)(t.p,{children:"While this analysis doesn't take into account other areas of North Carolina, my initial guess would be to assume that other areas also will show similar results: nothing interesting is happening. Maybe that will be for another blog post later!"}),"\n",(0,r.jsx)(t.p,{children:"Coming soon: I'll compare rain/cloud conditions in North Carolina to some other places in the U.S.!"}),"\n",(0,r.jsx)(t.h1,{id:"generating-the-forecast-file",children:"Generating the Forecast file"}),"\n",(0,r.jsx)(t.p,{children:"The following code was generates the file that was used throughout the blog post. Please note that I'm retrieving data for other cities to use in a future blog post, only Cary data was used for this post."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"import pandas as pd\nfrom functools import reduce\nimport requests\nfrom datetime import datetime\n\n# Coordinate data from http://itouchmap.com/latlong.html\ncary_loc = (35.79154,-78.781117)\nnyc_loc = (40.78306,-73.971249)\nseattle_loc = (47.60621,-122.332071)\nbinghamton_loc = (42.098687,-75.917974)\ncities = {\n 'cary': cary_loc,\n 'nyc': nyc_loc,\n 'seattle': seattle_loc,\n 'binghamton': binghamton_loc\n}\n\napikey = '' # My super-secret API Key\n\ndef get_forecast(lat, long, date=None):\n forecast_base = \"https://api.forecast.io/forecast/\"\n if date is None:\n url = forecast_base + apikey + '/{},{}'.format(lat, long)\n else:\n epoch = int(date.timestamp())\n url = forecast_base + apikey + '/{},{},{}'.format(lat, long, epoch)\n \n return requests.get(url).json()\n \nyears = range(1990,2016)\n# For datetimes, the 12 is for getting the weather at noon.\n# We're doing this over midnight because we're more concerned\n# with what people see, and people don't typically see the weather\n# at midnight.\ndt_indices = [pd.date_range(start=datetime(year, 7, 1, 12),\n end=datetime(year, 11, 30, 12))\n for year in years]\ndt_merge = reduce(lambda x, y: x.union(y), dt_indices)\n\n# Because we have to pay a little bit to use the API, we use for loops here\n# instead of a comprehension - if something breaks, we want to preserve the\n# data already retrieved\ncity_forecasts = {}\nfor city, loc in cities.items():\n print(\"Retrieving data for {} starting at {}\".format(city,\n datetime.now().strftime(\"%I:%M:%S %p\")))\n for dt in dt_merge:\n try:\n city_forecasts[(city, dt)] = get_forecast(*loc, dt)\n except Exception as e:\n print(e)\n city_forecasts[(city, dt)] = None\nprint(\"End forecast retrieval: {}\".format(datetime.now().strftime(\"%I:%M:%S %p\")))\n\nimport pickle\npickle.dump(city_forecasts, open('city_forecasts.p', 'wb'))\n\n### Output:\n# Retrieving data for binghamton starting at 05:13:42 PM\n# Retrieving data for seattle starting at 05:30:51 PM\n# Retrieving data for nyc starting at 05:48:30 PM\n# Retrieving data for cary starting at 06:08:32 PM\n# End forecast retrieval: 06:25:21 PM\n"})})]})}function d(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},3754:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/1-0d5e8450555296218deb0517b80440f3.png"},8469:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/2-062e1e47a07f200ff3b1531a02812bc7.png"},3918:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/3-eea635f8cfe4a12ae649ceb6c984e0cd.png"},6814:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/4-b4c3dbfa10b1997706bc271ca71e2ff5.png"},3118:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/5-8f10acd82b2f025abe57cb93d435a25f.png"},966:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/6-456ca1125f48947cf3c1c13722af95a0.png"},65:function(e,t,n){n.d(t,{Z:function(){return i},a:function(){return s}});var a=n(7294);let r={},o=a.createContext(r);function s(e){let t=a.useContext(o);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:t},e.children)}},7133:function(e){e.exports=JSON.parse('{"permalink":"/2016/01/complaining-about-the-weather","source":"@site/blog/2016-01-01-complaining-about-the-weather/index.mdx","title":"Complaining about the weather","description":"Figuring out whether people should be complaining about the recent weather in North Carolina.","date":"2016-01-01T12:00:00.000Z","tags":[],"readingTime":7.475,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/complaining-about-the-weather","title":"Complaining about the weather","date":"2016-01-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"},"nextItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"}}')}}]); \ No newline at end of file diff --git a/assets/js/94d32f6c.bca1abd5.js b/assets/js/94d32f6c.bca1abd5.js new file mode 100644 index 0000000..b696b83 --- /dev/null +++ b/assets/js/94d32f6c.bca1abd5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7580"],{4935:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return a},default:function(){return d},frontMatter:function(){return i},metadata:function(){return s},toc:function(){return c}});var s=n(6583),o=n(5893),r=n(65);let i={slug:"2019/02/understanding-allocations-in-rust",title:"Allocations in Rust: Foreword",date:new Date("2019-02-04T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,l={authorsImageUrls:[void 0]},c=[];function h(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",hr:"hr",li:"li",ol:"ol",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["There's an alchemy of distilling complex technical topics into articles and videos that change the\nway programmers see the tools they interact with on a regular basis. I knew what a linker was, but\nthere's a staggering amount of complexity in between\n",(0,o.jsxs)(t.a,{href:"https://www.youtube.com/watch?v=dOfucXtyEsU",children:["the OS and ",(0,o.jsx)(t.code,{children:"main()"})]}),". Rust programmers use the\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/stable/std/boxed/struct.Box.html",children:(0,o.jsx)(t.code,{children:"Box"})})," type all the time, but there's a\nrich history of the Rust language itself wrapped up in\n",(0,o.jsx)(t.a,{href:"https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/",children:"how special it is"}),"."]}),"\n",(0,o.jsx)(t.p,{children:"In a similar vein, this series attempts to look at code and understand how memory is used; the\ncomplex choreography of operating system, compiler, and program that frees you to focus on\nfunctionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the\ncognitive burden associated with memory management, but we're going to step into its world for a\nwhile."}),"\n",(0,o.jsx)(t.p,{children:"Let's learn a bit about memory in Rust."}),"\n",(0,o.jsx)(t.hr,{}),"\n",(0,o.jsxs)(t.p,{children:["Rust's three defining features of\n",(0,o.jsx)(t.a,{href:"https://www.rust-lang.org/",children:"Performance, Reliability, and Productivity"})," are all driven to a great\ndegree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java,\nPython), Rust\n",(0,o.jsx)(t.a,{href:"https://words.steveklabnik.com/borrow-checking-escape-analysis-and-the-generational-hypothesis",children:"doesn't really"}),"\ngarbage collect; instead, it uses an\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html",children:"ownership"}),' system to reason about\nhow long objects will last in your program. In some cases, if the life of an object is fairly\ntransient, Rust can make use of a very fast region called the "stack." When that\'s not possible,\nRust uses\n',(0,o.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Memory_management#Dynamic_memory_allocation",children:"dynamic (heap) memory"}),"\nand the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it\nis important to have available."]}),"\n",(0,o.jsx)(t.p,{children:"That said, there are specific situations in Rust where you'd never need to worry about the\nstack/heap distinction! If you:"}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsxs)(t.li,{children:["Never use ",(0,o.jsx)(t.code,{children:"unsafe"})]}),"\n",(0,o.jsxs)(t.li,{children:["Never use ",(0,o.jsx)(t.code,{children:"#![feature(alloc)]"})," or the ",(0,o.jsxs)(t.a,{href:"https://doc.rust-lang.org/alloc/index.html",children:[(0,o.jsx)(t.code,{children:"alloc"})," crate"]})]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"...then it's not possible for you to use dynamic memory!"}),"\n",(0,o.jsxs)(t.p,{children:["For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited\nmemory, and the program binary size itself may significantly affect what's available! There's no\noperating system able to manage this\n",(0,o.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Virtual_memory",children:'"virtual memory"'})," thing, but that's not an issue\nbecause there's only one running application. The\n",(0,o.jsx)(t.a,{href:"https://docs.rust-embedded.org/embedonomicon/preface.html",children:"embedonomicon"}),' is ever in mind, and\ninteracting with the "real world" through extra peripherals is accomplished by reading and writing\nto ',(0,o.jsx)(t.a,{href:"https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-gpio-mem.html",children:"specific memory addresses"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Most Rust programs find these requirements overly burdensome though. C++ developers would struggle\nwithout access to ",(0,o.jsx)(t.a,{href:"https://en.cppreference.com/w/cpp/container/vector",children:(0,o.jsx)(t.code,{children:"std::vector"})})," (except those\nhardcore no-STL people), and Rust developers would struggle without\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/std/vec/struct.Vec.html",children:(0,o.jsx)(t.code,{children:"std::vec"})}),". But with the constraints above,\n",(0,o.jsx)(t.code,{children:"std::vec"})," is actually a part of the\n",(0,o.jsxs)(t.a,{href:"https://doc.rust-lang.org/alloc/vec/struct.Vec.html",children:[(0,o.jsx)(t.code,{children:"alloc"})," crate"]}),", and thus off-limits. ",(0,o.jsx)(t.code,{children:"Box"}),",\n",(0,o.jsx)(t.code,{children:"Rc"}),", etc., are also unusable for the same reason."]}),"\n",(0,o.jsxs)(t.p,{children:["Whether writing code for embedded devices or not, the important thing in both situations is how much\nyou know ",(0,o.jsx)(t.em,{children:"before your application starts"})," about what its memory usage will look like. In embedded\ndevices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large\n",(0,o.jsx)(t.a,{href:"https://www.google.com",children:"google.com"}),"'s home page is until you start trying to download it. The\ncompiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code\nruns faster when the compiler can guarantee exactly how much memory your program needs while it's\nrunning. This series is all about understanding how the compiler reasons about your program, with an\nemphasis on the implications for performance."]}),"\n",(0,o.jsx)(t.p,{children:"Now let's address some conditions and caveats before going much further:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:['We\'ll focus on "safe" Rust only; ',(0,o.jsx)(t.code,{children:"unsafe"})," lets you use platform-specific allocation API's\n(",(0,o.jsx)(t.a,{href:"https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm",children:(0,o.jsx)(t.code,{children:"malloc"})}),") that we'll\nignore."]}),"\n",(0,o.jsxs)(t.li,{children:['We\'ll assume a "debug" build of Rust code (what you get with ',(0,o.jsx)(t.code,{children:"cargo run"})," and ",(0,o.jsx)(t.code,{children:"cargo test"}),") and\naddress (pun intended) release mode at the end (",(0,o.jsx)(t.code,{children:"cargo run --release"})," and ",(0,o.jsx)(t.code,{children:"cargo test --release"}),")."]}),"\n",(0,o.jsxs)(t.li,{children:["All content will be run using Rust 1.32, as that's the highest currently supported in the\n",(0,o.jsx)(t.a,{href:"https://godbolt.org/",children:"Compiler Exporer"}),". As such, we'll avoid upcoming innovations like\n",(0,o.jsxs)(t.a,{href:"https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md",children:["compile-time evaluation of ",(0,o.jsx)(t.code,{children:"static"})]}),"\nthat are available in nightly."]}),"\n",(0,o.jsxs)(t.li,{children:["Because of the nature of the content, being able to read assembly is helpful. We'll keep it\nsimple, but I ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/a/4584131/1454178",children:"found"})," a\n",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/a/26026278/1454178",children:"refresher"})," on the ",(0,o.jsx)(t.code,{children:"push"})," and ",(0,o.jsx)(t.code,{children:"pop"}),"\n",(0,o.jsx)(t.a,{href:"http://www.cs.virginia.edu/~evans/cs216/guides/x86.html",children:"instructions"})," was helpful while writing\nthis."]}),"\n",(0,o.jsxs)(t.li,{children:["I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are\navailable, but if there's something said in error it will be corrected expeditiously. Please let\nme know at ",(0,o.jsx)(t.a,{href:"mailto:bradlee@speice.io",children:"bradlee@speice.io"})]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth\nrepeating:"}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsx)(t.p,{children:"Rust does not currently have a rigorously and formally defined memory model."}),"\n",(0,o.jsxs)(t.p,{children:["-- ",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/std/ptr/fn.read_volatile.html",children:"the docs"})]}),"\n"]})]})}function d(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return i}});var s=n(7294);let o={},r=s.createContext(o);function i(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(r.Provider,{value:t},e.children)}},6583:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/understanding-allocations-in-rust","source":"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx","title":"Allocations in Rust: Foreword","description":"There\'s an alchemy of distilling complex technical topics into articles and videos that change the","date":"2019-02-04T12:00:00.000Z","tags":[],"readingTime":3.785,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/understanding-allocations-in-rust","title":"Allocations in Rust: Foreword","date":"2019-02-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"},"nextItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"}}')}}]); \ No newline at end of file diff --git a/assets/js/9555.2cb431fa.js b/assets/js/9555.2cb431fa.js new file mode 100644 index 0000000..928d36c --- /dev/null +++ b/assets/js/9555.2cb431fa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9555"],{3549:function(e,t,n){n.r(t),n.d(t,{default:()=>I});var r=n("5893"),i=n("7294"),l=n("7026"),s=n("2743"),a=n("4681"),o=n("4183"),c=n("979"),d=n("2553"),u=n("8127");function m(){let{assets:e,metadata:t}=(0,o.nO)(),{title:n,description:i,date:l,tags:a,authors:c,frontMatter:d}=t,{keywords:u}=d,m=e.image??d.image;return(0,r.jsxs)(s.d,{title:d.title_meta??n,description:i,keywords:u,image:m,children:[(0,r.jsx)("meta",{property:"og:type",content:"article"}),(0,r.jsx)("meta",{property:"article:published_time",content:l}),c.some(e=>e.url)&&(0,r.jsx)("meta",{property:"article:author",content:c.map(e=>e.url).filter(Boolean).join(",")}),a.length>0&&(0,r.jsx)("meta",{property:"article:tag",content:a.map(e=>e.label).join(",")})]})}var f=n("4819");function h(){let e=(0,o.iZ)();return(0,r.jsx)(f.Z,{children:(0,r.jsx)("script",{type:"application/ld+json",children:JSON.stringify(e)})})}var x=n("140");function p(e){let t=e.getBoundingClientRect();return t.top===t.bottom?p(e.parentNode):t}var j=n("3012");let g=i.memo(function e(t){let{toc:n,className:i,linkClassName:l,isChild:s}=t;return n.length?(0,r.jsx)("ul",{className:s?void 0:i,children:n.map(t=>(0,r.jsxs)("li",{children:[(0,r.jsx)(j.Z,{to:`#${t.id}`,className:l??void 0,dangerouslySetInnerHTML:{__html:t.value}}),(0,r.jsx)(e,{isChild:!0,toc:t.children,className:i,linkClassName:l})]},t.id))}):null});function v(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:l="table-of-contents__link",linkActiveClassName:s,minHeadingLevel:a,maxHeadingLevel:o,...c}=e,d=(0,x.L)(),u=a??d.tableOfContents.minHeadingLevel,m=o??d.tableOfContents.maxHeadingLevel,f=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:r}=e;return(0,i.useMemo)(()=>(function e(t){let{toc:n,minHeadingLevel:r,maxHeadingLevel:i}=t;return n.flatMap(t=>{var n;let l=e({toc:t.children,minHeadingLevel:r,maxHeadingLevel:i});return(n=t).level>=r&&n.level<=i?[{...t,children:l}]:l})})({toc:function(e){let t=e.map(e=>({...e,parentIndex:-1,children:[]})),n=Array(7).fill(-1);t.forEach((e,t)=>{let r=n.slice(2,e.level);e.parentIndex=Math.max(...r),n[e.level]=t});let r=[];return t.forEach(e=>{let{parentIndex:n,...i}=e;n>=0?t[n].children.push(i):r.push(i)}),r}(t),minHeadingLevel:n,maxHeadingLevel:r}),[t,n,r])}({toc:t,minHeadingLevel:u,maxHeadingLevel:m});return!function(e){let t=(0,i.useRef)(void 0),n=function(){let e=(0,i.useRef)(0),{navbar:{hideOnScroll:t}}=(0,x.L)();return(0,i.useEffect)(()=>{e.current=t?0:document.querySelector(".navbar").clientHeight},[t]),e}();(0,i.useEffect)(()=>{if(!e)return()=>{};let{linkClassName:r,linkActiveClassName:i,minHeadingLevel:l,maxHeadingLevel:s}=e;function a(){var e;let a=(e=r,Array.from(document.getElementsByClassName(e))),o=function(e,t){let{anchorTopOffset:n}=t,r=e.find(e=>p(e).top>=n);if(r){var i;return(i=p(r)).top>0&&i.bottom<window.innerHeight/2?r:e[e.indexOf(r)-1]??null}return e[e.length-1]??null}(function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e,r=[];for(let e=t;e<=n;e+=1)r.push(`h${e}.anchor`);return Array.from(document.querySelectorAll(r.join()))}({minHeadingLevel:l,maxHeadingLevel:s}),{anchorTopOffset:n.current}),c=a.find(e=>{var t;return o&&o.id===decodeURIComponent((t=e).href.substring(t.href.indexOf("#")+1))});a.forEach(e=>{var n;n=e,e===c?(t.current&&t.current!==n&&t.current.classList.remove(i),n.classList.add(i),t.current=n):n.classList.remove(i)})}return document.addEventListener("scroll",a),document.addEventListener("resize",a),a(),()=>{document.removeEventListener("scroll",a),document.removeEventListener("resize",a)}},[e,n])}((0,i.useMemo)(()=>{if(l&&s)return{linkClassName:l,linkActiveClassName:s,minHeadingLevel:u,maxHeadingLevel:m}},[l,s,u,m])),(0,r.jsx)(g,{toc:f,className:n,linkClassName:l,...c})}let b="tableOfContents_bqdL";function _(e){let{className:t,...n}=e;return(0,r.jsx)("div",{className:(0,l.Z)(b,"thin-scrollbar",t),children:(0,r.jsx)(v,{...n,linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})})}var y=n("6025");function k(){return(0,r.jsx)(y.Z,{id:"theme.contentVisibility.unlistedBanner.title",description:"The unlisted content banner title",children:"Unlisted page"})}function L(){return(0,r.jsx)(y.Z,{id:"theme.contentVisibility.unlistedBanner.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function Z(){return(0,r.jsx)(f.Z,{children:(0,r.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}function N(){return(0,r.jsx)(y.Z,{id:"theme.contentVisibility.draftBanner.title",description:"The draft content banner title",children:"Draft page"})}function C(){return(0,r.jsx)(y.Z,{id:"theme.contentVisibility.draftBanner.message",description:"The draft content banner message",children:"This page is a draft. It will only be visible in dev and be excluded from the production build."})}var B=n("5094");function E(e){let{className:t}=e;return(0,r.jsx)(B.Z,{type:"caution",title:(0,r.jsx)(N,{}),className:(0,l.Z)(t,a.k.common.draftBanner),children:(0,r.jsx)(C,{})})}function w(e){let{className:t}=e;return(0,r.jsx)(B.Z,{type:"caution",title:(0,r.jsx)(k,{}),className:(0,l.Z)(t,a.k.common.unlistedBanner),children:(0,r.jsx)(L,{})})}function H(e){return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(Z,{}),(0,r.jsx)(w,{...e})]})}function O(e){let{metadata:t}=e,{unlisted:n,frontMatter:i}=t;return(0,r.jsxs)(r.Fragment,{children:[(n||i.unlisted)&&(0,r.jsx)(H,{}),i.draft&&(0,r.jsx)(E,{})]})}function T(e){let{sidebar:t,children:n}=e,{metadata:i,toc:l}=(0,o.nO)(),{nextItem:s,prevItem:a,frontMatter:m}=i,{hide_table_of_contents:f,toc_min_heading_level:h,toc_max_heading_level:x}=m;return(0,r.jsxs)(c.Z,{sidebar:t,toc:!f&&l.length>0?(0,r.jsx)(_,{toc:l,minHeadingLevel:h,maxHeadingLevel:x}):void 0,children:[(0,r.jsx)(O,{metadata:i}),(0,r.jsx)(d.Z,{children:n}),(s||a)&&(0,r.jsx)(u.Z,{nextItem:s,prevItem:a})]})}function I(e){let t=e.content;return(0,r.jsx)(o.n4,{content:e.content,isBlogPostPage:!0,children:(0,r.jsxs)(s.FG,{className:(0,l.Z)(a.k.wrapper.blogPages,a.k.page.blogPostPage),children:[(0,r.jsx)(m,{}),(0,r.jsx)(h,{}),(0,r.jsx)(T,{sidebar:e.sidebar,children:(0,r.jsx)(t,{})})]})})}}}]); \ No newline at end of file diff --git a/assets/js/962a4168.a5498250.js b/assets/js/962a4168.a5498250.js new file mode 100644 index 0000000..8bcdacf --- /dev/null +++ b/assets/js/962a4168.a5498250.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["302"],{8674:function(e,n,t){t.r(n),t.d(n,{assets:function(){return l},contentTitle:function(){return o},default:function(){return h},frontMatter:function(){return r},metadata:function(){return s},toc:function(){return c}});var s=t(6749),a=t(5893),i=t(65);let r={slug:"2016/03/predicting-santander-customer-happiness",title:"Predicting Santander customer happiness",date:new Date("2016-03-05T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Data Exploration",id:"data-exploration",level:2},{value:"Dimensionality Reduction pt. 1 - Binary Classifiers",id:"dimensionality-reduction-pt-1---binary-classifiers",level:3},{value:"Dimensionality Reduction pt. 2 - LDA",id:"dimensionality-reduction-pt-2---lda",level:3},{value:"Summary for Day 1",id:"summary-for-day-1",level:2},{value:"Appendix",id:"appendix",level:2}];function d(e){let n={a:"a",annotation:"annotation",code:"code",h2:"h2",h3:"h3",img:"img",li:"li",math:"math",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"My first Kaggle competition."}),"\n",(0,a.jsxs)(n.p,{children:["It's time! After embarking on a Machine Learning class this semester, and with a Saturday in which I don't have much planned, I wanted to put this class and training to work. It's my first competition submission. I want to walk you guys through how I'm approaching this problem, because I thought it would be really neat. The competition is Banco Santander's ",(0,a.jsx)(n.a,{href:"https://www.kaggle.com/c/santander-customer-satisfaction",children:"Santander Customer Satisfaction"})," competition. It seemed like an easy enough problem I could actually make decent progress on it."]}),"\n",(0,a.jsx)(n.h2,{id:"data-exploration",children:"Data Exploration"}),"\n",(0,a.jsxs)(n.p,{children:["First up: we need to load our data and do some exploratory work. Because we're going to be using this data for model selection prior to testing, we need to make a further split. I've already gone ahead and done this work, please see the code in the ",(0,a.jsx)(n.a,{href:"#appendix",children:"appendix below"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\n# Record how long it takes to run the notebook - I'm curious.\nfrom datetime import datetime\nstart = datetime.now()\n\ndataset = pd.read_csv('split_train.csv')\ndataset.index = dataset.ID\nX = dataset.drop(['TARGET', 'ID', 'ID.1'], 1)\ny = dataset.TARGET\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"y.unique()\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:" array([0, 1], dtype=int64)\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"len(X.columns)\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:" 369\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Okay, so there are only ",(0,a.jsx)(n.a,{href:"https://www.kaggle.com/c/santander-customer-satisfaction/data",children:"two classes we're predicting"}),": 1 for unsatisfied customers, 0 for satisfied customers. I would have preferred this to be something more like a regression, or predicting multiple classes: maybe the customer isn't the most happy, but is nowhere near closing their accounts. For now though, that's just the data we're working with."]}),"\n",(0,a.jsx)(n.p,{children:"Now, I'd like to make a scatter matrix of everything going on. Unfortunately as noted above, we have 369 different features. There's no way I can graphically make sense of that much data to start with."}),"\n",(0,a.jsx)(n.p,{children:"We're also not told what the data actually represents: Are these survey results? Average time between contact with a customer care person? Frequency of contacting a customer care person? The idea is that I need to reduce the number of dimensions we're predicting across."}),"\n",(0,a.jsx)(n.h3,{id:"dimensionality-reduction-pt-1---binary-classifiers",children:"Dimensionality Reduction pt. 1 - Binary Classifiers"}),"\n",(0,a.jsx)(n.p,{children:"My first attempt to reduce the data dimensionality is to find all the binary classifiers in the dataset (i.e. 0 or 1 values) and see if any of those are good (or anti-good) predictors of the final data."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"cols = X.columns\nb_class = []\nfor c in cols:\n if len(X[c].unique()) == 2:\n b_class.append(c)\n \nlen(b_class)\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:" 111\n"})}),"\n",(0,a.jsx)(n.p,{children:"So there are 111 features in the dataset that are a binary label. Let's see if any of them are good at predicting the users satisfaction!"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:'# First we need to `binarize` the data to 0-1; some of the labels are {0, 1},\n# some are {0, 3}, etc.\nfrom sklearn.preprocessing import binarize\nX_bin = binarize(X[b_class])\n\naccuracy = [np.mean(X_bin[:,i] == y) for i in range(0, len(b_class))]\nacc_df = pd.DataFrame({"Accuracy": accuracy}, index=b_class)\nacc_df.describe()\n'})}),"\n",(0,a.jsx)("div",{children:(0,a.jsxs)("table",{children:[(0,a.jsx)("thead",{children:(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{}),(0,a.jsx)("th",{children:"Accuracy"})]})}),(0,a.jsxs)("tbody",{children:[(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"count"}),(0,a.jsx)("td",{children:"111.000000"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"mean"}),(0,a.jsx)("td",{children:"0.905159"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"std"}),(0,a.jsx)("td",{children:"0.180602"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"min"}),(0,a.jsx)("td",{children:"0.043598"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"25%"}),(0,a.jsx)("td",{children:"0.937329"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"50%"}),(0,a.jsx)("td",{children:"0.959372"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"75%"}),(0,a.jsx)("td",{children:"0.960837"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"max"}),(0,a.jsx)("td",{children:"0.960837"})]})]})]})}),"\n",(0,a.jsx)(n.p,{children:"Wow! Looks like we've got some incredibly predictive features! So much so that we should be a bit concerned. My initial guess for what's happening is that we have a sparsity issue: so many of the values are 0, and these likely happen to line up with satisfied customers."}),"\n",(0,a.jsx)(n.p,{children:"So the question we must now answer, which I likely should have asked long before now: What exactly is the distribution of un/satisfied customers?"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:'unsat = y[y == 1].count()\nprint("Satisfied customers: {}; Unsatisfied customers: {}".format(len(y) - unsat, unsat))\nnaive_guess = np.mean(y == np.zeros(len(y)))\nprint("Naive guess accuracy: {}".format(naive_guess))\n'})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:" Satisfied customers: 51131; Unsatisfied customers: 2083\n Naive guess accuracy: 0.9608561656706882\n"})}),"\n",(0,a.jsx)(n.p,{children:"This is a bit discouraging. A naive guess of \"always satisfied\" performs as well as our best individual binary classifier. What this tells me then, is that these data columns aren't incredibly helpful in prediction. I'd be interested in a polynomial expansion of this data-set, but for now, that's more computation than I want to take on."}),"\n",(0,a.jsx)(n.h3,{id:"dimensionality-reduction-pt-2---lda",children:"Dimensionality Reduction pt. 2 - LDA"}),"\n",(0,a.jsx)(n.p,{children:"Knowing that our naive guess performs so well is a blessing and a curse:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:'Curse: The threshold for performance is incredibly high: We can only "improve" over the naive guess by 4%'}),"\n",(0,a.jsx)(n.li,{children:"Blessing: All the binary classification features we just discovered are worthless on their own. We can throw them out and reduce the data dimensionality from 369 to 111."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Now, in removing these features from the dataset, I'm not saying that there is no \"information\" contained within them. There might be. But the only way we'd know is through a polynomial expansion, and I'm not going to take that on within this post."}),"\n",(0,a.jsxs)(n.p,{children:['My initial thought for a "next guess" is to use the ',(0,a.jsx)(n.a,{href:"http://scikit-learn.org/stable/modules/lda_qda.html",children:"LDA"})," model for dimensionality reduction. However, it can only reduce dimensions to ",(0,a.jsxs)(n.span,{className:"katex",children:[(0,a.jsx)(n.span,{className:"katex-mathml",children:(0,a.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(n.semantics,{children:[(0,a.jsxs)(n.mrow,{children:[(0,a.jsx)(n.mn,{children:"1"}),(0,a.jsx)(n.mo,{children:"\u2212"}),(0,a.jsx)(n.mi,{children:"p"})]}),(0,a.jsx)(n.annotation,{encoding:"application/x-tex",children:"1 - p"})]})})}),(0,a.jsxs)(n.span,{className:"katex-html","aria-hidden":"true",children:[(0,a.jsxs)(n.span,{className:"base",children:[(0,a.jsx)(n.span,{className:"strut",style:{height:"0.7278em",verticalAlign:"-0.0833em"}}),(0,a.jsx)(n.span,{className:"mord",children:"1"}),(0,a.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,a.jsx)(n.span,{className:"mbin",children:"\u2212"}),(0,a.jsx)(n.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,a.jsxs)(n.span,{className:"base",children:[(0,a.jsx)(n.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,a.jsx)(n.span,{className:"mord mathnormal",children:"p"})]})]})]}),", with ",(0,a.jsxs)(n.span,{className:"katex",children:[(0,a.jsx)(n.span,{className:"katex-mathml",children:(0,a.jsx)(n.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,a.jsxs)(n.semantics,{children:[(0,a.jsx)(n.mrow,{children:(0,a.jsx)(n.mi,{children:"p"})}),(0,a.jsx)(n.annotation,{encoding:"application/x-tex",children:"p"})]})})}),(0,a.jsx)(n.span,{className:"katex-html","aria-hidden":"true",children:(0,a.jsxs)(n.span,{className:"base",children:[(0,a.jsx)(n.span,{className:"strut",style:{height:"0.625em",verticalAlign:"-0.1944em"}}),(0,a.jsx)(n.span,{className:"mord mathnormal",children:"p"})]})})]})," being the number of classes. Since this is a binary classification, every LDA model that I try will have dimensionality one; when I actually try this, the predictor ends up being slightly less accurate than the naive guess."]}),"\n",(0,a.jsxs)(n.p,{children:["Instead, let's take a different approach to dimensionality reduction: ",(0,a.jsx)(n.a,{href:"http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html",children:"principle components analysis"}),". This allows us to perform the dimensionality reduction without worrying about the number of classes. Then, we'll use a ",(0,a.jsx)(n.a,{href:"http://scikit-learn.org/stable/modules/naive_bayes.html#gaussian-naive-bayes",children:"Gaussian Naive Bayes"})," model to actually do the prediction. This model is chosen simply because it doesn't take a long time to fit and compute; because PCA will take so long, I just want a prediction at the end of this. We can worry about using a more sophisticated LDA/QDA/SVM model later."]}),"\n",(0,a.jsx)(n.p,{children:"Now into the actual process: We're going to test out PCA dimensionality reduction from 1 - 20 dimensions, and then predict using a Gaussian Naive Bayes model. The 20 dimensions upper limit was selected because the accuracy never improves after you get beyond that (I found out by running it myself). Hopefully, we'll find that we can create a model better than the naive guess."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:'from sklearn.naive_bayes import GaussianNB\nfrom sklearn.decomposition import PCA\n\nX_no_bin = X.drop(b_class, 1)\n\ndef evaluate_gnb(dims):\n pca = PCA(n_components=dims)\n X_xform = pca.fit_transform(X_no_bin)\n \n gnb = GaussianNB()\n gnb.fit(X_xform, y)\n return gnb.score(X_xform, y)\n\ndim_range = np.arange(1, 21)\nplt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy")\nplt.axhline(naive_guess, label="Naive Guess", c=\'k\')\nplt.axhline(1 - naive_guess, label="Inverse Naive Guess", c=\'k\')\nplt.gcf().set_size_inches(12, 6)\nplt.legend();\n'})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"png",src:t(9034).Z+"",width:"710",height:"368"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"sigh..."})," After all the effort and computational power, we're still at square one: we have yet to beat out the naive guess threshold. With PCA in play we end up performing terribly, but not terribly enough that we can guess against ourselves."]}),"\n",(0,a.jsx)(n.p,{children:"Let's try one last-ditch attempt using the entire data set:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:'def evaluate_gnb_full(dims):\n pca = PCA(n_components=dims)\n X_xform = pca.fit_transform(X)\n \n gnb = GaussianNB()\n gnb.fit(X_xform, y)\n return gnb.score(X_xform, y)\n\ndim_range = np.arange(1, 21)\nplt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy")\nplt.axhline(naive_guess, label="Naive Guess", c=\'k\')\nplt.axhline(1 - naive_guess, label="Inverse Naive Guess", c=\'k\')\nplt.gcf().set_size_inches(12, 6)\nplt.legend();\n'})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"png",src:t(3448).Z+"",width:"710",height:"368"})}),"\n",(0,a.jsx)(n.p,{children:"Nothing. It is interesting to note that the graphs are almost exactly the same: This would imply again that the variables we removed earlier (all the binary classifiers) indeed have almost no predictive power. It seems this problem is high-dimensional, but with almost no data that can actually inform our decisions."}),"\n",(0,a.jsx)(n.h2,{id:"summary-for-day-1",children:"Summary for Day 1"}),"\n",(0,a.jsxs)(n.p,{children:["After spending a couple hours with this dataset, there seems to be a fundamental issue in play: We have very high-dimensional data, and it has no bearing on our ability to actually predict customer satisfaction. This can be a huge issue: it implies that ",(0,a.jsx)(n.strong,{children:"no matter what model we use, we fundamentally can't perform well."})," I'm sure most of this is because I'm not an experienced data scientist. Even so, we have yet to develop a strategy that can actually beat out the village idiot; ",(0,a.jsx)(n.strong,{children:"so far, the bank is best off just assuming all its customers are satisfied."})," Hopefully more to come soon."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:'end = datetime.now()\nprint("Running time: {}".format(end - start))\n'})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:" Running time: 0:00:58.715714\n"})}),"\n",(0,a.jsx)(n.h2,{id:"appendix",children:"Appendix"}),"\n",(0,a.jsx)(n.p,{children:"Code used to split the initial training data:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-python",children:"from sklearn.cross_validation import train_test_split\ndata = pd.read_csv('train.csv')\ndata.index = data.ID\n\ndata_train, data_validate = train_test_split(\n data, train_size=.7)\n\ndata_train.to_csv('split_train.csv')\ndata_validate.to_csv('split_validate.csv')\n"})})]})}function h(e={}){let{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},9034:function(e,n,t){t.d(n,{Z:function(){return s}});let s=t.p+"assets/images/_notebook_11_0-2d0fe64b876b1c32a095f2d74b128f3c.png"},3448:function(e,n,t){t.d(n,{Z:function(){return s}});let s=t.p+"assets/images/_notebook_13_0-2d0fe64b876b1c32a095f2d74b128f3c.png"},65:function(e,n,t){t.d(n,{Z:function(){return o},a:function(){return r}});var s=t(7294);let a={},i=s.createContext(a);function r(e){let n=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(i.Provider,{value:n},e.children)}},6749:function(e){e.exports=JSON.parse('{"permalink":"/2016/03/predicting-santander-customer-happiness","source":"@site/blog/2016-03-05-predicting-santander-customer-happiness/index.mdx","title":"Predicting Santander customer happiness","description":"My first Kaggle competition.","date":"2016-03-05T12:00:00.000Z","tags":[],"readingTime":6.95,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/predicting-santander-customer-happiness","title":"Predicting Santander customer happiness","date":"2016-03-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"},"nextItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"}}')}}]); \ No newline at end of file diff --git a/assets/js/975a028b.b8fcc2ff.js b/assets/js/975a028b.b8fcc2ff.js new file mode 100644 index 0000000..effd5e2 --- /dev/null +++ b/assets/js/975a028b.b8fcc2ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5478"],{8422:function(e,t,n){n.r(t),n.d(t,{assets:function(){return i},contentTitle:function(){return l},default:function(){return m},frontMatter:function(){return o},metadata:function(){return a},toc:function(){return u}});var a=n(5288),s=n(5893),r=n(65);let o={slug:"2018/12/what-small-business-really-means",title:'More "what companies really mean"',date:new Date("2018-12-04T12:00:00.000Z"),authors:["bspeice"],tags:[]},l=void 0,i={authorsImageUrls:[void 0]},u=[];function c(e){let t={a:"a",p:"p",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["I recently stumbled across a phenomenal small article entitled\n",(0,s.jsx)(t.a,{href:"https://angel.co/blog/what-startups-really-mean-by-why-should-we-hire-you",children:'What Startups Really Mean By "Why Should We Hire You?"'}),".\nHaving been interviewed by smaller companies (though not exactly startups), the questions and\nsubtexts are the same. There's often a question behind the question that you're actually trying to\nanswer, and I wish I spotted the nuance earlier in my career."]}),"\n",(0,s.jsx)(t.p,{children:"Let me also make note of one more question/euphemism I've come across:"})]})}function m(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return l},a:function(){return o}});var a=n(7294);let s={},r=a.createContext(s);function o(e){let t=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),a.createElement(r.Provider,{value:t},e.children)}},5288:function(e){e.exports=JSON.parse('{"permalink":"/2018/12/what-small-business-really-means","source":"@site/blog/2018-12-04-what-small-business-really-means/index.mdx","title":"More \\"what companies really mean\\"","description":"I recently stumbled across a phenomenal small article entitled","date":"2018-12-04T12:00:00.000Z","tags":[],"readingTime":1.205,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/what-small-business-really-means","title":"More \\"what companies really mean\\"","date":"2018-12-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731190109000,"prevItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"},"nextItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"}}')}}]); \ No newline at end of file diff --git a/assets/js/9990.f91a94a2.js b/assets/js/9990.f91a94a2.js new file mode 100644 index 0000000..d6ac5fb --- /dev/null +++ b/assets/js/9990.f91a94a2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9990"],{4802:function(e,n,c){c.d(n,{Z:function(){return i}});let i=c(1336)},7936:function(){}}]); \ No newline at end of file diff --git a/assets/js/9e4087bc.7ce15d2c.js b/assets/js/9e4087bc.7ce15d2c.js new file mode 100644 index 0000000..2835b81 --- /dev/null +++ b/assets/js/9e4087bc.7ce15d2c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7293"],{2204:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var i=r(5893);r(7294);var a=r(3012),n=r(6025),s=r(2743),l=r(1437),c=r(5654),d=r(4403);function o(e){let{year:t,posts:r}=e,n=(0,l.P)({day:"numeric",month:"long",timeZone:"UTC"}),s=e=>n.format(new Date(e));return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(d.Z,{as:"h3",id:t,children:t}),(0,i.jsx)("ul",{children:r.map(e=>(0,i.jsx)("li",{children:(0,i.jsxs)(a.Z,{to:e.metadata.permalink,children:[s(e.metadata.date)," - ",e.metadata.title]})},e.metadata.date))})]})}function h(e){let{years:t}=e;return(0,i.jsx)("section",{className:"margin-vert--lg",children:(0,i.jsx)("div",{className:"container",children:(0,i.jsx)("div",{className:"row",children:t.map((e,t)=>(0,i.jsx)("div",{className:"col col--4 margin-vert--lg",children:(0,i.jsx)(o,{...e})},t))})})})}function m(e){let{archive:t}=e,r=(0,n.I)({id:"theme.blog.archive.title",message:"Archive",description:"The page & hero title of the blog archive page"}),a=(0,n.I)({id:"theme.blog.archive.description",message:"Archive",description:"The page & hero description of the blog archive page"}),l=Array.from(t.blogPosts.reduce((e,t)=>{let r=t.metadata.date.split("-")[0],i=e.get(r)??[];return e.set(r,[t,...i])},new Map),e=>{let[t,r]=e;return{year:t,posts:r}});return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.d,{title:r,description:a}),(0,i.jsxs)(c.Z,{children:[(0,i.jsx)("header",{className:"hero hero--primary",children:(0,i.jsxs)("div",{className:"container",children:[(0,i.jsx)(d.Z,{as:"h1",className:"hero__title",children:r}),(0,i.jsx)("p",{className:"hero__subtitle",children:a})]})}),(0,i.jsx)("main",{children:l.length>0&&(0,i.jsx)(h,{years:l})})]})]})}},1437:function(e,t,r){r.d(t,{P:function(){return a}});var i=r(2933);function a(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{i18n:{currentLocale:t}}=(0,i.Z)(),r=function(){let{i18n:{currentLocale:e,localeConfigs:t}}=(0,i.Z)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:r,...e})}}}]); \ No newline at end of file diff --git a/assets/js/a14a666c.bfdacafa.js b/assets/js/a14a666c.bfdacafa.js new file mode 100644 index 0000000..3fa60ee --- /dev/null +++ b/assets/js/a14a666c.bfdacafa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1000"],{7493:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return m},frontMatter:function(){return a},metadata:function(){return o},toc:function(){return l}});var o=n(2340),r=n(5893),i=n(65);let a={slug:"2019/02/stacking-up",title:"Allocations in Rust: Fixed memory",date:new Date("2019-02-06T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},l=[];function u(e){let t={code:"code",p:"p",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.code,{children:"const"})," and ",(0,r.jsx)(t.code,{children:"static"})," are perfectly fine, but it's relatively rare that we know at compile-time about\neither values or references that will be the same for the duration of our program. Put another way,\nit's not often the case that either you or your compiler knows how much memory your entire program\nwill ever need."]}),"\n",(0,r.jsx)(t.p,{children:'However, there are still some optimizations the compiler can do if it knows how much memory\nindividual functions will need. Specifically, the compiler can make use of "stack" memory (as\nopposed to "heap" memory) which can be managed far faster in both the short- and long-term.'})]})}function m(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return a}});var o=n(7294);let r={},i=o.createContext(r);function a(e){let t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),o.createElement(i.Provider,{value:t},e.children)}},2340:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/stacking-up","source":"@site/blog/2019-02-06-stacking-up/index.mdx","title":"Allocations in Rust: Fixed memory","description":"const and static are perfectly fine, but it\'s relatively rare that we know at compile-time about","date":"2019-02-06T12:00:00.000Z","tags":[],"readingTime":15.165,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/stacking-up","title":"Allocations in Rust: Fixed memory","date":"2019-02-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"},"nextItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"}}')}}]); \ No newline at end of file diff --git a/assets/js/a6aa9e1f.1b78d77e.js b/assets/js/a6aa9e1f.1b78d77e.js new file mode 100644 index 0000000..fc7c8f7 --- /dev/null +++ b/assets/js/a6aa9e1f.1b78d77e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8514"],{1434:function(e,t,n){n.r(t),n.d(t,{default:()=>v});var i=n("5893");n("7294");var r=n("7026"),l=n("2933"),s=n("2743"),a=n("4681"),o=n("979"),c=n("6025"),u=n("790");function p(e){let{metadata:t}=e,{previousPage:n,nextPage:r}=t;return(0,i.jsxs)("nav",{className:"pagination-nav","aria-label":(0,c.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"}),children:[n&&(0,i.jsx)(u.Z,{permalink:n,title:(0,i.jsx)(c.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)",children:"Newer entries"})}),r&&(0,i.jsx)(u.Z,{permalink:r,title:(0,i.jsx)(c.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)",children:"Older entries"}),isNext:!0})]})}var d=n("4315"),g=n("4183"),h=n("2553");function x(e){let{items:t,component:n=h.Z}=e;return(0,i.jsx)(i.Fragment,{children:t.map(e=>{let{content:t}=e;return(0,i.jsx)(g.n4,{content:t,children:(0,i.jsx)(n,{children:(0,i.jsx)(t,{})})},t.metadata.permalink)})})}var j=n("4819");function f(e){let t=(0,g.CS)(e);return(0,i.jsx)(j.Z,{children:(0,i.jsx)("script",{type:"application/ld+json",children:JSON.stringify(t)})})}function m(e){let{metadata:t}=e,{siteConfig:{title:n}}=(0,l.Z)(),{blogDescription:r,blogTitle:a,permalink:o}=t;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.d,{title:"/"===o?n:a,description:r}),(0,i.jsx)(d.Z,{tag:"blog_posts_list"})]})}function b(e){let{metadata:t,items:n,sidebar:r}=e;return(0,i.jsxs)(o.Z,{sidebar:r,children:[(0,i.jsx)(x,{items:n}),(0,i.jsx)(p,{metadata:t})]})}function v(e){return(0,i.jsxs)(s.FG,{className:(0,r.Z)(a.k.wrapper.blogPages,a.k.page.blogListPage),children:[(0,i.jsx)(m,{...e}),(0,i.jsx)(f,{...e}),(0,i.jsx)(b,{...e})]})}},131:function(e,t,n){n.d(t,{Z:function(){return a}});var i=n(5893),r=n(7294),l=n(4403);function s(e){let{title:t,headingType:n,children:r}=e;return(0,i.jsxs)("div",{role:"group",children:[(0,i.jsx)(l.Z,{as:n,children:t}),r]})}let a=(0,r.memo)(function(e){let{items:t,yearGroupHeadingClassName:n,ListComponent:r}=e;return function(e,t){var n=[],r=[];function l(){if(0===r.length)return;let e=new Date(r[0].date).getFullYear(),l=function(e,t){var n=[],r=[];function l(){if(0===r.length)return;let e=r[0].title.split(":")[0];r=(r=r.map(e=>({...e,title:e.title.split(":")[1].trim()}))).reverse(),n.push((0,i.jsx)(i.Fragment,{children:(0,i.jsx)(s,{title:e,headingType:"h4",children:(0,i.jsx)("ul",{children:(0,i.jsx)(t,{items:r})})})})),r=[]}for(let s of e){if(s.title.includes(":")){r.push(s);continue}l(),n.push((0,i.jsx)(t,{items:[s]}))}return l(),n}(r,t);n.push((0,i.jsx)(i.Fragment,{children:(0,i.jsx)(s,{title:String(e),headingType:"h3",children:l})})),r=[]}for(let t of e){if(0===r.length){r.push(t);continue}let e=new Date(t.date).getFullYear();e!==new Date(r[0].date).getFullYear()&&l(),r.push(t)}return l(),n}(t,r)})}}]); \ No newline at end of file diff --git a/assets/js/a7456010.f1672167.js b/assets/js/a7456010.f1672167.js new file mode 100644 index 0000000..d65038b --- /dev/null +++ b/assets/js/a7456010.f1672167.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7365"],{2050:function(e){e.exports=JSON.parse('{"name":"docusaurus-plugin-content-pages","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/acecf23e.31db30f2.js b/assets/js/acecf23e.31db30f2.js new file mode 100644 index 0000000..57c1185 --- /dev/null +++ b/assets/js/acecf23e.31db30f2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7627"],{7548:function(e){e.exports=JSON.parse('{"blogBasePath":"/","blogTitle":"Blog","authorsListPath":"/authors"}')}}]); \ No newline at end of file diff --git a/assets/js/aea41ef6.9227fb2a.js b/assets/js/aea41ef6.9227fb2a.js new file mode 100644 index 0000000..1534115 --- /dev/null +++ b/assets/js/aea41ef6.9227fb2a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4595"],{3200:function(e){e.exports=JSON.parse('{"metadata":{"permalink":"/page/2","page":2,"postsPerPage":10,"totalPages":4,"totalCount":34,"previousPage":"/","nextPage":"/page/3","blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/b08f0f32.4de38c21.js b/assets/js/b08f0f32.4de38c21.js new file mode 100644 index 0000000..abba9cc --- /dev/null +++ b/assets/js/b08f0f32.4de38c21.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9363"],{1998:function(e,s,a){a.r(s),a.d(s,{assets:function(){return h},contentTitle:function(){return l},default:function(){return d},frontMatter:function(){return r},metadata:function(){return t},toc:function(){return m}});var t=a(2208),n=a(5893),i=a(65);let r={slug:"2016/04/tick-tock",title:"Tick tock...",date:new Date("2016-04-06T12:00:00.000Z"),authors:["bspeice"],tags:[]},l=void 0,h={authorsImageUrls:[void 0]},m=[{value:"2.5 Billion",id:"25-billion",level:2},{value:"Statistical Considerations",id:"statistical-considerations",level:2},{value:"Getting the data",id:"getting-the-data",level:2},{value:"Registering an application",id:"registering-an-application",level:2},{value:"Handling OAuth 2",id:"handling-oauth-2",level:3},{value:"Requesting the data",id:"requesting-the-data",level:3},{value:"Wild Extrapolations from Small Data",id:"wild-extrapolations-from-small-data",level:2},{value:"How many heartbeats so far?",id:"how-many-heartbeats-so-far",level:3},{value:"How many heartbeats longer?",id:"how-many-heartbeats-longer",level:3},{value:"Summary",id:"summary",level:2}];function c(e){let s={a:"a",annotation:"annotation",code:"code",h2:"h2",h3:"h3",li:"li",math:"math",mi:"mi",mo:"mo",mrow:"mrow",mstyle:"mstyle",msub:"msub",mtable:"mtable",mtd:"mtd",mtr:"mtr",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.p,{children:"If all we have is a finite number of heartbeats left, what about me?"}),"\n",(0,n.jsx)(s.p,{children:"Warning: this one is a bit creepier. But that's what you get when you come up with data science ideas as you're drifting off to sleep."}),"\n",(0,n.jsx)(s.h2,{id:"25-billion",children:"2.5 Billion"}),"\n",(0,n.jsxs)(s.p,{children:["If ",(0,n.jsx)(s.a,{href:"http://www.pbs.org/wgbh/nova/heart/heartfacts.html",children:"PBS"})," is right, that's the total number of heartbeats we get. Approximately once every second that number goes down, and down, and down again..."]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"total_heartbeats = 2500000000\n"})}),"\n",(0,n.jsx)(s.p,{children:"I got a Fitbit this past Christmas season, mostly because I was interested in the data and trying to work on some data science projects with it. This is going to be the first project, but there will likely be more (and not nearly as morbid). My idea was: If this is the final number that I'm running up against, how far have I come, and how far am I likely to go? I've currently had about 3 months' time to estimate what my data will look like, so let's go ahead and see: given a lifetime 2.5 billion heart beats, how much time do I have left?"}),"\n",(0,n.jsx)(s.h2,{id:"statistical-considerations",children:"Statistical Considerations"}),"\n",(0,n.jsx)(s.p,{children:"Since I'm starting to work with health data, there are a few considerations I think are important before I start digging through my data."}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:["The concept of 2.5 billion as an agreed-upon number is tenuous at best. I've seen anywhere from ",(0,n.jsx)(s.a,{href:"http://gizmodo.com/5982977/how-many-heartbeats-does-each-species-get-in-a-lifetime",children:"2.21 billion"})," to ",(0,n.jsx)(s.a,{href:"http://wonderopolis.org/wonder/how-many-times-does-your-heart-beat-in-a-lifetime/",children:"3.4 billion"})," so even if I knew exactly how many times my heart had beaten so far, the ending result is suspect at best. I'm using 2.5 billion because that seems to be about the midpoint of the estimates I've seen so far."]}),"\n",(0,n.jsx)(s.li,{children:"Most of the numbers I've seen so far are based on extrapolating number of heart beats from life expectancy. As life expectancy goes up, the number of expected heart beats goes up too."}),"\n",(0,n.jsx)(s.li,{children:"My estimation of the number of heartbeats in my life so far is based on 3 months worth of data, and I'm extrapolating an entire lifetime based on this."}),"\n"]}),"\n",(0,n.jsxs)(s.p,{children:["So while the ending number is ",(0,n.jsx)(s.strong,{children:"not useful in any medical context"}),", it is still an interesting project to work with the data I have on hand."]}),"\n",(0,n.jsx)(s.h2,{id:"getting-the-data",children:"Getting the data"}),"\n",(0,n.jsxs)(s.p,{children:[(0,n.jsx)(s.a,{href:"https://www.fitbit.com/",children:"Fitbit"})," has an ",(0,n.jsx)(s.a,{href:"https://dev.fitbit.com/",children:"API available"})," for people to pull their personal data off the system. It requires registering an application, authentication with OAuth, and some other complicated things. ",(0,n.jsxs)(s.strong,{children:["If you're not interested in how I fetch the data, skip ",(0,n.jsx)(s.a,{href:"#Wild-Extrapolations-from-Small-Data",children:"here"})]}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"registering-an-application",children:"Registering an application"}),"\n",(0,n.jsxs)(s.p,{children:["I've already ",(0,n.jsx)(s.a,{href:"https://dev.fitbit.com/apps/new",children:"registered a personal application"})," with Fitbit, so I can go ahead and retrieve things like the client secret from a file."]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"# Import all the OAuth secret information from a local file\nfrom secrets import CLIENT_SECRET, CLIENT_ID, CALLBACK_URL\n"})}),"\n",(0,n.jsx)(s.h3,{id:"handling-oauth-2",children:"Handling OAuth 2"}),"\n",(0,n.jsx)(s.p,{children:"So, all the people that know what OAuth 2 is know what's coming next. For those who don't: OAuth is how people allow applications to access other data without having to know your password. Essentially the dialog goes like this:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:"Application: I've got a user here who wants to use my application, but I need their data.\nFitbit: OK, what data do you need access to, and for how long?\nApplication: I need all of these scopes, and for this amount of time.\nFitbit: OK, let me check with the user to make sure they really want to do this.\n\nFitbit: User, do you really want to let this application have your data?\nUser: I do! And to prove it, here's my password.\nFitbit: OK, everything checks out. I'll let the application access your data.\n\nFitbit: Application, you can access the user's data. Use this special value whenever you need to request data from me.\nApplication: Thank you, now give me all the data.\n"})}),"\n",(0,n.jsx)(s.p,{children:"Effectively, this allows an application to gain access to a user's data without ever needing to know the user's password. That way, even if the other application is hacked, the user's original data remains safe. Plus, the user can let the data service know to stop providing the application access any time they want. All in all, very secure."}),"\n",(0,n.jsxs)(s.p,{children:["It does make handling small requests a bit challenging, but I'll go through the steps here. We'll be using the ",(0,n.jsx)(s.a,{href:"https://dev.fitbit.com/docs/oauth2/",children:"Implicit Grant"})," workflow, as it requires fewer steps in processing."]}),"\n",(0,n.jsx)(s.p,{children:"First, we need to set up the URL the user would visit to authenticate:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"import urllib\n\nFITBIT_URI = 'https://www.fitbit.com/oauth2/authorize'\nparams = {\n # If we need more than one scope, must be a CSV string\n 'scope': 'heartrate',\n 'response_type': 'token',\n 'expires_in': 86400, # 1 day\n 'redirect_uri': CALLBACK_URL,\n 'client_id': CLIENT_ID\n}\n\nrequest_url = FITBIT_URI + '?' + urllib.parse.urlencode(params)\n"})}),"\n",(0,n.jsxs)(s.p,{children:["Now, here you would print out the request URL, go visit it, and get the full URL that it sends you back to. Because that is very sensitive information (specifically containing my ",(0,n.jsx)(s.code,{children:"CLIENT_ID"})," that I'd really rather not share on the internet), I've skipped that step in the code here, but it happens in the background."]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"# The `response_url` variable contains the full URL that\n# FitBit sent back to us, but most importantly,\n# contains the token we need for authorization.\naccess_token = dict(urllib.parse.parse_qsl(response_url))['access_token']\n"})}),"\n",(0,n.jsx)(s.h3,{id:"requesting-the-data",children:"Requesting the data"}),"\n",(0,n.jsxs)(s.p,{children:["Now that we've actually set up our access via the ",(0,n.jsx)(s.code,{children:"access_token"}),", it's time to get the actual ",(0,n.jsx)(s.a,{href:"https://dev.fitbit.com/docs/heart-rate/",children:"heart rate data"}),". I'll be using data from January 1, 2016 through March 31, 2016, and extrapolating wildly from that."]}),"\n",(0,n.jsx)(s.p,{children:"Fitbit only lets us fetch intraday data one day at a time, so I'll create a date range using pandas and iterate through that to pull down all the data."}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"from requests_oauthlib import OAuth2Session\nimport pandas as pd\nfrom datetime import datetime\n\nsession = OAuth2Session(token={\n 'access_token': access_token,\n 'token_type': 'Bearer'\n })\n\nformat_str = '%Y-%m-%d'\nstart_date = datetime(2016, 1, 1)\nend_date = datetime(2016, 3, 31)\ndr = pd.date_range(start_date, end_date)\n\nurl = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json'\nhr_responses = [session.get(url.format(d.strftime(format_str))) for d in dr]\n\ndef record_to_df(record):\n if 'activities-heart' not in record:\n return None\n date_str = record['activities-heart'][0]['dateTime']\n df = pd.DataFrame(record['activities-heart-intraday']['dataset'])\n \n df.index = df['time'].apply(\n lambda x: datetime.strptime(date_str + ' ' + x, '%Y-%m-%d %H:%M:%S'))\n return df\n\nhr_dataframes = [record_to_df(record.json()) for record in hr_responses]\nhr_df_concat = pd.concat(hr_dataframes)\n\n\n# There are some minutes with missing data, so we need to correct that\nfull_daterange = pd.date_range(hr_df_concat.index[0],\n hr_df_concat.index[-1],\n freq='min')\nhr_df_full = hr_df_concat.reindex(full_daterange, method='nearest')\n\nprint(\"Heartbeats from {} to {}: {}\".format(hr_df_full.index[0],\n hr_df_full.index[-1],\n hr_df_full['value'].sum()))\n"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" Heartbeats from 2016-01-01 00:00:00 to 2016-03-31 23:59:00: 8139060\n"})}),"\n",(0,n.jsxs)(s.p,{children:["And now we've retrieved all the available heart rate data for January 1",(0,n.jsx)("sup",{children:"st"})," through March 31",(0,n.jsx)("sup",{children:"st"}),"! Let's get to the actual analysis."]}),"\n",(0,n.jsx)(s.h2,{id:"wild-extrapolations-from-small-data",children:"Wild Extrapolations from Small Data"}),"\n",(0,n.jsx)(s.p,{children:"A fundamental issue of this data is that it's pretty small. I'm using 3 months of data to make predictions about my entire life. But, purely as an exercise, I'll move forward."}),"\n",(0,n.jsx)(s.h3,{id:"how-many-heartbeats-so-far",children:"How many heartbeats so far?"}),"\n",(0,n.jsxs)(s.p,{children:["The first step is figuring out how many of the 2.5 billion heartbeats I've used so far. We're going to try and work backward from the present day to when I was born to get that number. The easy part comes first: going back to January 1",(0,n.jsx)("sup",{children:"st"}),", 1992. That's because I can generalize how many 3-month increments there were between now and then, account for leap years, and call that section done."]}),"\n",(0,n.jsx)(s.p,{children:"Between January 1992 and January 2016 there were 96 quarters, and 6 leap days. The number we're looking for is:"}),"\n",(0,n.jsx)(s.span,{className:"katex-display",children:(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mtable,{rowspacing:"0.16em",columnspacing:"1em",children:(0,n.jsx)(s.mtr,{children:(0,n.jsx)(s.mtd,{children:(0,n.jsx)(s.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"q"})]}),(0,n.jsx)(s.mo,{children:"\u22C5"}),(0,n.jsx)(s.mi,{children:"n"}),(0,n.jsx)(s.mo,{children:"\u2212"}),(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"d"})]}),(0,n.jsx)(s.mo,{children:"\u22C5"}),(0,n.jsx)(s.mo,{stretchy:"false",children:"("}),(0,n.jsx)(s.mi,{children:"n"}),(0,n.jsx)(s.mo,{children:"\u2212"}),(0,n.jsx)(s.mi,{children:"m"}),(0,n.jsx)(s.mo,{stretchy:"false",children:")"})]})})})})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"\\begin{equation*}\nhr_q \\cdot n - hr_d \\cdot (n-m)\n\\end{equation*}"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"1.2em",verticalAlign:"-0.35em"}}),(0,n.jsx)(s.span,{className:"mord",children:(0,n.jsx)(s.span,{className:"mtable",children:(0,n.jsx)(s.span,{className:"col-align-c",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.85em"},children:(0,n.jsxs)(s.span,{style:{top:"-3.01em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.1514em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"q"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(s.span,{})})})]})})]}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u22C5"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u2212"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(s.span,{})})})]})})]}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u22C5"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mopen",children:"("}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u2212"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"m"}),(0,n.jsx)(s.span,{className:"mclose",children:")"})]})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.35em"},children:(0,n.jsx)(s.span,{})})})]})})})})]})})]})}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"q"})]})]}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"hr_q"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.9805em",verticalAlign:"-0.2861em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.1514em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"q"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(s.span,{})})})]})})]})]})})]}),": Number of heartbeats per quarter"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"d"})]})]}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"hr_d"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(s.span,{})})})]})})]})]})})]}),": Number of heartbeats on leap day"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mrow,{children:(0,n.jsx)(s.mi,{children:"n"})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"})]})})]}),": Number of quarters, in this case 96"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mrow,{children:(0,n.jsx)(s.mi,{children:"m"})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"m"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"m"})]})})]}),": Number of leap days, in this case 6"]}),"\n"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"quarterly_count = hr_df_full['value'].sum()\nleap_day_count = hr_df_full[(hr_df_full.index.month == 2) &\n (hr_df_full.index.day == 29)]['value'].sum()\nnum_quarters = 96\nleap_days = 6\n\njan_92_jan_16 = quarterly_count * num_quarters - leap_day_count * (num_quarters - leap_days)\njan_92_jan_16\n"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" 773609400\n"})}),"\n",(0,n.jsxs)(s.p,{children:["So between January 1992 and January 2016 I've used ",(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mrow,{children:(0,n.jsx)(s.mo,{children:"\u2248"})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"\\approx"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.4831em"}}),(0,n.jsx)(s.span,{className:"mrel",children:"\u2248"})]})})]})," 774 million heartbeats. Now, I need to go back to my exact birthday. I'm going to first find on average how many heartbeats I use in a minute, and multiply that by the number of minutes between my birthday and January 1992."]}),"\n",(0,n.jsx)(s.p,{children:"For privacy purposes I'll put the code here that I'm using, but without any identifying information:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:'minute_mean = hr_df_full[\'value\'].mean()\n# Don\'t you wish you knew?\n# birthday_minutes = ???\n\nbirthday_heartbeats = birthday_minutes * minute_mean\n\nheartbeats_until_2016 = int(birthday_heartbeats + jan_92_jan_16)\nremaining_2016 = total_heartbeats - heartbeats_until_2016\n\nprint("Heartbeats so far: {}".format(heartbeats_until_2016))\nprint("Remaining heartbeats: {}".format(remaining_2016))\n'})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" Heartbeats so far: 775804660\n Remaining heartbeats: 1724195340\n"})}),"\n",(0,n.jsxs)(s.p,{children:["It would appear that my heart has beaten 775,804,660 times between my moment of birth and January 1",(0,n.jsx)("sup",{children:"st"})," 2016, and that I have 1.72 billion left."]}),"\n",(0,n.jsx)(s.h3,{id:"how-many-heartbeats-longer",children:"How many heartbeats longer?"}),"\n",(0,n.jsx)(s.p,{children:"Now comes the tricky bit. I know how many heart beats I've used so far, and how many I have remaining, so I'd like to come up with a (relatively) accurate estimate of when exactly my heart should give out. We'll do this in a few steps, increasing in granularity."}),"\n",(0,n.jsx)(s.p,{children:"First step, how many heartbeats do I use in a 4-year period? I have data for a single quarter including leap day, so I want to know:"}),"\n",(0,n.jsx)(s.span,{className:"katex-display",children:(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mtable,{rowspacing:"0.16em",columnspacing:"1em",children:(0,n.jsx)(s.mtr,{children:(0,n.jsx)(s.mtd,{children:(0,n.jsx)(s.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"q"})]}),(0,n.jsx)(s.mo,{children:"\u22C5"}),(0,n.jsx)(s.mi,{children:"n"}),(0,n.jsx)(s.mo,{children:"\u2212"}),(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"d"})]}),(0,n.jsx)(s.mo,{children:"\u22C5"}),(0,n.jsx)(s.mo,{stretchy:"false",children:"("}),(0,n.jsx)(s.mi,{children:"n"}),(0,n.jsx)(s.mo,{children:"\u2212"}),(0,n.jsx)(s.mi,{children:"m"}),(0,n.jsx)(s.mo,{stretchy:"false",children:")"})]})})})})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"\\begin{equation*}\nhr_q \\cdot n - hr_d \\cdot (n - m)\n\\end{equation*}"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"1.2em",verticalAlign:"-0.35em"}}),(0,n.jsx)(s.span,{className:"mord",children:(0,n.jsx)(s.span,{className:"mtable",children:(0,n.jsx)(s.span,{className:"col-align-c",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.85em"},children:(0,n.jsxs)(s.span,{style:{top:"-3.01em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"3em"}}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.1514em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"q"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(s.span,{})})})]})})]}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u22C5"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u2212"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(s.span,{})})})]})})]}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u22C5"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mopen",children:"("}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mbin",children:"\u2212"}),(0,n.jsx)(s.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"m"}),(0,n.jsx)(s.span,{className:"mclose",children:")"})]})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.35em"},children:(0,n.jsx)(s.span,{})})})]})})})})]})})]})}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"q"})]})]}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"hr_q"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.9805em",verticalAlign:"-0.2861em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.1514em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",style:{marginRight:"0.03588em"},children:"q"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.2861em"},children:(0,n.jsx)(s.span,{})})})]})})]})]})})]}),": Heartbeats per quarter"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsxs)(s.mrow,{children:[(0,n.jsx)(s.mi,{children:"h"}),(0,n.jsxs)(s.msub,{children:[(0,n.jsx)(s.mi,{children:"r"}),(0,n.jsx)(s.mi,{children:"d"})]})]}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"hr_d"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"h"}),(0,n.jsxs)(s.span,{className:"mord",children:[(0,n.jsx)(s.span,{className:"mord mathnormal",style:{marginRight:"0.02778em"},children:"r"}),(0,n.jsx)(s.span,{className:"msupsub",children:(0,n.jsxs)(s.span,{className:"vlist-t vlist-t2",children:[(0,n.jsxs)(s.span,{className:"vlist-r",children:[(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.3361em"},children:(0,n.jsxs)(s.span,{style:{top:"-2.55em",marginLeft:"-0.0278em",marginRight:"0.05em"},children:[(0,n.jsx)(s.span,{className:"pstrut",style:{height:"2.7em"}}),(0,n.jsx)(s.span,{className:"sizing reset-size6 size3 mtight",children:(0,n.jsx)(s.span,{className:"mord mathnormal mtight",children:"d"})})]})}),(0,n.jsx)(s.span,{className:"vlist-s",children:"\u200B"})]}),(0,n.jsx)(s.span,{className:"vlist-r",children:(0,n.jsx)(s.span,{className:"vlist",style:{height:"0.15em"},children:(0,n.jsx)(s.span,{})})})]})})]})]})})]}),": Heartbeats per leap day"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mrow,{children:(0,n.jsx)(s.mi,{children:"n"})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"n"})]})})]}),": Number of quarters = 16"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsxs)(s.span,{className:"katex",children:[(0,n.jsx)(s.span,{className:"katex-mathml",children:(0,n.jsx)(s.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,n.jsxs)(s.semantics,{children:[(0,n.jsx)(s.mrow,{children:(0,n.jsx)(s.mi,{children:"m"})}),(0,n.jsx)(s.annotation,{encoding:"application/x-tex",children:"m"})]})})}),(0,n.jsx)(s.span,{className:"katex-html","aria-hidden":"true",children:(0,n.jsxs)(s.span,{className:"base",children:[(0,n.jsx)(s.span,{className:"strut",style:{height:"0.4306em"}}),(0,n.jsx)(s.span,{className:"mord mathnormal",children:"m"})]})})]}),": Number of leap days = 1"]}),"\n"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"heartbeats_4year = quarterly_count * 16 - leap_day_count * (16 - 1)\nheartbeats_4year\n"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" 128934900\n"})}),"\n",(0,n.jsx)(s.p,{children:"Now, I can fast forward from 2016 the number of periods of 4 years I have left."}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:'four_year_periods = remaining_2016 // heartbeats_4year\nremaining_4y = remaining_2016 - four_year_periods * heartbeats_4year\n\nprint("Four year periods remaining: {}".format(four_year_periods))\nprint("Remaining heartbeats after 4 year periods: {}".format(remaining_4y))\n'})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" Four year periods remaining: 13\n Remaining heartbeats after 4 year periods: 48041640\n"})}),"\n",(0,n.jsx)(s.p,{children:"Given that there are 13 four-year periods left, I can move from 2016 all the way to 2068, and find that I will have 48 million heart beats left. Let's drop down to figuring out how many quarters that is. I know that 2068 will have a leap day (unless someone finally decides to get rid of them), so I'll subtract that out first. Then, I'm left to figure out how many quarters exactly are left."}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:'remaining_leap = remaining_4y - leap_day_count\n# Ignore leap day in the data set\nheartbeats_quarter = hr_df_full[(hr_df_full.index.month != 2) &\n (hr_df_full.index.day != 29)][\'value\'].sum()\nquarters_left = remaining_leap // heartbeats_quarter\nremaining_year = remaining_leap - quarters_left * heartbeats_quarter\n\nprint("Quarters left starting 2068: {}".format(quarters_left))\nprint("Remaining heartbeats after that: {}".format(remaining_year))\n'})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" Quarters left starting 2068: 8\n Remaining heartbeats after that: 4760716\n"})}),"\n",(0,n.jsxs)(s.p,{children:["So, that analysis gets me through until January 1",(0,n.jsx)("sup",{children:"st"})," 2070. Final step, using that minute estimate to figure out how many minutes past that I'm predicted to have:"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-python",children:"from datetime import timedelta\n\nbase = datetime(2070, 1, 1)\nminutes_left = remaining_year // minute_mean\n\nkaput = timedelta(minutes=minutes_left)\nbase + kaput\n"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:" datetime.datetime(2070, 2, 23, 5, 28)\n"})}),"\n",(0,n.jsxs)(s.p,{children:["According to this, I've got until February 23",(0,n.jsx)("sup",{children:"rd"}),", 2070 at 5:28 PM in the evening before my heart gives out."]}),"\n",(0,n.jsx)(s.h2,{id:"summary",children:"Summary"}),"\n",(0,n.jsxs)(s.p,{children:["Well, that's kind of a creepy date to know. As I said at the top though, ",(0,n.jsx)(s.strong,{children:"this number is totally useless in any medical context"}),". It ignores the rate at which we continue to get better at making people live longer, and is extrapolating from 3 months' worth of data the rest of my life. Additionally, throughout my time developing this post I made many minor mistakes. I think they're all fixed now, but it's easy to mix a number up here or there and the analysis gets thrown off by a couple years."]}),"\n",(0,n.jsxs)(s.p,{children:["Even still, I think philosophically humans have a desire to know how much time we have left in the world. ",(0,n.jsx)(s.a,{href:"https://www.biblegateway.com/passage/?search=psalm+144&version=ESV",children:"Man is but a breath"}),", and it's scary to think just how quickly that date may be coming up. This analysis asks an important question though: what are you going to do with the time you have left?"]}),"\n",(0,n.jsx)(s.p,{children:"Thanks for sticking with me on this one, I promise it will be much less depressing next time!"})]})}function d(e={}){let{wrapper:s}={...(0,i.a)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},65:function(e,s,a){a.d(s,{Z:function(){return l},a:function(){return r}});var t=a(7294);let n={},i=t.createContext(n);function r(e){let s=t.useContext(i);return t.useMemo(function(){return"function"==typeof e?e(s):{...s,...e}},[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),t.createElement(i.Provider,{value:s},e.children)}},2208:function(e){e.exports=JSON.parse('{"permalink":"/2016/04/tick-tock","source":"@site/blog/2016-04-06-tick-tock/index.mdx","title":"Tick tock...","description":"If all we have is a finite number of heartbeats left, what about me?","date":"2016-04-06T12:00:00.000Z","tags":[],"readingTime":10.125,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/04/tick-tock","title":"Tick tock...","date":"2016-04-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"},"nextItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"}}')}}]); \ No newline at end of file diff --git a/assets/js/b16509ac.cc76897d.js b/assets/js/b16509ac.cc76897d.js new file mode 100644 index 0000000..de60952 --- /dev/null +++ b/assets/js/b16509ac.cc76897d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2628"],{9804:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return a},default:function(){return l},frontMatter:function(){return o},metadata:function(){return r},toc:function(){return c}});var r=n(510),s=n(5893),i=n(65);let o={slug:"2016/10/rustic-repodcasting",title:"A Rustic re-podcasting server",date:new Date("2016-10-22T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,u={authorsImageUrls:[void 0]},c=[];function p(e){let t={p:"p",...(0,i.a)(),...e.components};return(0,s.jsx)(t.p,{children:"Learning Rust by fire (it sounds better than learning by corrosion)"})}function l(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return o}});var r=n(7294);let s={},i=r.createContext(s);function o(e){let t=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),r.createElement(i.Provider,{value:t},e.children)}},510:function(e){e.exports=JSON.parse('{"permalink":"/2016/10/rustic-repodcasting","source":"@site/blog/2016-10-22-rustic-repodcasting/index.mdx","title":"A Rustic re-podcasting server","description":"Learning Rust by fire (it sounds better than learning by corrosion)","date":"2016-10-22T12:00:00.000Z","tags":[],"readingTime":10.405,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/10/rustic-repodcasting","title":"A Rustic re-podcasting server","date":"2016-10-22T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"},"nextItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"}}')}}]); \ No newline at end of file diff --git a/assets/js/b266de79.ae25f078.js b/assets/js/b266de79.ae25f078.js new file mode 100644 index 0000000..ce82777 --- /dev/null +++ b/assets/js/b266de79.ae25f078.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1225"],{6760:function(e){e.exports=JSON.parse('{"archive":{"blogPosts":[{"id":"2011/11/webpack-industrial-complex","metadata":{"permalink":"/2011/11/webpack-industrial-complex","source":"@site/blog/2022-11-20-webpack-industrial-complex/index.mdx","title":"The webpack industrial complex","description":"This started because I wanted to build a synthesizer. Setting a goal of \\"digital DX7\\" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).","date":"2022-11-20T12:00:00.000Z","tags":[],"readingTime":4.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2011/11/webpack-industrial-complex","title":"The webpack industrial complex","date":"2022-11-20T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731274898000,"nextItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"}},"content":"This started because I wanted to build a synthesizer. Setting a goal of \\"digital DX7\\" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).\\n\\nThe project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it\'s still not clear whether those problems were my fault. As a result, I\'m writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.\\n\\n\x3c!-- truncate --\x3e\\n\\n## Starting strong\\n\\nThe sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is \\"compile TypeScript, show it in a browser.\\"\\n\\nCreate React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an `onEvent` handler and a function easy.\\n\\nSome quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking \\"modern browsers are magical.\\"\\n\\n## Continuing on\\n\\nNow comes the first mistake: I began to worry about \\"scale\\" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?\\n\\nThe first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API [was missing](https://github.com/microsoft/TypeScript/issues/28308). After searching out Github issues and (unsuccessfully) tweaking the `.tsconfig` settings, I settled on installing a package and moving on.\\n\\nThe next problem came from actually using the API. Worklets must load from separate \\"modules,\\" but it wasn\'t clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use `new URL(<local path>, import.meta.url)` and it worked! Well, kind of:\\n\\n![Browser error](./video_mp2t.png)\\n\\nThat file has the audio processor code, so why does it get served with `Content-Type: video/mp2t`?\\n\\n## Floundering about\\n\\nNow comes the second mistake: even though I didn\'t understand the error, I ignored recommendations to [just use JavaScript](https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474) and stuck by the original TypeScript requirement.\\n\\nI tried different project structures. Moving the worklet code to a new folder didn\'t help, nor did setting up a monorepo and placing it in a new package.\\n\\nI tried three different CRA tools - `react-app-rewired`, `craco`, `customize-react-app` - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn\'t clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well.\\n\\nI tried changing the webpack configuration: using [new](https://github.com/webpack/webpack/issues/11543#issuecomment-917673256) [loaders](https://github.com/popelenkow/worker-url), setting [asset rules](https://github.com/webpack/webpack/discussions/14093#discussioncomment-1257149), even [changing how webpack detects worker resources](https://github.com/webpack/webpack/issues/11543#issuecomment-826897590). In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn\'t find audio worklet examples in any other framework, I gave up.\\n\\nI tried so many application frameworks. Next.js looked like a good candidate, but added its own [bespoke webpack complexity](https://github.com/vercel/next.js/issues/24907) to the existing confusion. Astro had the best \\"getting started\\" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn\'t import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn\'t figure out how to make them work.\\n\\n## Learning and reflecting\\n\\nI ended up using Vite and vite-plugin-react-pages to handle both \\"build the app\\" and \\"bundle worklets,\\" but the specific tool choice isn\'t important. Instead, the focus should be on lessons learned.\\n\\nFor myself:\\n\\n- I\'m obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: \\"types are awesome\\"), it can get in the way of more important work\\n- I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts\\n\\nFor the tools:\\n\\n- Resource bundling is great and solves a genuine challenge. I\'ve heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity\\n- Webpack is a build system and modern frameworks are deeply dependent on it (hence the \\"webpack industrial complex\\"). While this often saves users from unnecessary complexity, there\'s no path forward if something breaks\\n- There\'s little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren\'t portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn\'t integrate it\\n\\nIn the end, learning new systems is fun, but a focus on tools that \\"just work\\" can leave users out in the cold if they break down."},{"id":"2019/12/release-the-gil","metadata":{"permalink":"/2019/12/release-the-gil","source":"@site/blog/2019-12-14-release-the-gil/index.mdx","title":"Release the GIL","description":"Complaining about the Global Interpreter Lock","date":"2019-12-14T12:00:00.000Z","tags":[],"readingTime":8.58,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/12/release-the-gil","title":"Release the GIL","date":"2019-12-14T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"The webpack industrial complex","permalink":"/2011/11/webpack-industrial-complex"},"nextItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"}},"content":"Complaining about the [Global Interpreter Lock](https://wiki.python.org/moin/GlobalInterpreterLock)\\n(GIL) seems like a rite of passage for Python developers. It\'s easy to criticize a design decision\\nmade before multi-core CPU\'s were widely available, but the fact that it\'s still around indicates\\nthat it generally works [Good](https://wiki.c2.com/?PrematureOptimization)\\n[Enough](https://wiki.c2.com/?YouArentGonnaNeedIt). Besides, there are simple and effective\\nworkarounds; it\'s not hard to start a\\n[new process](https://docs.python.org/3/library/multiprocessing.html) and use message passing to\\nsynchronize code running in parallel.\\n\\nStill, wouldn\'t it be nice to have more than a single active interpreter thread? In an age of\\nasynchronicity and _M:N_ threading, Python seems lacking. The ideal scenario is to take advantage of\\nboth Python\'s productivity and the modern CPU\'s parallel capabilities.\\n\\n\x3c!-- truncate --\x3e\\n\\nPresented below are two strategies for releasing the GIL\'s icy grip without giving up on what makes\\nPython a nice language to start with. Bear in mind: these are just the tools, no claim is made about\\nwhether it\'s a good idea to use them. Very often, unlocking the GIL is an\\n[XY problem](https://en.wikipedia.org/wiki/XY_problem); you want application performance, and the\\nGIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at\\nthe expense of project complexity; messing with the GIL is ultimately messing with Python\'s memory\\nmodel.\\n\\n```python\\n%load_ext Cython\\nfrom numba import jit\\n\\nN = 1_000_000_000\\n```\\n\\n## Cython\\n\\nPut simply, [Cython](https://cython.org/) is a programming language that looks a lot like Python,\\ngets [transpiled](https://en.wikipedia.org/wiki/Source-to-source_compiler) to C/C++, and integrates\\nwell with the [CPython](https://en.wikipedia.org/wiki/CPython) API. It\'s great for building Python\\nwrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And\\nwhen it comes to managing the GIL, there are two special features:\\n\\n- The `nogil`\\n [function annotation](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#declaring-a-function-as-callable-without-the-gil)\\n asserts that a Cython function is safe to use without the GIL, and compilation will fail if it\\n interacts with Python in an unsafe manner\\n- The `with nogil`\\n [context manager](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#releasing-the-gil)\\n explicitly unlocks the CPython GIL while active\\n\\nWhenever Cython code runs inside a `with nogil` block on a separate thread, the Python interpreter\\nis unblocked and allowed to continue work elsewhere. We\'ll define a \\"busy work\\" function that\\ndemonstrates this principle in action:\\n\\n```python\\n%%cython\\n\\n# Annotating a function with `nogil` indicates only that it is safe\\n# to call in a `with nogil` block. It *does not* release the GIL.\\ncdef unsigned long fibonacci(unsigned long n) nogil:\\n if n <= 1:\\n return n\\n\\n cdef unsigned long a = 0, b = 1, c = 0\\n\\n c = a + b\\n for _i in range(2, n):\\n a = b\\n b = c\\n c = a + b\\n\\n return c\\n\\n\\ndef cython_nogil(unsigned long n):\\n # Explicitly release the GIL while running `fibonacci`\\n with nogil:\\n value = fibonacci(n)\\n\\n return value\\n\\n\\ndef cython_gil(unsigned long n):\\n # Because the GIL is not explicitly released, it implicitly\\n # remains acquired when running the `fibonacci` function\\n return fibonacci(n)\\n```\\n\\nFirst, let\'s time how long it takes Cython to calculate the billionth Fibonacci number:\\n\\n```python\\n%%time\\n_ = cython_gil(N);\\n```\\n\\n> <pre>\\n> CPU times: user 365 ms, sys: 0 ns, total: 365 ms\\n> Wall time: 372 ms\\n> </pre>\\n\\n```python\\n%%time\\n_ = cython_nogil(N);\\n```\\n\\n> <pre>\\n> CPU times: user 381 ms, sys: 0 ns, total: 381 ms\\n> Wall time: 388 ms\\n> </pre>\\n\\nBoth versions (with and without GIL) take effectively the same amount of time to run. Even when\\nrunning this calculation in parallel on separate threads, it is expected that the run time will\\ndouble because only one thread can be active at a time:\\n\\n```python\\n%%time\\nfrom threading import Thread\\n\\n# Create the two threads to run on\\nt1 = Thread(target=cython_gil, args=[N])\\nt2 = Thread(target=cython_gil, args=[N])\\n# Start the threads\\nt1.start(); t2.start()\\n# Wait for the threads to finish\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms\\n> Wall time: 645 ms\\n> </pre>\\n\\nHowever, if the first thread releases the GIL, the second thread is free to acquire it and run in\\nparallel:\\n\\n```python\\n%%time\\n\\nt1 = Thread(target=cython_nogil, args=[N])\\nt2 = Thread(target=cython_gil, args=[N])\\nt1.start(); t2.start()\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 717 ms, sys: 372 \xb5s, total: 718 ms\\n> Wall time: 358 ms\\n> </pre>\\n\\nBecause `user` time represents the sum of processing time on all threads, it doesn\'t change much.\\nThe [\\"wall time\\"](https://en.wikipedia.org/wiki/Elapsed_real_time) has been cut roughly in half\\nbecause each function is running simultaneously.\\n\\nKeep in mind that the **order in which threads are started** makes a difference!\\n\\n```python\\n%%time\\n\\n# Note that the GIL-locked version is started first\\nt1 = Thread(target=cython_gil, args=[N])\\nt2 = Thread(target=cython_nogil, args=[N])\\nt1.start(); t2.start()\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 667 ms, sys: 0 ns, total: 667 ms\\n> Wall time: 672 ms\\n> </pre>\\n\\nEven though the second thread releases the GIL while running, it can\'t start until the first has\\ncompleted. Thus, the overall runtime is effectively the same as running two GIL-locked threads.\\n\\nFinally, be aware that attempting to unlock the GIL from a thread that doesn\'t own it will crash the\\n**interpreter**, not just the thread attempting the unlock:\\n\\n```python\\n%%cython\\n\\ncdef int cython_recurse(int n) nogil:\\n if n <= 0:\\n return 0\\n\\n with nogil:\\n return cython_recurse(n - 1)\\n\\ncython_recurse(2)\\n```\\n\\n> <pre>\\n> Fatal Python error: PyEval_SaveThread: NULL tstate\\n> \\n> Thread 0x00007f499effd700 (most recent call first):\\n> File \\"/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py\\", line 39 in run\\n> File \\"/usr/lib/python3.7/threading.py\\", line 926 in _bootstrap_inner\\n> File \\"/usr/lib/python3.7/threading.py\\", line 890 in _bootstrap\\n> </pre>\\n\\nIn practice, avoiding this issue is simple. First, `nogil` functions probably shouldn\'t contain\\n`with nogil` blocks. Second, Cython can\\n[conditionally acquire/release](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#conditional-acquiring-releasing-the-gil)\\nthe GIL, so these conditions can be used to synchronize access. Finally, Cython\'s documentation for\\n[external C code](https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil)\\ncontains more detail on how to safely manage the GIL.\\n\\nTo conclude: use Cython\'s `nogil` annotation to assert that functions are safe for calling when the\\nGIL is unlocked, and `with nogil` to actually unlock the GIL and run those functions.\\n\\n## Numba\\n\\nLike Cython, [Numba](https://numba.pydata.org/) is a \\"compiled Python.\\" Where Cython works by\\ncompiling a Python-like language to C/C++, Numba compiles Python bytecode _directly to machine code_\\nat runtime. Behavior is controlled with a special `@jit` decorator; calling a decorated function\\nfirst compiles it to machine code before running. Calling the function a second time re-uses that\\nmachine code unless the argument types have changed.\\n\\nNumba works best when a `nopython=True` argument is added to the `@jit` decorator; functions\\ncompiled in [`nopython`](http://numba.pydata.org/numba-doc/latest/user/jit.html?#nopython) mode\\navoid the CPython API and have performance comparable to C. Further, adding `nogil=True` to the\\n`@jit` decorator unlocks the GIL while that function is running. Note that `nogil` and `nopython`\\nare separate arguments; while it is necessary for code to be compiled in `nopython` mode in order to\\nrelease the lock, the GIL will remain locked if `nogil=False` (the default).\\n\\nLet\'s repeat the same experiment, this time using Numba instead of Cython:\\n\\n```python\\n# The `int` type annotation is only for humans and is ignored\\n# by Numba.\\n@jit(nopython=True, nogil=True)\\ndef numba_nogil(n: int) -> int:\\n if n <= 1:\\n return n\\n\\n a = 0\\n b = 1\\n\\n c = a + b\\n for _i in range(2, n):\\n a = b\\n b = c\\n c = a + b\\n\\n return c\\n\\n\\n# Run using `nopython` mode to receive a performance boost,\\n# but GIL remains locked due to `nogil=False` by default.\\n@jit(nopython=True)\\ndef numba_gil(n: int) -> int:\\n if n <= 1:\\n return n\\n\\n a = 0\\n b = 1\\n\\n c = a + b\\n for _i in range(2, n):\\n a = b\\n b = c\\n c = a + b\\n\\n return c\\n\\n\\n# Call each function once to force compilation; we don\'t want\\n# the timing statistics to include how long it takes to compile.\\nnumba_nogil(N)\\nnumba_gil(N);\\n```\\n\\nWe\'ll perform the same tests as above; first, figure out how long it takes the function to run:\\n\\n```python\\n%%time\\n_ = numba_gil(N)\\n```\\n\\n> <pre>\\n> CPU times: user 253 ms, sys: 258 \xb5s, total: 253 ms\\n> Wall time: 251 ms\\n> </pre>\\n\\n<small>\\nAside: it\'s not immediately clear why Numba takes ~20% less time to run than Cython for code that should be\\neffectively identical after compilation.\\n</small>\\n\\nWhen running two GIL-locked threads, the result (as expected) takes around twice as long to compute:\\n\\n```python\\n%%time\\nt1 = Thread(target=numba_gil, args=[N])\\nt2 = Thread(target=numba_gil, args=[N])\\nt1.start(); t2.start()\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms\\n> Wall time: 541 ms\\n> </pre>\\n\\nBut if the GIL-unlocking thread starts first, both threads run in parallel:\\n\\n```python\\n%%time\\nt1 = Thread(target=numba_nogil, args=[N])\\nt2 = Thread(target=numba_gil, args=[N])\\nt1.start(); t2.start()\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms\\n> Wall time: 279 ms\\n> </pre>\\n\\nJust like Cython, starting the GIL-locked thread first leads to poor performance:\\n\\n```python\\n%%time\\nt1 = Thread(target=numba_gil, args=[N])\\nt2 = Thread(target=numba_nogil, args=[N])\\nt1.start(); t2.start()\\nt1.join(); t2.join()\\n```\\n\\n> <pre>\\n> CPU times: user 524 ms, sys: 0 ns, total: 524 ms\\n> Wall time: 522 ms\\n> </pre>\\n\\nFinally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired;\\nrecursively calling `@jit(nogil=True)` functions is perfectly safe:\\n\\n```python\\nfrom numba import jit\\n\\n@jit(nopython=True, nogil=True)\\ndef numba_recurse(n: int) -> int:\\n if n <= 0:\\n return 0\\n\\n return numba_recurse(n - 1)\\n\\nnumba_recurse(2);\\n```\\n\\n## Conclusion\\n\\nBefore finishing, it\'s important to address pain points that will show up if these techniques are\\nused in a more realistic project:\\n\\nFirst, code running in a GIL-free context will likely also need non-trivial data structures;\\nGIL-free functions aren\'t useful if they\'re constantly interacting with Python objects whose access\\nrequires the GIL. Cython provides\\n[extension types](http://docs.cython.org/en/latest/src/tutorial/cdef_classes.html) and Numba\\nprovides a [`@jitclass`](https://numba.pydata.org/numba-doc/dev/user/jitclass.html) decorator to\\naddress this need.\\n\\nSecond, building and distributing applications that make use of Cython/Numba can be complicated.\\nCython packages require running the compiler, (potentially) linking/packaging external dependencies,\\nand distributing a binary wheel. Numba is generally simpler because the code being distributed is\\npure Python, but can be tricky since errors aren\'t detected until runtime.\\n\\nFinally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba\\nprovide tools to directly manage the GIL when appropriate. This enables true parallelism (not just\\n[concurrency](https://stackoverflow.com/a/1050257)) that is impossible in vanilla Python."},{"id":"2019/09/binary-format-shootout","metadata":{"permalink":"/2019/09/binary-format-shootout","source":"@site/blog/2019-09-28-binary-format-shootout/index.mdx","title":"Binary format shootout","description":"I\'ve found that in many personal projects,","date":"2019-09-28T12:00:00.000Z","tags":[],"readingTime":8.37,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/09/binary-format-shootout","title":"Binary format shootout","date":"2019-09-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"},"nextItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"}},"content":"I\'ve found that in many personal projects,\\n[analysis paralysis](https://en.wikipedia.org/wiki/Analysis_paralysis) is particularly deadly.\\nMaking good decisions in the beginning avoids pain and suffering later; if extra research prevents\\nfuture problems, I\'m happy to continue ~~procrastinating~~ researching indefinitely.\\n\\nSo let\'s say you\'re in need of a binary serialization format. Data will be going over the network,\\nnot just in memory, so having a schema document and code generation is a must. Performance is\\ncrucial, so formats that support zero-copy de/serialization are given priority. And the more\\nlanguages supported, the better; I use Rust, but can\'t predict what other languages this could\\ninteract with.\\n\\nGiven these requirements, the candidates I could find were:\\n\\n\x3c!-- truncate --\x3e\\n\\n1. [Cap\'n Proto](https://capnproto.org/) has been around the longest, and is the most established\\n2. [Flatbuffers](https://google.github.io/flatbuffers/) is the newest, and claims to have a simpler\\n encoding\\n3. [Simple Binary Encoding](https://github.com/real-logic/simple-binary-encoding) has the simplest\\n encoding, but the Rust implementation is unmaintained\\n\\nAny one of these will satisfy the project requirements: easy to transmit over a network, reasonably\\nfast, and polyglot support. But how do you actually pick one? It\'s impossible to know what issues\\nwill follow that choice, so I tend to avoid commitment until the last possible moment.\\n\\nStill, a choice must be made. Instead of worrying about which is \\"the best,\\" I decided to build a\\nsmall proof-of-concept system in each format and pit them against each other. All code can be found\\nin the [repository](https://github.com/speice-io/marketdata-shootout) for this post.\\n\\nWe\'ll discuss more in detail, but a quick preview of the results:\\n\\n- Cap\'n Proto: Theoretically performs incredibly well, the implementation had issues\\n- Flatbuffers: Has some quirks, but largely lived up to its \\"zero-copy\\" promises\\n- SBE: Best median and worst-case performance, but the message structure has a limited feature set\\n\\n## Prologue: Binary Parsing with Nom\\n\\nOur benchmark system will be a simple data processor; given depth-of-book market data from\\n[IEX](https://iextrading.com/trading/market-data/#deep), serialize each message into the schema\\nformat, read it back, and calculate total size of stock traded and the lowest/highest quoted prices.\\nThis test isn\'t complex, but is representative of the project I need a binary format for.\\n\\nBut before we make it to that point, we have to actually read in the market data. To do so, I\'m\\nusing a library called [`nom`](https://github.com/Geal/nom). Version 5.0 was recently released and\\nbrought some big changes, so this was an opportunity to build a non-trivial program and get\\nfamiliar.\\n\\nIf you don\'t already know about `nom`, it\'s a \\"parser generator\\". By combining different smaller\\nparsers, you can assemble a parser to handle complex structures without writing tedious code by\\nhand. For example, when parsing\\n[PCAP files](https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#rfc.section.3.3):\\n\\n```\\n 0 1 2 3\\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\\n +---------------------------------------------------------------+\\n 0 | Block Type = 0x00000006 |\\n +---------------------------------------------------------------+\\n 4 | Block Total Length |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n 8 | Interface ID |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n12 | Timestamp (High) |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n16 | Timestamp (Low) |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n20 | Captured Len |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n24 | Packet Len |\\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\\n | Packet Data |\\n | ... |\\n```\\n\\n...you can build a parser in `nom` that looks like\\n[this](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/parsers.rs#L59-L93):\\n\\n```rust\\nconst ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];\\npub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> {\\n let (\\n remaining,\\n (\\n block_type,\\n block_len,\\n interface_id,\\n timestamp_high,\\n timestamp_low,\\n captured_len,\\n packet_len,\\n ),\\n ) = tuple((\\n tag(ENHANCED_PACKET),\\n le_u32,\\n le_u32,\\n le_u32,\\n le_u32,\\n le_u32,\\n le_u32,\\n ))(input)?;\\n\\n let (remaining, packet_data) = take(captured_len)(remaining)?;\\n Ok((remaining, packet_data))\\n}\\n```\\n\\nWhile this example isn\'t too interesting, more complex formats (like IEX market data) are where\\n[`nom` really shines](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/iex.rs).\\n\\nUltimately, because the `nom` code in this shootout was the same for all formats, we\'re not too\\ninterested in its performance. Still, it\'s worth mentioning that building the market data parser was\\nactually fun; I didn\'t have to write tons of boring code by hand.\\n\\n## Cap\'n Proto\\n\\nNow it\'s time to get into the meaty part of the story. Cap\'n Proto was the first format I tried\\nbecause of how long it has supported Rust (thanks to [dwrensha](https://github.com/dwrensha) for\\nmaintaining the Rust port since\\n[2014!](https://github.com/capnproto/capnproto-rust/releases/tag/rustc-0.10)). However, I had a ton\\nof performance concerns once I started using it.\\n\\nTo serialize new messages, Cap\'n Proto uses a \\"builder\\" object. This builder allocates memory on the\\nheap to hold the message content, but because builders\\n[can\'t be re-used](https://github.com/capnproto/capnproto-rust/issues/111), we have to allocate a\\nnew buffer for every single message. I was able to work around this with a\\n[special builder](https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/capnp_runner.rs#L17-L51)\\nthat could re-use the buffer, but it required reading through Cap\'n Proto\'s\\n[benchmarks](https://github.com/capnproto/capnproto-rust/blob/master/benchmark/benchmark.rs#L124-L156)\\nto find an example, and used\\n[`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) to bypass Rust\'s borrow\\nchecker.\\n\\nThe process of reading messages was better, but still had issues. Cap\'n Proto has two message\\nencodings: a [\\"packed\\"](https://capnproto.org/encoding.html#packing) representation, and an\\n\\"unpacked\\" version. When reading \\"packed\\" messages, we need a buffer to unpack the message into\\nbefore we can use it; Cap\'n Proto allocates a new buffer for each message we unpack, and I wasn\'t\\nable to figure out a way around that. In contrast, the unpacked message format should be where Cap\'n\\nProto shines; its main selling point is that there\'s [no decoding step](https://capnproto.org/).\\nHowever, accomplishing zero-copy deserialization required code in the private API\\n([since fixed](https://github.com/capnproto/capnproto-rust/issues/148)), and we allocate a vector on\\nevery read for the segment table.\\n\\nIn the end, I put in significant work to make Cap\'n Proto as fast as possible, but there were too\\nmany issues for me to feel comfortable using it long-term.\\n\\n## Flatbuffers\\n\\nThis is the new kid on the block. After a\\n[first attempt](https://github.com/google/flatbuffers/pull/3894) didn\'t pan out, official support\\nwas [recently launched](https://github.com/google/flatbuffers/pull/4898). Flatbuffers intends to\\naddress the same problems as Cap\'n Proto: high-performance, polyglot, binary messaging. The\\ndifference is that Flatbuffers claims to have a simpler wire format and\\n[more flexibility](https://google.github.io/flatbuffers/flatbuffers_benchmarks.html).\\n\\nOn the whole, I enjoyed using Flatbuffers; the [tooling](https://crates.io/crates/flatc-rust) is\\nnice, and unlike Cap\'n Proto, parsing messages was actually zero-copy and zero-allocation. However,\\nthere were still some issues.\\n\\nFirst, Flatbuffers (at least in Rust) can\'t handle nested vectors. This is a problem for formats\\nlike the following:\\n\\n```\\ntable Message {\\n symbol: string;\\n}\\ntable MultiMessage {\\n messages:[Message];\\n}\\n```\\n\\nWe want to create a `MultiMessage` which contains a vector of `Message`, and each `Message` itself\\ncontains a vector (the `string` type). I was able to work around this by\\n[caching `Message` elements](https://github.com/speice-io/marketdata-shootout/blob/e9d07d148bf36a211a6f86802b313c4918377d1b/src/flatbuffers_runner.rs#L83)\\nin a `SmallVec` before building the final `MultiMessage`, but it was a painful process that I\\nbelieve contributed to poor serialization performance.\\n\\nSecond, streaming support in Flatbuffers seems to be something of an\\n[afterthought](https://github.com/google/flatbuffers/issues/3898). Where Cap\'n Proto in Rust handles\\nreading messages from a stream as part of the API, Flatbuffers just sticks a `u32` at the front of\\neach message to indicate the size. Not specifically a problem, but calculating message size without\\nthat tag is nigh on impossible.\\n\\nUltimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform\\nwell.\\n\\n## Simple Binary Encoding\\n\\nSupport for SBE was added by the author of one of my favorite\\n[Rust blog posts](https://web.archive.org/web/20190427124806/https://polysync.io/blog/session-types-for-hearty-codecs/).\\nI\'ve [talked previously](/2019/06/high-performance-systems) about how important\\nvariance is in high-performance systems, so it was encouraging to read about a format that\\n[directly addressed](https://github.com/real-logic/simple-binary-encoding/wiki/Why-Low-Latency) my\\nconcerns. SBE has by far the simplest binary format, but it does make some tradeoffs.\\n\\nBoth Cap\'n Proto and Flatbuffers use [message offsets](https://capnproto.org/encoding.html#structs)\\nto handle variable-length data, [unions](https://capnproto.org/language.html#unions), and various\\nother features. In contrast, messages in SBE are essentially\\n[just structs](https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-samples/src/main/resources/example-schema.xml);\\nvariable-length data is supported, but there\'s no union type.\\n\\nAs mentioned in the beginning, the Rust port of SBE works well, but is\\n[essentially unmaintained](https://users.rust-lang.org/t/zero-cost-abstraction-frontier-no-copy-low-allocation-ordered-decoding/11515/9).\\nHowever, if you don\'t need union types, and can accept that schemas are XML documents, it\'s still\\nworth using. SBE\'s implementation had the best streaming support of all formats I tested, and\\ndoesn\'t trigger allocation during de/serialization.\\n\\n## Results\\n\\nAfter building a test harness\\n[for](https://github.com/speice-io/marketdata-shootout/blob/master/src/capnp_runner.rs)\\n[each](https://github.com/speice-io/marketdata-shootout/blob/master/src/flatbuffers_runner.rs)\\n[format](https://github.com/speice-io/marketdata-shootout/blob/master/src/sbe_runner.rs), it was\\ntime to actually take them for a spin. I used\\n[this script](https://github.com/speice-io/marketdata-shootout/blob/master/run_shootout.sh) to run\\nthe benchmarks, and the raw results are\\n[here](https://github.com/speice-io/marketdata-shootout/blob/master/shootout.csv). All data reported\\nbelow is the average of 10 runs on a single day of IEX data. Results were validated to make sure\\nthat each format parsed the data correctly.\\n\\n### Serialization\\n\\nThis test measures, on a\\n[per-message basis](https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L268-L272),\\nhow long it takes to serialize the IEX message into the desired format and write to a pre-allocated\\nbuffer.\\n\\n| Schema | Median | 99th Pctl | 99.9th Pctl | Total |\\n| :------------------- | :----- | :-------- | :---------- | :----- |\\n| Cap\'n Proto Packed | 413ns | 1751ns | 2943ns | 14.80s |\\n| Cap\'n Proto Unpacked | 273ns | 1828ns | 2836ns | 10.65s |\\n| Flatbuffers | 355ns | 2185ns | 3497ns | 14.31s |\\n| SBE | 91ns | 1535ns | 2423ns | 3.91s |\\n\\n### Deserialization\\n\\nThis test measures, on a\\n[per-message basis](https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L294-L298),\\nhow long it takes to read the previously-serialized message and perform some basic aggregation. The\\naggregation code is the same for each format, so any performance differences are due solely to the\\nformat implementation.\\n\\n| Schema | Median | 99th Pctl | 99.9th Pctl | Total |\\n| :------------------- | :----- | :-------- | :---------- | :----- |\\n| Cap\'n Proto Packed | 539ns | 1216ns | 2599ns | 18.92s |\\n| Cap\'n Proto Unpacked | 366ns | 737ns | 1583ns | 12.32s |\\n| Flatbuffers | 173ns | 421ns | 1007ns | 6.00s |\\n| SBE | 116ns | 286ns | 659ns | 4.05s |\\n\\n## Conclusion\\n\\nBuilding a benchmark turned out to be incredibly helpful in making a decision; because a \\"union\\"\\ntype isn\'t important to me, I can be confident that SBE best addresses my needs.\\n\\nWhile SBE was the fastest in terms of both median and worst-case performance, its worst case\\nperformance was proportionately far higher than any other format. It seems to be that\\nde/serialization time scales with message size, but I\'ll need to do some more research to understand\\nwhat exactly is going on."},{"id":"2019/06/high-performance-systems","metadata":{"permalink":"/2019/06/high-performance-systems","source":"@site/blog/2019-06-31-high-performance-systems/index.mdx","title":"On building high performance systems","description":"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is","date":"2019-07-01T12:00:00.000Z","tags":[],"readingTime":12.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/06/high-performance-systems","title":"On building high performance systems","date":"2019-07-01T12:00:00.000Z","last_updated":{"date":"2019-09-21T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"},"nextItem":{"title":"Making bread","permalink":"/2019/05/making-bread"}},"content":"Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is\\nmade up of people who have access to secret techniques mortal developers could only dream of. There\\nhad to be some secret art that could only be learned if one had an appropriately tragic backstory.\\n\\n\x3c!-- truncate --\x3e\\n\\n![Kung Fu fight](./kung-fu.webp)\\n\\n> How I assumed HFT people learn their secret techniques\\n\\nHow else do you explain people working on systems that complete the round trip of market data in to\\norders out (a.k.a. tick-to-trade) consistently within\\n[750-800 nanoseconds](https://stackoverflow.com/a/22082528/1454178)? In roughly the time it takes a\\ncomputer to access\\n[main memory 8 times](https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html),\\ntrading systems are capable of reading the market data packets, deciding what orders to send, doing\\nrisk checks, creating new packets for exchange-specific protocols, and putting those packets on the\\nwire.\\n\\nHaving now worked in the trading industry, I can confirm the developers aren\'t super-human; I\'ve\\nmade some simple mistakes at the very least. Instead, what shows up in public discussions is that\\nphilosophy, not technique, separates high-performance systems from everything else.\\nPerformance-critical systems don\'t rely on \\"this one cool C++ optimization trick\\" to make code fast\\n(though micro-optimizations have their place); there\'s a lot more to worry about than just the code\\nwritten for the project.\\n\\nThe framework I\'d propose is this: **If you want to build high-performance systems, focus first on\\nreducing performance variance** (reducing the gap between the fastest and slowest runs of the same\\ncode), **and only look at average latency once variance is at an acceptable level**.\\n\\nDon\'t get me wrong, I\'m a much happier person when things are fast. Computer goes from booting in 20\\nseconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes\\na full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a\\nweek is the same in each situation, but you\'re painfully aware of that minute when it happens. When\\nit comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds\\ndoesn\'t mean much if there\'s a 100ms difference between your fastest and slowest runs. When\\nperformance matters, you need to respond quickly _every time_, not just in aggregate.\\nHigh-performance systems should first optimize for time variance. Once you\'re consistent at the time\\nscale you care about, then focus on improving average time.\\n\\nThis focus on variance shows up all the time in industry too (emphasis added in all quotes below):\\n\\n- In [marketing materials](https://business.nasdaq.com/market-tech/marketplaces/trading) for\\n NASDAQ\'s matching engine, the most performance-sensitive component of the exchange, dependability\\n is highlighted in addition to instantaneous metrics:\\n\\n > Able to **consistently sustain** an order rate of over 100,000 orders per second at sub-40\\n > microsecond average latency\\n\\n- The [Aeron](https://github.com/real-logic/aeron) message bus has this to say about performance:\\n\\n > Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and\\n > **most predictable latency possible** of any messaging system\\n\\n- The company PolySync, which is working on autonomous vehicles,\\n [mentions why](https://polysync.io/blog/session-types-for-hearty-codecs/) they picked their\\n specific messaging format:\\n\\n > In general, high performance is almost always desirable for serialization. But in the world of\\n > autonomous vehicles, **steady timing performance is even more important** than peak throughput.\\n > This is because safe operation is sensitive to timing outliers. Nobody wants the system that\\n > decides when to slam on the brakes to occasionally take 100 times longer than usual to encode\\n > its commands.\\n\\n- [Solarflare](https://solarflare.com/), which makes highly-specialized network hardware, points out\\n variance (jitter) as a big concern for\\n [electronic trading](https://solarflare.com/electronic-trading/):\\n > The high stakes world of electronic trading, investment banks, market makers, hedge funds and\\n > exchanges demand the **lowest possible latency and jitter** while utilizing the highest\\n > bandwidth and return on their investment.\\n\\nAnd to further clarify: we\'re not discussing _total run-time_, but variance of total run-time. There\\nare situations where it\'s not reasonably possible to make things faster, and you\'d much rather be\\nconsistent. For example, trading firms use\\n[wireless networks](https://sniperinmahwah.wordpress.com/2017/06/07/network-effects-part-i/) because\\nthe speed of light through air is faster than through fiber-optic cables. There\'s still at _absolute\\nminimum_ a [~33.76 millisecond](http://tinyurl.com/y2vd7tn8) delay required to send data between,\\nsay,\\n[Chicago and Tokyo](https://www.theice.com/market-data/connectivity-and-feeds/wireless/tokyo-chicago).\\nIf a trading system in Chicago calls the function for \\"send order to Tokyo\\" and waits to see if a\\ntrade occurs, there\'s a physical limit to how long that will take. In this situation, the focus is\\non keeping variance of _additional processing_ to a minimum, since speed of light is the limiting\\nfactor.\\n\\nSo how does one go about looking for and eliminating performance variance? To tell the truth, I\\ndon\'t think a systematic answer or flow-chart exists. There\'s no substitute for (A) building a deep\\nunderstanding of the entire technology stack, and (B) actually measuring system performance (though\\n(C) watching a lot of [CppCon](https://www.youtube.com/channel/UCMlGfpWw-RUdWX_JbLCukXg) videos for\\ninspiration never hurt). Even then, every project cares about performance to a different degree; you\\nmay need to build an entire\\n[replica production system](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=3015) to\\naccurately benchmark at nanosecond precision, or you may be content to simply\\n[avoid garbage collection](https://www.youtube.com/watch?v=BD9cRbxWQx8&feature=youtu.be&t=1335) in\\nyour Java code.\\n\\nEven though everyone has different needs, there are still common things to look for when trying to\\nisolate and eliminate variance. In no particular order, these are my focus areas when thinking about\\nhigh-performance systems:\\n\\n**Update 2019-09-21**: Added notes on `isolcpus` and `systemd` affinity.\\n\\n## Language-specific\\n\\n**Garbage Collection**: How often does garbage collection happen? When is it triggered? What are the\\nimpacts?\\n\\n- [In Python](https://rushter.com/blog/python-garbage-collector/), individual objects are collected\\n if the reference count reaches 0, and each generation is collected if\\n `num_alloc - num_dealloc > gc_threshold` whenever an allocation happens. The GIL is acquired for\\n the duration of generational collection.\\n- Java has\\n [many](https://docs.oracle.com/en/java/javase/12/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE)\\n [different](https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573)\\n [collection](https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector-tuning.html#GUID-90E30ACA-8040-432E-B3A0-1E0440AB556A)\\n [algorithms](https://docs.oracle.com/en/java/javase/12/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0)\\n to choose from, each with different characteristics. The default algorithms (Parallel GC in Java\\n 8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms\\n ([ZGC](https://wiki.openjdk.java.net/display/zgc) and\\n [Shenandoah](https://wiki.openjdk.java.net/display/shenandoah)) are designed to keep \\"stop the\\n world\\" to a minimum by doing collection work in parallel.\\n\\n**Allocation**: Every language has a different way of interacting with \\"heap\\" memory, but the\\nprinciple is the same: running the allocator to allocate/deallocate memory takes time that can often\\nbe put to better use. Understanding when your language interacts with the allocator is crucial, and\\nnot always obvious. For example: C++ and Rust don\'t allocate heap memory for iterators, but Java\\ndoes (meaning potential GC pauses). Take time to understand heap behavior (I made a\\n[a guide for Rust](/2019/02/understanding-allocations-in-rust)), and look into alternative\\nallocators ([jemalloc](http://jemalloc.net/),\\n[tcmalloc](https://gperftools.github.io/gperftools/tcmalloc.html)) that might run faster than the\\noperating system default.\\n\\n**Data Layout**: How your data is arranged in memory matters;\\n[data-oriented design](https://www.youtube.com/watch?v=yy8jQgmhbAU) and\\n[cache locality](https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=1185) can have huge\\nimpacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have\\nguarantees about the shape every object takes in memory that others (e.g. Java and Python) can\'t\\nmake. [Cachegrind](http://valgrind.org/docs/manual/cg-manual.html) and kernel\\n[perf](https://perf.wiki.kernel.org/index.php/Main_Page) counters are both great for understanding\\nhow performance relates to memory layout.\\n\\n**Just-In-Time Compilation**: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are\\ngreat because they optimize your program for how it\'s actually being used, rather than how a\\ncompiler expects it to be used. However, there\'s a variance problem if the program stops executing\\nwhile waiting for translation from VM bytecode to native code. As a remedy, many languages support\\nahead-of-time compilation in addition to the JIT versions\\n([CoreRT](https://github.com/dotnet/corert) in C# and [GraalVM](https://www.graalvm.org/) in Java).\\nOn the other hand, LLVM supports\\n[Profile Guided Optimization](https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization),\\nwhich theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing\\napples and oranges during benchmarks; you don\'t want your code to suddenly speed up because the JIT\\ncompiler kicked in.\\n\\n**Programming Tricks**: These won\'t make or break performance, but can be useful in specific\\ncircumstances. For example, C++ can use\\n[templates instead of branches](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=1206)\\nin critical sections.\\n\\n## Kernel\\n\\nCode you wrote is almost certainly not the _only_ code running on your hardware. There are many ways\\nthe operating system interacts with your program, from interrupts to system calls, that are\\nimportant to watch for. These are written from a Linux perspective, but Windows does typically have\\nequivalent functionality.\\n\\n**Scheduling**: The kernel is normally free to schedule any process on any core, so it\'s important\\nto reserve CPU cores exclusively for the important programs. There are a few parts to this: first,\\nlimit the CPU cores that non-critical processes are allowed to run on by excluding cores from\\nscheduling\\n([`isolcpus`](https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re46.html)\\nkernel command-line option), or by setting the `init` process CPU affinity\\n([`systemd` example](https://access.redhat.com/solutions/2884991)). Second, set critical processes\\nto run on the isolated cores by setting the\\n[processor affinity](https://en.wikipedia.org/wiki/Processor_affinity) using\\n[taskset](https://linux.die.net/man/1/taskset). Finally, use\\n[`NO_HZ`](https://github.com/torvalds/linux/blob/master/Documentation/timers/NO_HZ.txt) or\\n[`chrt`](https://linux.die.net/man/1/chrt) to disable scheduling interrupts. Turning off\\nhyper-threading is also likely beneficial.\\n\\n**System calls**: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long\\nthe I/O operation takes, these all trigger expensive\\n[system calls (syscalls)](https://en.wikipedia.org/wiki/System_call). To handle these, the CPU must\\n[context switch](https://en.wikipedia.org/wiki/Context_switch) to the kernel, let the kernel\\noperation complete, then context switch back to your program. We\'d rather keep these\\n[to a minimum](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript) (see\\ntimestamp 18:20). [Strace](https://linux.die.net/man/1/strace) is your friend for understanding when\\nand where syscalls happen.\\n\\n**Signal Handling**: Far less likely to be an issue, but signals do trigger a context switch if your\\ncode has a handler registered. This will be highly dependent on the application, but you can\\n[block signals](https://www.linuxprogrammingblog.com/all-about-linux-signals?page=show#Blocking_signals)\\nif it\'s an issue.\\n\\n**Interrupts**: System interrupts are how devices connected to your computer notify the CPU that\\nsomething has happened. The CPU will then choose a processor core to pause and context switch to the\\nOS to handle the interrupt. Make sure that\\n[SMP affinity](http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux) is\\nset so that interrupts are handled on a CPU core not running the program you care about.\\n\\n**[NUMA](https://www.kernel.org/doc/html/latest/vm/numa.html)**: While NUMA is good at making\\nmulti-cell systems transparent, there are variance implications; if the kernel moves a process\\nacross nodes, future memory accesses must wait for the controller on the original node. Use\\n[numactl](https://linux.die.net/man/8/numactl) to handle memory-/cpu-cell pinning so this doesn\'t\\nhappen.\\n\\n## Hardware\\n\\n**CPU Pipelining/Speculation**: Speculative execution in modern processors gave us vulnerabilities\\nlike Spectre, but it also gave us performance improvements like\\n[branch prediction](https://stackoverflow.com/a/11227902/1454178). And if the CPU mis-speculates\\nyour code, there\'s variance associated with rewind and replay. While the compiler knows a lot about\\nhow your CPU [pipelines instructions](https://youtu.be/nAbCKa0FzjQ?t=4467), code can be\\n[structured to help](https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=755) the branch\\npredictor.\\n\\n**Paging**: For most systems, virtual memory is incredible. Applications live in their own worlds,\\nand the CPU/[MMU](https://en.wikipedia.org/wiki/Memory_management_unit) figures out the details.\\nHowever, there\'s a variance penalty associated with memory paging and caching; if you access more\\nmemory pages than the [TLB](https://en.wikipedia.org/wiki/Translation_lookaside_buffer) can store,\\nyou\'ll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an\\nissue, but using [huge pages](https://blog.pythian.com/performance-tuning-hugepages-in-linux/) can\\nreduce TLB burdens. Alternately, running applications in a hypervisor like\\n[Jailhouse](https://github.com/siemens/jailhouse) allows one to skip virtual memory entirely, but\\nthis is probably more work than the benefits are worth.\\n\\n**Network Interfaces**: When more than one computer is involved, variance can go up dramatically.\\nTuning kernel\\n[network parameters](https://github.com/leandromoreira/linux-network-performance-parameters) may be\\nhelpful, but modern systems more frequently opt to skip the kernel altogether with a technique\\ncalled [kernel bypass](https://blog.cloudflare.com/kernel-bypass/). This typically requires\\nspecialized hardware and [drivers](https://www.openonload.org/), but even industries like\\n[telecom](https://www.bbc.co.uk/rd/blog/2018-04-high-speed-networking-open-source-kernel-bypass) are\\nfinding the benefits.\\n\\n## Networks\\n\\n**Routing**: There\'s a reason financial firms are willing to pay\\n[millions of euros](https://sniperinmahwah.wordpress.com/2019/03/26/4-les-moeres-english-version/)\\nfor rights to a small plot of land - having a straight-line connection from point A to point B means\\nthe path their data takes is the shortest possible. In contrast, there are currently 6 computers in\\nbetween me and Google, but that may change at any moment if my ISP realizes a\\n[more efficient route](https://en.wikipedia.org/wiki/Border_Gateway_Protocol) is available. Whether\\nit\'s using\\n[research-quality equipment](https://sniperinmahwah.wordpress.com/2018/05/07/shortwave-trading-part-i-the-west-chicago-tower-mystery/)\\nfor shortwave radio, or just making sure there\'s no data inadvertently going between data centers,\\nrouting matters.\\n\\n**Protocol**: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control,\\nand congestion control all built in. But these attributes make the most sense when networking\\ninfrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the\\nsetup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may\\nmake sense in these contexts as it avoids the chatter needed to track connection state, and\\n[gap-fill](https://iextrading.com/docs/IEX%20Transport%20Specification.pdf)\\n[strategies](http://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/moldudp64.pdf)\\ncan handle the rest.\\n\\n**Switching**: Many routers/switches handle packets using \\"store-and-forward\\" behavior: wait for the\\nwhole packet, validate checksums, and then send to the next device. In variance terms, the time\\nneeded to move data between two nodes is proportional to the size of that data; the switch must\\n\\"store\\" all data before it can calculate checksums and \\"forward\\" to the next node. With\\n[\\"cut-through\\"](https://www.networkworld.com/article/2241573/latency-and-jitter--cut-through-design-pays-off-for-arista--blade.html)\\ndesigns, switches will begin forwarding data as soon as they know where the destination is,\\nchecksums be damned. This means there\'s a fixed cost (at the switch) for network traffic, no matter\\nthe size.\\n\\n## Final Thoughts\\n\\nHigh-performance systems, regardless of industry, are not magical. They do require extreme precision\\nand attention to detail, but they\'re designed, built, and operated by regular people, using a lot of\\ntools that are publicly available. Interested in seeing how context switching affects performance of\\nyour benchmarks? `taskset` should be installed in all modern Linux distributions, and can be used to\\nmake sure the OS never migrates your process. Curious how often garbage collection triggers during a\\ncrucial operation? Your language of choice will typically expose details of its operations\\n([Python](https://docs.python.org/3/library/gc.html),\\n[Java](https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#DebuggingOptions)).\\nWant to know how hard your program is stressing the TLB? Use `perf record` and look for\\n`dtlb_load_misses.miss_causes_a_walk`.\\n\\nTwo final guiding questions, then: first, before attempting to apply some of the technology above to\\nyour own systems, can you first identify\\n[where/when you care](http://wiki.c2.com/?PrematureOptimization) about \\"high-performance\\"? As an\\nexample, if parts of a system rely on humans pushing buttons, CPU pinning won\'t have any measurable\\neffect. Humans are already far too slow to react in time. Second, if you\'re using benchmarks, are\\nthey being designed in a way that\'s actually helpful? Tools like\\n[Criterion](http://www.serpentine.com/criterion/) (also in\\n[Rust](https://github.com/bheisler/criterion.rs)) and Google\'s\\n[Benchmark](https://github.com/google/benchmark) output not only average run time, but variance as\\nwell; your benchmarking environment is subject to the same concerns your production environment is.\\n\\nFinally, I believe high-performance systems are a matter of philosophy, not necessarily technique.\\nRigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate\\nit; once that\'s at an acceptable level, then optimize for speed."},{"id":"2019/05/making-bread","metadata":{"permalink":"/2019/05/making-bread","source":"@site/blog/2019-05-03-making-bread/index.mdx","title":"Making bread","description":"Having recently started my \\"gardening leave\\" between positions, I have some more personal time","date":"2019-05-03T12:00:00.000Z","tags":[],"readingTime":1.61,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/05/making-bread","title":"Making bread","date":"2019-05-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207625000,"prevItem":{"title":"On building high performance systems","permalink":"/2019/06/high-performance-systems"},"nextItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"}},"content":"Having recently started my \\"gardening leave\\" between positions, I have some more personal time\\navailable. I\'m planning to stay productive, contributing to some open-source projects, but it also\\noccurred to me that despite [talking about](https://speice.io/2018/05/hello.html) bread pics, this\\nblog has been purely technical. Maybe I\'ll change the site title from \\"The Old Speice Guy\\" to \\"Bites\\nand Bytes\\"?\\n\\n\x3c!-- truncate --\x3e\\n\\nEither way, I\'m baking a little bit again, and figured it was worth taking a quick break to focus on\\nsome lighter material. I recently learned two critically important lessons: first, the temperature\\nof the dough when you put the yeast in makes a huge difference.\\n\\nPreviously, when I wasn\'t paying attention to dough temperature:\\n\\n![Whole weat dough](./whole-wheat-not-rising.jpg)\\n\\nCompared with what happens when I put the dough in the microwave for a defrost cycle because the\\nwater I used wasn\'t warm enough:\\n\\n![White dough](./white-dough-rising-before-fold.jpg)\\n\\nI mean, just look at the bubbles!\\n\\n![White dough with bubbles](./white-dough-rising-after-fold.jpg)\\n\\nAfter shaping the dough, I\'ve got two loaves ready:\\n\\n![Shaped loaves](./shaped-loaves.jpg)\\n\\nNow, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from\\ndrying out in the oven. Because I don\'t own a Dutch Oven, I typically put a casserole dish on the\\nbottom rack and fill it with water so there\'s still some moisture in the oven. This time, I forgot\\nto add the water and learned my second lesson: never add room-temperature water to a glass dish\\nthat\'s currently at 500 degrees.\\n\\n![Shattered glass dish](./shattered-glass.jpg)\\n\\nNeedless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected\\nto be doing during my garden leave.\\n\\nIn the end, the bread crust wasn\'t great, but the bread itself turned out pretty alright:\\n\\n![Baked bread](./final-product.jpg)\\n\\nI\'ve been writing a lot more during this break, so I\'m looking forward to sharing that in the\\nfuture. In the mean-time, I\'m planning on making a sandwich."},{"id":"2019/02/summary","metadata":{"permalink":"/2019/02/summary","source":"@site/blog/2019-02-09-summary/index.mdx","title":"Allocations in Rust: Summary","description":"While there\'s a lot of interesting detail captured in this series, it\'s often helpful to have a","date":"2019-02-09T12:00:00.000Z","tags":[],"readingTime":1.095,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/summary","title":"Allocations in Rust: Summary","date":"2019-02-09T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Making bread","permalink":"/2019/05/making-bread"},"nextItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"}},"content":"While there\'s a lot of interesting detail captured in this series, it\'s often helpful to have a\\ndocument that answers some \\"yes/no\\" questions. You may not care about what an `Iterator` looks like\\nin assembly, you just need to know whether it allocates an object on the heap or not. And while Rust\\nwill prioritize the fastest behavior it can, here are the rules for each memory type:\\n\\n\x3c!-- truncate --\x3e\\n\\n**Global Allocation**:\\n\\n- `const` is a fixed value; the compiler is allowed to copy it wherever useful.\\n- `static` is a fixed reference; the compiler will guarantee it is unique.\\n\\n**Stack Allocation**:\\n\\n- Everything not using a smart pointer will be allocated on the stack.\\n- Structs, enums, iterators, arrays, and closures are all stack allocated.\\n- Cell types (`RefCell`) behave like smart pointers, but are stack-allocated.\\n- Inlining (`#[inline]`) will not affect allocation behavior for better or worse.\\n- Types that are marked `Copy` are guaranteed to have their contents stack-allocated.\\n\\n\\n**Heap Allocation**:\\n\\n- Smart pointers (`Box`, `Rc`, `Mutex`, etc.) allocate their contents in heap memory.\\n- Collections (`HashMap`, `Vec`, `String`, etc.) allocate their contents in heap memory.\\n- Some smart pointers in the standard library have counterparts in other crates that don\'t need heap\\n memory. If possible, use those.\\n\\n![Container Sizes in Rust](./container-size.svg)\\n\\n-- [Raph Levien](https://docs.google.com/presentation/d/1q-c7UAyrUlM-eZyTo1pd8SZ0qwA_wYxmPZVOQkoDmH4/edit?usp=sharing)"},{"id":"/2019/02/08/compiler-optimizations","metadata":{"permalink":"/2019/02/08/compiler-optimizations","source":"@site/blog/2019-02-08-compiler-optimizations/index.mdx","title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","tags":[],"readingTime":3.695,"hasTruncateMarker":true,"authors":[],"frontMatter":{"title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","last_updated":{"date":"2019-02-10T12:00:00.000Z"},"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"},"nextItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"}},"content":"Up to this point, we\'ve been discussing memory usage in the Rust language by focusing on simple\\nrules that are mostly right for small chunks of code. We\'ve spent time showing how those rules work\\nthemselves out in practice, and become familiar with reading the assembly code needed to see each\\nmemory type (global, stack, heap) in action.\\n\\nThroughout the series so far, we\'ve put a handicap on the code. In the name of consistent and\\nunderstandable results, we\'ve asked the compiler to pretty please leave the training wheels on. Now\\nis the time where we throw out all the rules and take off the kid gloves. As it turns out, both the\\nRust compiler and the LLVM optimizers are incredibly sophisticated, and we\'ll step back and let them\\ndo their job.\\n\\n\x3c!-- truncate --\x3e\\n\\nSimilar to\\n[\\"What Has My Compiler Done For Me Lately?\\"](https://www.youtube.com/watch?v=bSkpMdDe4g4), we\'re\\nfocusing on interesting things the Rust language (and LLVM!) can do with memory management. We\'ll\\nstill be looking at assembly code to understand what\'s going on, but it\'s important to mention\\nagain: **please use automated tools like [alloc-counter](https://crates.io/crates/alloc_counter) to\\ndouble-check memory behavior if it\'s something you care about**. It\'s far too easy to mis-read\\nassembly in large code sections, you should always verify behavior if you care about memory usage.\\n\\nThe guiding principal as we move forward is this: _optimizing compilers won\'t produce worse programs\\nthan we started with._ There won\'t be any situations where stack allocations get moved to heap\\nallocations. There will, however, be an opera of optimization.\\n\\n**Update 2019-02-10**: When debugging a\\n[related issue](https://gitlab.com/sio4/code/alloc-counter/issues/1), it was discovered that the\\noriginal code worked because LLVM optimized out the entire function, rather than just the allocation\\nsegments. The code has been updated with proper use of\\n[`read_volatile`](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html), and a previous section\\non vector capacity has been removed.\\n\\n## The Case of the Disappearing Box\\n\\nOur first optimization comes when LLVM can reason that the lifetime of an object is sufficiently\\nshort that heap allocations aren\'t necessary. In these cases, LLVM will move the allocation to the\\nstack instead! The way this interacts with `#[inline]` attributes is a bit opaque, but the important\\npart is that LLVM can sometimes do better than the baseline Rust language:\\n\\n```rust\\nuse std::alloc::{GlobalAlloc, Layout, System};\\nuse std::sync::atomic::{AtomicBool, Ordering};\\n\\npub fn cmp(x: u32) {\\n // Turn on panicking if we allocate on the heap\\n DO_PANIC.store(true, Ordering::SeqCst);\\n\\n // The compiler is able to see through the constant `Box`\\n // and directly compare `x` to 24 - assembly line 73\\n let y = Box::new(24);\\n let equals = x == *y;\\n\\n // This call to drop is eliminated\\n drop(y);\\n\\n // Need to mark the comparison result as volatile so that\\n // LLVM doesn\'t strip out all the code. If `y` is marked\\n // volatile instead, allocation will be forced.\\n unsafe { std::ptr::read_volatile(&equals) };\\n\\n // Turn off panicking, as there are some deallocations\\n // when we exit main.\\n DO_PANIC.store(false, Ordering::SeqCst);\\n}\\n\\nfn main() {\\n cmp(12)\\n}\\n\\n#[global_allocator]\\nstatic A: PanicAllocator = PanicAllocator;\\nstatic DO_PANIC: AtomicBool = AtomicBool::new(false);\\nstruct PanicAllocator;\\n\\nunsafe impl GlobalAlloc for PanicAllocator {\\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\\n if DO_PANIC.load(Ordering::SeqCst) {\\n panic!(\\"Unexpected allocation.\\");\\n }\\n System.alloc(layout)\\n }\\n\\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\\n if DO_PANIC.load(Ordering::SeqCst) {\\n panic!(\\"Unexpected deallocation.\\");\\n }\\n System.dealloc(ptr, layout);\\n }\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/BZ_Yp3)\\n\\n-- [Rust Playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4a765f753183d5b919f62c71d2109d5d)\\n\\n## Dr. Array or: how I learned to love the optimizer\\n\\nFinally, this isn\'t so much about LLVM figuring out different memory behavior, but LLVM stripping\\nout code that doesn\'t do anything. Optimizations of this type have a lot of nuance to them; if\\nyou\'re not careful, they can make your benchmarks look\\n[impossibly good](https://www.youtube.com/watch?v=nXaxk27zwlk&feature=youtu.be&t=1199). In Rust, the\\n`black_box` function (implemented in both\\n[`libtest`](https://doc.rust-lang.org/1.1.0/test/fn.black_box.html) and\\n[`criterion`](https://docs.rs/criterion/0.2.10/criterion/fn.black_box.html)) will tell the compiler\\nto disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up\\nrunning programs that previously caused errors:\\n\\n```rust\\n#[derive(Default)]\\nstruct TwoFiftySix {\\n _a: [u64; 32]\\n}\\n\\n#[derive(Default)]\\nstruct EightK {\\n _a: [TwoFiftySix; 32]\\n}\\n\\n#[derive(Default)]\\nstruct TwoFiftySixK {\\n _a: [EightK; 32]\\n}\\n\\n#[derive(Default)]\\nstruct EightM {\\n _a: [TwoFiftySixK; 32]\\n}\\n\\npub fn main() {\\n // Normally this blows up because we can\'t reserve size on stack\\n // for the `EightM` struct. But because the compiler notices we\\n // never do anything with `_x`, it optimizes out the stack storage\\n // and the program completes successfully.\\n let _x = EightM::default();\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/daHn7P)\\n\\n-- [Rust Playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4c253bf26072119896ab93c6ef064dc0)"},{"id":"2019/02/a-heaping-helping","metadata":{"permalink":"/2019/02/a-heaping-helping","source":"@site/blog/2019-02-07-a-heaping-helping/index.mdx","title":"Allocations in Rust: Dynamic memory","description":"Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and","date":"2019-02-07T12:00:00.000Z","tags":[],"readingTime":5.86,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/a-heaping-helping","title":"Allocations in Rust: Dynamic memory","date":"2019-02-07T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"},"nextItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"}},"content":"Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and\\nsome languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how\\nthe language uses dynamic memory (also referred to as the **heap**) is a system called _ownership_.\\nAnd as the docs mention, ownership\\n[is Rust\'s most unique feature](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html).\\n\\nThe heap is used in two situations; when the compiler is unable to predict either the _total size of\\nmemory needed_, or _how long the memory is needed for_, it allocates space in the heap.\\n\\n\x3c!-- truncate --\x3e\\n\\nThis happens\\npretty frequently; if you want to download the Google home page, you won\'t know how large it is\\nuntil your program runs. And when you\'re finished with Google, we deallocate the memory so it can be\\nused to store other webpages. If you\'re interested in a slightly longer explanation of the heap,\\ncheck out\\n[The Stack and the Heap](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#the-stack-and-the-heap)\\nin Rust\'s documentation.\\n\\nWe won\'t go into detail on how the heap is managed; the\\n[ownership documentation](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) does a\\nphenomenal job explaining both the \\"why\\" and \\"how\\" of memory management. Instead, we\'re going to\\nfocus on understanding \\"when\\" heap allocations occur in Rust.\\n\\nTo start off, take a guess for how many allocations happen in the program below:\\n\\n```rust\\nfn main() {}\\n```\\n\\nIt\'s obviously a trick question; while no heap allocations occur as a result of that code, the setup\\nneeded to call `main` does allocate on the heap. Here\'s a way to show it:\\n\\n```rust\\n#![feature(integer_atomics)]\\nuse std::alloc::{GlobalAlloc, Layout, System};\\nuse std::sync::atomic::{AtomicU64, Ordering};\\n\\nstatic ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);\\n\\nstruct CountingAllocator;\\n\\nunsafe impl GlobalAlloc for CountingAllocator {\\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\\n ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst);\\n System.alloc(layout)\\n }\\n\\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\\n System.dealloc(ptr, layout);\\n }\\n}\\n\\n#[global_allocator]\\nstatic A: CountingAllocator = CountingAllocator;\\n\\nfn main() {\\n let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst);\\n println!(\\"There were {} allocations before calling main!\\", x);\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=fb5060025ba79fc0f906b65a4ef8eb8e)\\n\\nAs of the time of writing, there are five allocations that happen before `main` is ever called.\\n\\nBut when we want to understand more practically where heap allocation happens, we\'ll follow this\\nguide:\\n\\n- Smart pointers hold their contents in the heap\\n- Collections are smart pointers for many objects at a time, and reallocate when they need to grow\\n\\nFinally, there are two \\"addendum\\" issues that are important to address when discussing Rust and the\\nheap:\\n\\n- Non-heap alternatives to many standard library types are available.\\n- Special allocators to track memory behavior should be used to benchmark code.\\n\\n## Smart pointers\\n\\nThe first thing to note are the \\"smart pointer\\" types. When you have data that must outlive the\\nscope in which it is declared, or your data is of unknown or dynamic size, you\'ll make use of these\\ntypes.\\n\\nThe term [smart pointer](https://en.wikipedia.org/wiki/Smart_pointer) comes from C++, and while it\'s\\nclosely linked to a general design pattern of\\n[\\"Resource Acquisition Is Initialization\\"](https://en.cppreference.com/w/cpp/language/raii), we\'ll\\nuse it here specifically to describe objects that are responsible for managing ownership of data\\nallocated on the heap. The smart pointers available in the `alloc` crate should look mostly\\nfamiliar:\\n\\n- [`Box`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html)\\n- [`Rc`](https://doc.rust-lang.org/alloc/rc/struct.Rc.html)\\n- [`Arc`](https://doc.rust-lang.org/alloc/sync/struct.Arc.html)\\n- [`Cow`](https://doc.rust-lang.org/alloc/borrow/enum.Cow.html)\\n\\nThe [standard library](https://doc.rust-lang.org/std/) also defines some smart pointers to manage\\nheap objects, though more than can be covered here. Some examples are:\\n\\n- [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html)\\n- [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)\\n\\nFinally, there is one [\\"gotcha\\"](https://www.merriam-webster.com/dictionary/gotcha): **cell types**\\n(like [`RefCell`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html)) look and behave\\nsimilarly, but **don\'t involve heap allocation**. The\\n[`core::cell` docs](https://doc.rust-lang.org/stable/core/cell/index.html) have more information.\\n\\nWhen a smart pointer is created, the data it is given is placed in heap memory and the location of\\nthat data is recorded in the smart pointer. Once the smart pointer has determined it\'s safe to\\ndeallocate that memory (when a `Box` has\\n[gone out of scope](https://doc.rust-lang.org/stable/std/boxed/index.html) or a reference count\\n[goes to zero](https://doc.rust-lang.org/alloc/rc/index.html)), the heap space is reclaimed. We can\\nprove these types use heap memory by looking at code:\\n\\n```rust\\nuse std::rc::Rc;\\nuse std::sync::Arc;\\nuse std::borrow::Cow;\\n\\npub fn my_box() {\\n // Drop at assembly line 1640\\n Box::new(0);\\n}\\n\\npub fn my_rc() {\\n // Drop at assembly line 1650\\n Rc::new(0);\\n}\\n\\npub fn my_arc() {\\n // Drop at assembly line 1660\\n Arc::new(0);\\n}\\n\\npub fn my_cow() {\\n // Drop at assembly line 1672\\n Cow::from(\\"drop\\");\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/4AMQug)\\n\\n## Collections\\n\\nCollection types use heap memory because their contents have dynamic size; they will request more\\nmemory [when needed](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve), and can\\n[release memory](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit) when it\'s\\nno longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In\\na way, **collections are smart pointers for many objects at a time**. Common types that fall under\\nthis umbrella are [`Vec`](https://doc.rust-lang.org/stable/alloc/vec/struct.Vec.html),\\n[`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html), and\\n[`String`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html) (not\\n[`str`](https://doc.rust-lang.org/std/primitive.str.html)).\\n\\nWhile collections store the objects they own in heap memory, _creating new collections will not\\nallocate on the heap_. This is a bit weird; if we call `Vec::new()`, the assembly shows a\\ncorresponding call to `real_drop_in_place`:\\n\\n```rust\\npub fn my_vec() {\\n // Drop in place at line 481\\n Vec::<u8>::new();\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/1WkNtC)\\n\\nBut because the vector has no elements to manage, no calls to the allocator will ever be dispatched:\\n\\n```rust\\nuse std::alloc::{GlobalAlloc, Layout, System};\\nuse std::sync::atomic::{AtomicBool, Ordering};\\n\\nfn main() {\\n // Turn on panicking if we allocate on the heap\\n DO_PANIC.store(true, Ordering::SeqCst);\\n\\n // Interesting bit happens here\\n let x: Vec<u8> = Vec::new();\\n drop(x);\\n\\n // Turn panicking back off, some deallocations occur\\n // after main as well.\\n DO_PANIC.store(false, Ordering::SeqCst);\\n}\\n\\n#[global_allocator]\\nstatic A: PanicAllocator = PanicAllocator;\\nstatic DO_PANIC: AtomicBool = AtomicBool::new(false);\\nstruct PanicAllocator;\\n\\nunsafe impl GlobalAlloc for PanicAllocator {\\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\\n if DO_PANIC.load(Ordering::SeqCst) {\\n panic!(\\"Unexpected allocation.\\");\\n }\\n System.alloc(layout)\\n }\\n\\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\\n if DO_PANIC.load(Ordering::SeqCst) {\\n panic!(\\"Unexpected deallocation.\\");\\n }\\n System.dealloc(ptr, layout);\\n }\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=831a297d176d015b1f9ace01ae416cc6)\\n\\nOther standard library types follow the same behavior; make sure to check out\\n[`HashMap::new()`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.new),\\nand [`String::new()`](https://doc.rust-lang.org/std/string/struct.String.html#method.new).\\n\\n## Heap Alternatives\\n\\nWhile it is a bit strange to speak of the stack after spending time with the heap, it\'s worth\\npointing out that some heap-allocated objects in Rust have stack-based counterparts provided by\\nother crates. If you have need of the functionality, but want to avoid allocating, there are\\ntypically alternatives available.\\n\\nWhen it comes to some standard library smart pointers\\n([`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) and\\n[`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)), stack-based alternatives are\\nprovided in crates like [parking_lot](https://crates.io/crates/parking_lot) and\\n[spin](https://crates.io/crates/spin). You can check out\\n[`lock_api::RwLock`](https://docs.rs/lock_api/0.1.5/lock_api/struct.RwLock.html),\\n[`lock_api::Mutex`](https://docs.rs/lock_api/0.1.5/lock_api/struct.Mutex.html), and\\n[`spin::Once`](https://mvdnes.github.io/rust-docs/spin-rs/spin/struct.Once.html) if you\'re in need\\nof synchronization primitives.\\n\\n[thread_id](https://crates.io/crates/thread-id) may be necessary if you\'re implementing an allocator\\nbecause [`thread::current().id()`](https://doc.rust-lang.org/std/thread/struct.ThreadId.html) uses a\\n[`thread_local!` structure](https://doc.rust-lang.org/stable/src/std/sys_common/thread_info.rs.html#17-36)\\nthat needs heap allocation.\\n\\n## Tracing Allocators\\n\\nWhen writing performance-sensitive code, there\'s no alternative to measuring your code. If you\\ndidn\'t write a benchmark,\\n[you don\'t care about it\'s performance](https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=263)\\nYou should never rely on your instincts when\\n[a microsecond is an eternity](https://www.youtube.com/watch?v=NH1Tta7purM).\\n\\nSimilarly, there\'s great work going on in Rust with allocators that keep track of what they\'re doing\\n(like [`alloc_counter`](https://crates.io/crates/alloc_counter)). When it comes to tracking heap\\nbehavior, it\'s easy to make mistakes; please write tests and make sure you have tools to guard\\nagainst future issues."},{"id":"2019/02/stacking-up","metadata":{"permalink":"/2019/02/stacking-up","source":"@site/blog/2019-02-06-stacking-up/index.mdx","title":"Allocations in Rust: Fixed memory","description":"const and static are perfectly fine, but it\'s relatively rare that we know at compile-time about","date":"2019-02-06T12:00:00.000Z","tags":[],"readingTime":15.165,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/stacking-up","title":"Allocations in Rust: Fixed memory","date":"2019-02-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"},"nextItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"}},"content":"`const` and `static` are perfectly fine, but it\'s relatively rare that we know at compile-time about\\neither values or references that will be the same for the duration of our program. Put another way,\\nit\'s not often the case that either you or your compiler knows how much memory your entire program\\nwill ever need.\\n\\nHowever, there are still some optimizations the compiler can do if it knows how much memory\\nindividual functions will need. Specifically, the compiler can make use of \\"stack\\" memory (as\\nopposed to \\"heap\\" memory) which can be managed far faster in both the short- and long-term.\\n\\n\x3c!-- truncate --\x3e\\n\\nWhen requesting memory, the [`push` instruction](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html)\\ncan typically complete in [1 or 2 cycles](https://agner.org/optimize/instruction_tables.ods) (<1ns\\non modern CPUs). Contrast that to heap memory which requires an allocator (specialized\\nsoftware to track what memory is in use) to reserve space. When you\'re finished with stack memory,\\nthe `pop` instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory\\nfragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have\\nbeen used to design allocators:\\n\\n- [Garbage Collection](<https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)>)\\n strategies like [Tracing](https://en.wikipedia.org/wiki/Tracing_garbage_collection) (used in\\n [Java](https://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html)) and\\n [Reference counting](https://en.wikipedia.org/wiki/Reference_counting) (used in\\n [Python](https://docs.python.org/3/extending/extending.html#reference-counts))\\n- Thread-local structures to prevent locking the allocator in\\n [tcmalloc](https://jamesgolick.com/2013/5/19/how-tcmalloc-works.html)\\n- Arena structures used in [jemalloc](http://jemalloc.net/), which\\n [until recently](https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#jemalloc-is-removed-by-default)\\n was the primary allocator for Rust programs!\\n\\nBut no matter how fast your allocator is, the principle remains: the fastest allocator is the one\\nyou never use. As such, we\'re not going to discuss how exactly the\\n[`push` and `pop` instructions work](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html), but\\nwe\'ll focus instead on the conditions that enable the Rust compiler to use faster stack-based\\nallocation for variables.\\n\\nSo, **how do we know when Rust will or will not use stack allocation for objects we create?**\\nLooking at other languages, it\'s often easy to delineate between stack and heap. Managed memory\\nlanguages (Python, Java,\\n[C#](https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/)) place\\neverything on the heap. JIT compilers ([PyPy](https://www.pypy.org/),\\n[HotSpot](https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html)) may optimize\\nsome heap allocations away, but you should never assume it will happen. C makes things clear with\\ncalls to special functions (like [malloc(3)](https://linux.die.net/man/3/malloc)) needed to access\\nheap memory. Old C++ has the [`new`](https://stackoverflow.com/a/655086/1454178) keyword, though\\nmodern C++/C++11 is more complicated with [RAII](https://en.cppreference.com/w/cpp/language/raii).\\n\\nFor Rust, we can summarize as follows: **stack allocation will be used for everything that doesn\'t\\ninvolve \\"smart pointers\\" and collections**. We\'ll skip over a precise definition of the term \\"smart\\npointer\\" for now, and instead discuss what we should watch for to understand when stack and heap\\nmemory regions are used:\\n\\n1. Stack manipulation instructions (`push`, `pop`, and `add`/`sub` of the `rsp` register) indicate\\n allocation of stack memory:\\n\\n ```rust\\n pub fn stack_alloc(x: u32) -> u32 {\\n // Space for `y` is allocated by subtracting from `rsp`,\\n // and then populated\\n let y = [1u8, 2, 3, 4];\\n // Space for `y` is deallocated by adding back to `rsp`\\n x\\n }\\n ```\\n\\n -- [Compiler Explorer](https://godbolt.org/z/5WSgc9)\\n\\n2. Tracking when exactly heap allocation calls occur is difficult. It\'s typically easier to watch\\n for `call core::ptr::real_drop_in_place`, and infer that a heap allocation happened in the recent\\n past:\\n\\n ```rust\\n pub fn heap_alloc(x: usize) -> usize {\\n // Space for elements in a vector has to be allocated\\n // on the heap, and is then de-allocated once the\\n // vector goes out of scope\\n let y: Vec<u8> = Vec::with_capacity(x);\\n x\\n }\\n ```\\n\\n -- [Compiler Explorer](https://godbolt.org/z/epfgoQ) (`real_drop_in_place` happens on line 1317)\\n <small>Note: While the\\n [`Drop` trait](https://doc.rust-lang.org/std/ops/trait.Drop.html) is\\n [called for stack-allocated objects](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87edf374d8983816eb3d8cfeac657b46),\\n the Rust standard library only defines `Drop` implementations for types that involve heap\\n allocation.</small>\\n\\n3. If you don\'t want to inspect the assembly, use a custom allocator that\'s able to track and alert\\n when heap allocations occur. Crates like\\n [`alloc_counter`](https://crates.io/crates/alloc_counter) are designed for exactly this purpose.\\n\\nWith all that in mind, let\'s talk about situations in which we\'re guaranteed to use stack memory:\\n\\n- Structs are created on the stack.\\n- Function arguments are passed on the stack, meaning the\\n [`#[inline]` attribute](https://doc.rust-lang.org/reference/attributes.html#inline-attribute) will\\n not change the memory region used.\\n- Enums and unions are stack-allocated.\\n- [Arrays](https://doc.rust-lang.org/std/primitive.array.html) are always stack-allocated.\\n- Closures capture their arguments on the stack.\\n- Generics will use stack allocation, even with dynamic dispatch.\\n- [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html) types are guaranteed to be\\n stack-allocated, and copying them will be done in stack memory.\\n- [`Iterator`s](https://doc.rust-lang.org/std/iter/trait.Iterator.html) in the standard library are\\n stack-allocated even when iterating over heap-based collections.\\n\\n## Structs\\n\\nThe simplest case comes first. When creating vanilla `struct` objects, we use stack memory to hold\\ntheir contents:\\n\\n```rust\\nstruct Point {\\n x: u64,\\n y: u64,\\n}\\n\\nstruct Line {\\n a: Point,\\n b: Point,\\n}\\n\\npub fn make_line() {\\n // `origin` is stored in the first 16 bytes of memory\\n // starting at location `rsp`\\n let origin = Point { x: 0, y: 0 };\\n // `point` makes up the next 16 bytes of memory\\n let point = Point { x: 1, y: 2 };\\n\\n // When creating `ray`, we just move the content out of\\n // `origin` and `point` into the next 32 bytes of memory\\n let ray = Line { a: origin, b: point };\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/vri9BE)\\n\\nNote that while some extra-fancy instructions are used for memory manipulation in the assembly, the\\n`sub rsp, 64` instruction indicates we\'re still working with the stack.\\n\\n## Function arguments\\n\\nHave you ever wondered how functions communicate with each other? Like, once the variables are given\\nto you, everything\'s fine. But how do you \\"give\\" those variables to another function? How do you get\\nthe results back afterward? The answer: the compiler arranges memory and assembly instructions using\\na pre-determined [calling convention](http://llvm.org/docs/LangRef.html#calling-conventions). This\\nconvention governs the rules around where arguments needed by a function will be located (either in\\nmemory offsets relative to the stack pointer `rsp`, or in other registers), and where the results\\ncan be found once the function has finished. And when multiple languages agree on what the calling\\nconventions are, you can do things like having [Go call Rust code](https://blog.filippo.io/rustgo/)!\\n\\nPut simply: it\'s the compiler\'s job to figure out how to call other functions, and you can assume\\nthat the compiler is good at its job.\\n\\nWe can see this in action using a simple example:\\n\\n```rust\\nstruct Point {\\n x: i64,\\n y: i64,\\n}\\n\\n// We use integer division operations to keep\\n// the assembly clean, understanding the result\\n// isn\'t accurate.\\nfn distance(a: &Point, b: &Point) -> i64 {\\n // Immediately subtract from `rsp` the bytes needed\\n // to hold all the intermediate results - this is\\n // the stack allocation step\\n\\n // The compiler used the `rdi` and `rsi` registers\\n // to pass our arguments, so read them in\\n let x1 = a.x;\\n let x2 = b.x;\\n let y1 = a.y;\\n let y2 = b.y;\\n\\n // Do the actual math work\\n let x_pow = (x1 - x2) * (x1 - x2);\\n let y_pow = (y1 - y2) * (y1 - y2);\\n let squared = x_pow + y_pow;\\n squared / squared\\n\\n // Our final result will be stored in the `rax` register\\n // so that our caller knows where to retrieve it.\\n // Finally, add back to `rsp` the stack memory that is\\n // now ready to be used by other functions.\\n}\\n\\npub fn total_distance() {\\n let start = Point { x: 1, y: 2 };\\n let middle = Point { x: 3, y: 4 };\\n let end = Point { x: 5, y: 6 };\\n\\n let _dist_1 = distance(&start, &middle);\\n let _dist_2 = distance(&middle, &end);\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/Qmx4ST)\\n\\nAs a consequence of function arguments never using heap memory, we can also infer that functions\\nusing the `#[inline]` attributes also do not heap allocate. But better than inferring, we can look\\nat the assembly to prove it:\\n\\n```rust\\nstruct Point {\\n x: i64,\\n y: i64,\\n}\\n\\n// Note that there is no `distance` function in the assembly output,\\n// and the total line count goes from 229 with inlining off\\n// to 306 with inline on. Even still, no heap allocations occur.\\n#[inline(always)]\\nfn distance(a: &Point, b: &Point) -> i64 {\\n let x1 = a.x;\\n let x2 = b.x;\\n let y1 = a.y;\\n let y2 = b.y;\\n\\n let x_pow = (a.x - b.x) * (a.x - b.x);\\n let y_pow = (a.y - b.y) * (a.y - b.y);\\n let squared = x_pow + y_pow;\\n squared / squared\\n}\\n\\npub fn total_distance() {\\n let start = Point { x: 1, y: 2 };\\n let middle = Point { x: 3, y: 4 };\\n let end = Point { x: 5, y: 6 };\\n\\n let _dist_1 = distance(&start, &middle);\\n let _dist_2 = distance(&middle, &end);\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/30Sh66)\\n\\nFinally, passing by value (arguments with type\\n[`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html)) and passing by reference (either\\nmoving ownership or passing a pointer) may have slightly different layouts in assembly, but will\\nstill use either stack memory or CPU registers:\\n\\n```rust\\npub struct Point {\\n x: i64,\\n y: i64,\\n}\\n\\n// Moving values\\npub fn distance_moved(a: Point, b: Point) -> i64 {\\n let x1 = a.x;\\n let x2 = b.x;\\n let y1 = a.y;\\n let y2 = b.y;\\n\\n let x_pow = (x1 - x2) * (x1 - x2);\\n let y_pow = (y1 - y2) * (y1 - y2);\\n let squared = x_pow + y_pow;\\n squared / squared\\n}\\n\\n// Borrowing values has two extra `mov` instructions on lines 21 and 22\\npub fn distance_borrowed(a: &Point, b: &Point) -> i64 {\\n let x1 = a.x;\\n let x2 = b.x;\\n let y1 = a.y;\\n let y2 = b.y;\\n\\n let x_pow = (x1 - x2) * (x1 - x2);\\n let y_pow = (y1 - y2) * (y1 - y2);\\n let squared = x_pow + y_pow;\\n squared / squared\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/06hGiv)\\n\\n## Enums\\n\\nIf you\'ve ever worried that wrapping your types in\\n[`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) or\\n[`Result`](https://doc.rust-lang.org/stable/core/result/enum.Result.html) would finally make them\\nlarge enough that Rust decides to use heap allocation instead, fear no longer: `enum` and union\\ntypes don\'t use heap allocation:\\n\\n```rust\\nenum MyEnum {\\n Small(u8),\\n Large(u64)\\n}\\n\\nstruct MyStruct {\\n x: MyEnum,\\n y: MyEnum,\\n}\\n\\npub fn enum_compare() {\\n let x = MyEnum::Small(0);\\n let y = MyEnum::Large(0);\\n\\n let z = MyStruct { x, y };\\n\\n let opt = Option::Some(z);\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/HK7zBx)\\n\\nBecause the size of an `enum` is the size of its largest element plus a flag, the compiler can\\npredict how much memory is used no matter which variant of an enum is currently stored in a\\nvariable. Thus, enums and unions have no need of heap allocation. There\'s unfortunately not a great\\nway to show this in assembly, so I\'ll instead point you to the\\n[`core::mem::size_of`](https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums)\\ndocumentation.\\n\\n## Arrays\\n\\nThe array type is guaranteed to be stack allocated, which is why the array size must be declared.\\nInterestingly enough, this can be used to cause safe Rust programs to crash:\\n\\n```rust\\n// 256 bytes\\n#[derive(Default)]\\nstruct TwoFiftySix {\\n _a: [u64; 32]\\n}\\n\\n// 8 kilobytes\\n#[derive(Default)]\\nstruct EightK {\\n _a: [TwoFiftySix; 32]\\n}\\n\\n// 256 kilobytes\\n#[derive(Default)]\\nstruct TwoFiftySixK {\\n _a: [EightK; 32]\\n}\\n\\n// 8 megabytes - exceeds space typically provided for the stack,\\n// though the kernel can be instructed to allocate more.\\n// On Linux, you can check stack size using `ulimit -s`\\n#[derive(Default)]\\nstruct EightM {\\n _a: [TwoFiftySixK; 32]\\n}\\n\\nfn main() {\\n // Because we already have things in stack memory\\n // (like the current function call stack), allocating another\\n // eight megabytes of stack memory crashes the program\\n let _x = EightM::default();\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=587a6380a4914bcbcef4192c90c01dc4)\\n\\nThere aren\'t any security implications of this (no memory corruption occurs), but it\'s good to note\\nthat the Rust compiler won\'t move arrays into heap memory even if they can be reasonably expected to\\noverflow the stack.\\n\\n## Closures\\n\\nRules for how anonymous functions capture their arguments are typically language-specific. In Java,\\n[Lambda Expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) are\\nactually objects created on the heap that capture local primitives by copying, and capture local\\nnon-primitives as (`final`) references.\\n[Python](https://docs.python.org/3.7/reference/expressions.html#lambda) and\\n[JavaScript](https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/)\\nboth bind _everything_ by reference normally, but Python can also\\n[capture values](https://stackoverflow.com/a/235764/1454178) and JavaScript has\\n[Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions).\\n\\nIn Rust, arguments to closures are the same as arguments to other functions; closures are simply\\nfunctions that don\'t have a declared name. Some weird ordering of the stack may be required to\\nhandle them, but it\'s the compiler\'s responsiblity to figure that out.\\n\\nEach example below has the same effect, but a different assembly implementation. In the simplest\\ncase, we immediately run a closure returned by another function. Because we don\'t store a reference\\nto the closure, the stack memory needed to store the captured values is contiguous:\\n\\n```rust\\nfn my_func() -> impl FnOnce() {\\n let x = 24;\\n // Note that this closure in assembly looks exactly like\\n // any other function; you even use the `call` instruction\\n // to start running it.\\n move || { x; }\\n}\\n\\npub fn immediate() {\\n my_func()();\\n my_func()();\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/mgJ2zl), 25 total assembly instructions\\n\\nIf we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory\\nof the original function. Getting the details right is a bit harder, so the instruction count goes\\nup even though this code is functionally equivalent to our original example:\\n\\n```rust\\npub fn simple_reference() {\\n let x = my_func();\\n let y = my_func();\\n y();\\n x();\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/K_dj5n), 55 total assembly instructions\\n\\nEven things like variable order can make a difference in instruction count:\\n\\n```rust\\npub fn complex() {\\n let x = my_func();\\n let y = my_func();\\n x();\\n y();\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/p37qFl), 70 total assembly instructions\\n\\nIn every circumstance though, the compiler ensured that no heap allocations were necessary.\\n\\n## Generics\\n\\nTraits in Rust come in two broad forms: static dispatch (monomorphization, `impl Trait`) and dynamic\\ndispatch (trait objects, `dyn Trait`). While dynamic dispatch is often _associated_ with trait\\nobjects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:\\n\\n```rust\\ntrait GetInt {\\n fn get_int(&self) -> u64;\\n}\\n\\n// vtable stored at section L__unnamed_1\\nstruct WhyNotU8 {\\n x: u8\\n}\\nimpl GetInt for WhyNotU8 {\\n fn get_int(&self) -> u64 {\\n self.x as u64\\n }\\n}\\n\\n// vtable stored at section L__unnamed_2\\nstruct ActualU64 {\\n x: u64\\n}\\nimpl GetInt for ActualU64 {\\n fn get_int(&self) -> u64 {\\n self.x\\n }\\n}\\n\\n// `&dyn` declares that we want to use dynamic dispatch\\n// rather than monomorphization, so there is only one\\n// `retrieve_int` function that shows up in the final assembly.\\n// If we used generics, there would be one implementation of\\n// `retrieve_int` for each type that implements `GetInt`.\\npub fn retrieve_int(u: &dyn GetInt) {\\n // In the assembly, we just call an address given to us\\n // in the `rsi` register and hope that it was set up\\n // correctly when this function was invoked.\\n let x = u.get_int();\\n}\\n\\npub fn do_call() {\\n // Note that even though the vtable for `WhyNotU8` and\\n // `ActualU64` includes a pointer to\\n // `core::ptr::real_drop_in_place`, it is never invoked.\\n let a = WhyNotU8 { x: 0 };\\n let b = ActualU64 { x: 0 };\\n\\n retrieve_int(&a);\\n retrieve_int(&b);\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/u_yguS)\\n\\nIt\'s hard to imagine practical situations where dynamic dispatch would be used for objects that\\naren\'t heap allocated, but it technically can be done.\\n\\n## Copy types\\n\\nUnderstanding move semantics and copy semantics in Rust is weird at first. The Rust docs\\n[go into detail](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html) far better than can\\nbe addressed here, so I\'ll leave them to do the job. From a memory perspective though, their\\nguideline is reasonable:\\n[if your type can implemement `Copy`, it should](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html#when-should-my-type-be-copy).\\nWhile there are potential speed tradeoffs to _benchmark_ when discussing `Copy` (move semantics for\\nstack objects vs. copying stack pointers vs. copying stack `struct`s), _it\'s impossible for `Copy`\\nto introduce a heap allocation_.\\n\\nBut why is this the case? Fundamentally, it\'s because the language controls what `Copy` means -\\n[\\"the behavior of `Copy` is not overloadable\\"](https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone)\\nbecause it\'s a marker trait. From there we\'ll note that a type\\n[can implement `Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html#when-can-my-type-be-copy)\\nif (and only if) its components implement `Copy`, and that\\n[no heap-allocated types implement `Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html#implementors).\\nThus, assignments involving heap types are always move semantics, and new heap allocations won\'t\\noccur because of implicit operator behavior.\\n\\n```rust\\n#[derive(Clone)]\\nstruct Cloneable {\\n x: Box<u64>\\n}\\n\\n// error[E0204]: the trait `Copy` may not be implemented for this type\\n#[derive(Copy, Clone)]\\nstruct NotCopyable {\\n x: Box<u64>\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/VToRuK)\\n\\n## Iterators\\n\\nIn managed memory languages (like\\n[Java](https://www.youtube.com/watch?v=bSkpMdDe4g4&feature=youtu.be&t=357)), there\'s a subtle\\ndifference between these two code samples:\\n\\n```java\\npublic static int sum_for(List<Long> vals) {\\n long sum = 0;\\n // Regular for loop\\n for (int i = 0; i < vals.length; i++) {\\n sum += vals[i];\\n }\\n return sum;\\n}\\n\\npublic static int sum_foreach(List<Long> vals) {\\n long sum = 0;\\n // \\"Foreach\\" loop - uses iteration\\n for (Long l : vals) {\\n sum += l;\\n }\\n return sum;\\n}\\n```\\n\\nIn the `sum_for` function, nothing terribly interesting happens. In `sum_foreach`, an object of type\\n[`Iterator`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html)\\nis allocated on the heap, and will eventually be garbage-collected. This isn\'t a great design;\\niterators are often transient objects that you need during a function and can discard once the\\nfunction ends. Sounds exactly like the issue stack-allocated objects address, no?\\n\\nIn Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in\\nheap memory, but the iterator itself\\n([`Iter`](https://doc.rust-lang.org/std/slice/struct.Iter.html)) doesn\'t need to use the heap. In\\neach of the examples below we iterate over a collection, but never use heap allocation:\\n\\n```rust\\nuse std::collections::HashMap;\\n// There\'s a lot of assembly generated, but if you search in the text,\\n// there are no references to `real_drop_in_place` anywhere.\\n\\npub fn sum_vec(x: &Vec<u32>) {\\n let mut s = 0;\\n // Basic iteration over vectors doesn\'t need allocation\\n for y in x {\\n s += y;\\n }\\n}\\n\\npub fn sum_enumerate(x: &Vec<u32>) {\\n let mut s = 0;\\n // More complex iterators are just fine too\\n for (_i, y) in x.iter().enumerate() {\\n s += y;\\n }\\n}\\n\\npub fn sum_hm(x: &HashMap<u32, u32>) {\\n let mut s = 0;\\n // And it\'s not just Vec, all types will allocate the iterator\\n // on stack memory\\n for y in x.values() {\\n s += y;\\n }\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/FTT3CT)"},{"id":"2019/02/the-whole-world","metadata":{"permalink":"/2019/02/the-whole-world","source":"@site/blog/2019-02-05-the-whole-world/index.mdx","title":"Allocations in Rust: Global memory","description":"The first memory type we\'ll look at is pretty special: when Rust can prove that a value is fixed","date":"2019-02-05T12:00:00.000Z","tags":[],"readingTime":7.485,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/the-whole-world","title":"Allocations in Rust: Global memory","date":"2019-02-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"},"nextItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"}},"content":"The first memory type we\'ll look at is pretty special: when Rust can prove that a _value_ is fixed\\nfor the life of a program (`const`), and when a _reference_ is unique for the life of a program\\n(`static` as a declaration, not\\n[`\'static`](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#the-static-lifetime) as a\\nlifetime), we can make use of global memory. This special section of data is embedded directly in\\nthe program binary so that variables are ready to go once the program loads; no additional\\ncomputation is necessary.\\n\\nUnderstanding the value/reference distinction is important for reasons we\'ll go into below, and\\nwhile the\\n[full specification](https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md) for\\nthese two keywords is available, we\'ll take a hands-on approach to the topic.\\n\\n\x3c!-- truncate --\x3e\\n\\n## `const` values\\n\\nWhen a _value_ is guaranteed to be unchanging in your program (where \\"value\\" may be scalars,\\n`struct`s, etc.), you can declare it `const`. This tells the compiler that it\'s safe to treat the\\nvalue as never changing, and enables some interesting optimizations; not only is there no\\ninitialization cost to creating the value (it is loaded at the same time as the executable parts of\\nyour program), but the compiler can also copy the value around if it speeds up the code.\\n\\nThe points we need to address when talking about `const` are:\\n\\n- `Const` values are stored in read-only memory - it\'s impossible to modify.\\n- Values resulting from calling a `const fn` are materialized at compile-time.\\n- The compiler may (or may not) copy `const` values wherever it chooses.\\n\\n### Read-Only\\n\\nThe first point is a bit strange - \\"read-only memory.\\"\\n[The Rust book](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants)\\nmentions in a couple places that using `mut` with constants is illegal, but it\'s also important to\\ndemonstrate just how immutable they are. _Typically_ in Rust you can use\\n[interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html) to modify\\nthings that aren\'t declared `mut`.\\n[`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) provides an example of this\\npattern in action:\\n\\n```rust\\nuse std::cell::RefCell;\\n\\nfn my_mutator(cell: &RefCell<u8>) {\\n // Even though we\'re given an immutable reference,\\n // the `replace` method allows us to modify the inner value.\\n cell.replace(14);\\n}\\n\\nfn main() {\\n let cell = RefCell::new(25);\\n // Prints out 25\\n println!(\\"Cell: {:?}\\", cell);\\n my_mutator(&cell);\\n // Prints out 14\\n println!(\\"Cell: {:?}\\", cell);\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8e4bea1a718edaff4507944e825a54b2)\\n\\nWhen `const` is involved though, interior mutability is impossible:\\n\\n```rust\\nuse std::cell::RefCell;\\n\\nconst CELL: RefCell<u8> = RefCell::new(25);\\n\\nfn my_mutator(cell: &RefCell<u8>) {\\n cell.replace(14);\\n}\\n\\nfn main() {\\n // First line prints 25 as expected\\n println!(\\"Cell: {:?}\\", &CELL);\\n my_mutator(&CELL);\\n // Second line *still* prints 25\\n println!(\\"Cell: {:?}\\", &CELL);\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88fe98110c33c1b3a51e341f48b8ae00)\\n\\nAnd a second example using [`Once`](https://doc.rust-lang.org/std/sync/struct.Once.html):\\n\\n```rust\\nuse std::sync::Once;\\n\\nconst SURPRISE: Once = Once::new();\\n\\nfn main() {\\n // This is how `Once` is supposed to be used\\n SURPRISE.call_once(|| println!(\\"Initializing...\\"));\\n // Because `Once` is a `const` value, we never record it\\n // having been initialized the first time, and this closure\\n // will also execute.\\n SURPRISE.call_once(|| println!(\\"Initializing again???\\"));\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c3cc5979b5e5434eca0f9ec4a06ee0ed)\\n\\nWhen the\\n[`const` specification](https://github.com/rust-lang/rfcs/blob/26197104b7bb9a5a35db243d639aee6e46d35d75/text/0246-const-vs-static.md)\\nrefers to [\\"rvalues\\"](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf), this\\nbehavior is what they refer to. [Clippy](https://github.com/rust-lang/rust-clippy) will treat this\\nas an error, but it\'s still something to be aware of.\\n\\n### Initialization\\n\\nThe next thing to mention is that `const` values are loaded into memory _as part of your program\\nbinary_. Because of this, any `const` values declared in your program will be \\"realized\\" at\\ncompile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may\\nbe able to prefetch the value), but that\'s it.\\n\\n```rust\\nuse std::cell::RefCell;\\n\\nconst CELL: RefCell<u32> = RefCell::new(24);\\n\\npub fn multiply(value: u32) -> u32 {\\n // CELL is stored at `.L__unnamed_1`\\n value * (*CELL.get_mut())\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/Th8boO)\\n\\nThe compiler creates one `RefCell`, uses it everywhere, and never needs to call the `RefCell::new`\\nfunction.\\n\\n### Copying\\n\\nIf it\'s helpful though, the compiler can choose to copy `const` values.\\n\\n```rust\\nconst FACTOR: u32 = 1000;\\n\\npub fn multiply(value: u32) -> u32 {\\n // See assembly line 4 for the `mov edi, 1000` instruction\\n value * FACTOR\\n}\\n\\npub fn multiply_twice(value: u32) -> u32 {\\n // See assembly lines 22 and 29 for `mov edi, 1000` instructions\\n value * FACTOR * FACTOR\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/ZtS54X)\\n\\nIn this example, the `FACTOR` value is turned into the `mov edi, 1000` instruction in both the\\n`multiply` and `multiply_twice` functions; the \\"1000\\" value is never \\"stored\\" anywhere, as it\'s\\nsmall enough to inline into the assembly instructions.\\n\\nFinally, getting the address of a `const` value is possible, but not guaranteed to be unique\\n(because the compiler can choose to copy values). I was unable to get non-unique pointers in my\\ntesting (even using different crates), but the specifications are clear enough: _don\'t rely on\\npointers to `const` values being consistent_. To be frank, caring about locations for `const` values\\nis almost certainly a code smell.\\n\\n## `static` values\\n\\nStatic variables are related to `const` variables, but take a slightly different approach. When we\\ndeclare that a _reference_ is unique for the life of a program, you have a `static` variable\\n(unrelated to the `\'static` lifetime). Because of the reference/value distinction with\\n`const`/`static`, static variables behave much more like typical \\"global\\" variables.\\n\\nBut to understand `static`, here\'s what we\'ll look at:\\n\\n- `static` variables are globally unique locations in memory.\\n- Like `const`, `static` variables are loaded at the same time as your program being read into\\n memory.\\n- All `static` variables must implement the\\n [`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html) marker trait.\\n- Interior mutability is safe and acceptable when using `static` variables.\\n\\n### Memory Uniqueness\\n\\nThe single biggest difference between `const` and `static` is the guarantees provided about\\nuniqueness. Where `const` variables may or may not be copied in code, `static` variables are\\nguarantee to be unique. If we take a previous `const` example and change it to `static`, the\\ndifference should be clear:\\n\\n```rust\\nstatic FACTOR: u32 = 1000;\\n\\npub fn multiply(value: u32) -> u32 {\\n // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used\\n value * FACTOR\\n}\\n\\npub fn multiply_twice(value: u32) -> u32 {\\n // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used\\n value * FACTOR * FACTOR\\n}\\n```\\n\\n-- [Compiler Explorer](https://godbolt.org/z/uxmiRQ)\\n\\nWhere [previously](#copying) there were plenty of references to multiplying by 1000, the new\\nassembly refers to `FACTOR` as a named memory location instead. No initialization work needs to be\\ndone, but the compiler can no longer prove the value never changes during execution.\\n\\n### Initialization\\n\\nNext, let\'s talk about initialization. The simplest case is initializing static variables with\\neither scalar or struct notation:\\n\\n```rust\\n#[derive(Debug)]\\nstruct MyStruct {\\n x: u32\\n}\\n\\nstatic MY_STRUCT: MyStruct = MyStruct {\\n // You can even reference other statics\\n // declared later\\n x: MY_VAL\\n};\\n\\nstatic MY_VAL: u32 = 24;\\n\\nfn main() {\\n println!(\\"Static MyStruct: {:?}\\", MY_STRUCT);\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b538dbc46076f12db047af4f4403ee6e)\\n\\nThings can get a bit weirder when using `const fn` though. In most cases, it just works:\\n\\n```rust\\n#[derive(Debug)]\\nstruct MyStruct {\\n x: u32\\n}\\n\\nimpl MyStruct {\\n const fn new() -> MyStruct {\\n MyStruct { x: 24 }\\n }\\n}\\n\\nstatic MY_STRUCT: MyStruct = MyStruct::new();\\n\\nfn main() {\\n println!(\\"const fn Static MyStruct: {:?}\\", MY_STRUCT);\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8c796a6e7fc273c12115091b707b0255)\\n\\nHowever, there\'s a caveat: you\'re currently not allowed to use `const fn` to initialize static\\nvariables of types that aren\'t marked `Sync`. For example,\\n[`RefCell::new()`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.new) is a\\n`const fn`, but because\\n[`RefCell` isn\'t `Sync`](https://doc.rust-lang.org/std/cell/struct.RefCell.html#impl-Sync), you\'ll\\nget an error at compile time:\\n\\n```rust\\nuse std::cell::RefCell;\\n\\n// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely\\nstatic MY_LOCK: RefCell<u8> = RefCell::new(0);\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c76ef86e473d07117a1700e21fd45560)\\n\\nIt\'s likely that this will\\n[change in the future](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md) though.\\n\\n### The `Sync` marker\\n\\nWhich leads well to the next point: static variable types must implement the\\n[`Sync` marker](https://doc.rust-lang.org/std/marker/trait.Sync.html). Because they\'re globally\\nunique, it must be safe for you to access static variables from any thread at any time. Most\\n`struct` definitions automatically implement the `Sync` trait because they contain only elements\\nwhich themselves implement `Sync` (read more in the\\n[Nomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html)). This is why earlier examples could\\nget away with initializing statics, even though we never included an `impl Sync for MyStruct` in the\\ncode. To demonstrate this property, Rust refuses to compile our earlier example if we add a\\nnon-`Sync` element to the `struct` definition:\\n\\n```rust\\nuse std::cell::RefCell;\\n\\nstruct MyStruct {\\n x: u32,\\n y: RefCell<u8>,\\n}\\n\\n// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely\\nstatic MY_STRUCT: MyStruct = MyStruct {\\n x: 8,\\n y: RefCell::new(8)\\n};\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=40074d0248f056c296b662dbbff97cfc)\\n\\n### Interior mutability\\n\\nFinally, while `static mut` variables are allowed, mutating them is an `unsafe` operation. If we\\nwant to stay in `safe` Rust, we can use interior mutability to accomplish similar goals:\\n\\n```rust\\nuse std::sync::Once;\\n\\n// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once\\nstatic INIT: Once = Once::new();\\n\\nfn main() {\\n // Note that while `INIT` is declared immutable, we\'re still allowed\\n // to mutate its interior\\n INIT.call_once(|| println!(\\"Initializing...\\"));\\n // This code won\'t panic, as the interior of INIT was modified\\n // as part of the previous `call_once`\\n INIT.call_once(|| panic!(\\"INIT was called twice!\\"));\\n}\\n```\\n\\n--\\n[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3ba003a981a7ed7400240caadd384d59)"},{"id":"2019/02/understanding-allocations-in-rust","metadata":{"permalink":"/2019/02/understanding-allocations-in-rust","source":"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx","title":"Allocations in Rust: Foreword","description":"There\'s an alchemy of distilling complex technical topics into articles and videos that change the","date":"2019-02-04T12:00:00.000Z","tags":[],"readingTime":3.785,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/understanding-allocations-in-rust","title":"Allocations in Rust: Foreword","date":"2019-02-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"},"nextItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"}},"content":"There\'s an alchemy of distilling complex technical topics into articles and videos that change the\\nway programmers see the tools they interact with on a regular basis. I knew what a linker was, but\\nthere\'s a staggering amount of complexity in between\\n[the OS and `main()`](https://www.youtube.com/watch?v=dOfucXtyEsU). Rust programmers use the\\n[`Box`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html) type all the time, but there\'s a\\nrich history of the Rust language itself wrapped up in\\n[how special it is](https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/).\\n\\nIn a similar vein, this series attempts to look at code and understand how memory is used; the\\ncomplex choreography of operating system, compiler, and program that frees you to focus on\\nfunctionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the\\ncognitive burden associated with memory management, but we\'re going to step into its world for a\\nwhile.\\n\\nLet\'s learn a bit about memory in Rust.\\n\\n\x3c!-- truncate --\x3e\\n\\n---\\n\\nRust\'s three defining features of\\n[Performance, Reliability, and Productivity](https://www.rust-lang.org/) are all driven to a great\\ndegree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java,\\nPython), Rust\\n[doesn\'t really](https://words.steveklabnik.com/borrow-checking-escape-analysis-and-the-generational-hypothesis)\\ngarbage collect; instead, it uses an\\n[ownership](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html) system to reason about\\nhow long objects will last in your program. In some cases, if the life of an object is fairly\\ntransient, Rust can make use of a very fast region called the \\"stack.\\" When that\'s not possible,\\nRust uses\\n[dynamic (heap) memory](https://en.wikipedia.org/wiki/Memory_management#Dynamic_memory_allocation)\\nand the ownership system to ensure you can\'t accidentally corrupt memory. It\'s not as fast, but it\\nis important to have available.\\n\\nThat said, there are specific situations in Rust where you\'d never need to worry about the\\nstack/heap distinction! If you:\\n\\n1. Never use `unsafe`\\n2. Never use `#![feature(alloc)]` or the [`alloc` crate](https://doc.rust-lang.org/alloc/index.html)\\n\\n...then it\'s not possible for you to use dynamic memory!\\n\\nFor some uses of Rust, typically embedded devices, these constraints are OK. They have very limited\\nmemory, and the program binary size itself may significantly affect what\'s available! There\'s no\\noperating system able to manage this\\n[\\"virtual memory\\"](https://en.wikipedia.org/wiki/Virtual_memory) thing, but that\'s not an issue\\nbecause there\'s only one running application. The\\n[embedonomicon](https://docs.rust-embedded.org/embedonomicon/preface.html) is ever in mind, and\\ninteracting with the \\"real world\\" through extra peripherals is accomplished by reading and writing\\nto [specific memory addresses](https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-gpio-mem.html).\\n\\nMost Rust programs find these requirements overly burdensome though. C++ developers would struggle\\nwithout access to [`std::vector`](https://en.cppreference.com/w/cpp/container/vector) (except those\\nhardcore no-STL people), and Rust developers would struggle without\\n[`std::vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). But with the constraints above,\\n`std::vec` is actually a part of the\\n[`alloc` crate](https://doc.rust-lang.org/alloc/vec/struct.Vec.html), and thus off-limits. `Box`,\\n`Rc`, etc., are also unusable for the same reason.\\n\\nWhether writing code for embedded devices or not, the important thing in both situations is how much\\nyou know _before your application starts_ about what its memory usage will look like. In embedded\\ndevices, there\'s a small, fixed amount of memory to use. In a browser, you have no idea how large\\n[google.com](https://www.google.com)\'s home page is until you start trying to download it. The\\ncompiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code\\nruns faster when the compiler can guarantee exactly how much memory your program needs while it\'s\\nrunning. This series is all about understanding how the compiler reasons about your program, with an\\nemphasis on the implications for performance.\\n\\nNow let\'s address some conditions and caveats before going much further:\\n\\n- We\'ll focus on \\"safe\\" Rust only; `unsafe` lets you use platform-specific allocation API\'s\\n ([`malloc`](https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm)) that we\'ll\\n ignore.\\n- We\'ll assume a \\"debug\\" build of Rust code (what you get with `cargo run` and `cargo test`) and\\n address (pun intended) release mode at the end (`cargo run --release` and `cargo test --release`).\\n- All content will be run using Rust 1.32, as that\'s the highest currently supported in the\\n [Compiler Exporer](https://godbolt.org/). As such, we\'ll avoid upcoming innovations like\\n [compile-time evaluation of `static`](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)\\n that are available in nightly.\\n- Because of the nature of the content, being able to read assembly is helpful. We\'ll keep it\\n simple, but I [found](https://stackoverflow.com/a/4584131/1454178) a\\n [refresher](https://stackoverflow.com/a/26026278/1454178) on the `push` and `pop`\\n [instructions](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html) was helpful while writing\\n this.\\n- I\'ve tried to be precise in saying only what I can prove using the tools (ASM, docs) that are\\n available, but if there\'s something said in error it will be corrected expeditiously. Please let\\n me know at [bradlee@speice.io](mailto:bradlee@speice.io)\\n\\nFinally, I\'ll do what I can to flag potential future changes but the Rust docs have a notice worth\\nrepeating:\\n\\n> Rust does not currently have a rigorously and formally defined memory model.\\n>\\n> -- [the docs](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html)"},{"id":"2018/12/allocation-safety","metadata":{"permalink":"/2018/12/allocation-safety","source":"@site/blog/2018-12-15-allocation-safety/index.mdx","title":"QADAPT - debug_assert! for allocations","description":"I think it\'s part of the human condition to ignore perfectly good advice when it comes our way. A","date":"2018-12-15T12:00:00.000Z","tags":[],"readingTime":4.775,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/allocation-safety","title":"QADAPT - debug_assert! for allocations","date":"2018-12-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"},"nextItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"}},"content":"I think it\'s part of the human condition to ignore perfectly good advice when it comes our way. A\\nbit over a month ago, I was dispensing sage wisdom for the ages:\\n\\n> I had a really great idea: build a custom allocator that allows you to track your own allocations.\\n> I gave it a shot, but learned very quickly: **never write your own allocator.**\\n>\\n> -- [me](/2018/10/case-study-optimization)\\n\\nI proceeded to ignore it, because we never really learn from our mistakes.\\n\\n\x3c!-- truncate --\x3e\\n\\nThere\'s another part of the human condition that derives joy from seeing things explode.\\n\\n<center>\\n![Explosions](./watch-the-world-burn.webp)\\n</center>\\n\\nAnd _that\'s_ the part I\'m going to focus on.\\n\\n## Why an Allocator?\\n\\nSo why, after complaining about allocators, would I still want to write one? There are three reasons\\nfor that:\\n\\n1. Allocation/dropping is slow\\n2. It\'s difficult to know exactly when Rust will allocate or drop, especially when using code that\\n you did not write\\n3. I want automated tools to verify behavior, instead of inspecting by hand\\n\\nWhen I say \\"slow,\\" it\'s important to define the terms. If you\'re writing web applications, you\'ll\\nspend orders of magnitude more time waiting for the database than you will the allocator. However,\\nthere\'s still plenty of code where micro- or nano-seconds matter; think\\n[finance](https://www.youtube.com/watch?v=NH1Tta7purM),\\n[real-time audio](https://www.reddit.com/r/rust/comments/9hg7yj/synthesizer_progress_update/e6c291f),\\n[self-driving cars](https://polysync.io/blog/session-types-for-hearty-codecs/), and\\n[networking](https://carllerche.github.io/bytes/bytes/index.html). In these situations it\'s simply\\nunacceptable for you to spend time doing things that are not your program, and waiting on the\\nallocator is not cool.\\n\\nAs I continue to learn Rust, it\'s difficult for me to predict where exactly allocations will happen.\\nSo, I propose we play a quick trivia game: **Does this code invoke the allocator?**\\n\\n### Example 1\\n\\n```rust\\nfn my_function() {\\n let v: Vec<u8> = Vec::new();\\n}\\n```\\n\\n**No**: Rust [knows how big](https://doc.rust-lang.org/std/mem/fn.size_of.html) the `Vec` type is,\\nand reserves a fixed amount of memory on the stack for the `v` vector. However, if we wanted to\\nreserve extra space (using `Vec::with_capacity`) the allocator would get invoked.\\n\\n### Example 2\\n\\n```rust\\nfn my_function() {\\n let v: Box<Vec<u8>> = Box::new(Vec::new());\\n}\\n```\\n\\n**Yes**: Because Boxes allow us to work with things that are of unknown size, it has to allocate on\\nthe heap. While the `Box` is unnecessary in this snippet (release builds will optimize out the\\nallocation), reserving heap space more generally is needed to pass a dynamically sized type to\\nanother function.\\n\\n### Example 3\\n\\n```rust\\nfn my_function(v: Vec<u8>) {\\n v.push(5);\\n}\\n```\\n\\n**Maybe**: Depending on whether the Vector we were given has space available, we may or may not\\nallocate. Especially when dealing with code that you did not author, it\'s difficult to verify that\\nthings behave as you expect them to.\\n\\n## Blowing Things Up\\n\\nSo, how exactly does QADAPT solve these problems? **Whenever an allocation or drop occurs in code\\nmarked allocation-safe, QADAPT triggers a thread panic.** We don\'t want to let the program continue\\nas if nothing strange happened, _we want things to explode_.\\n\\nHowever, you don\'t want code to panic in production because of circumstances you didn\'t predict.\\nJust like [`debug_assert!`](https://doc.rust-lang.org/std/macro.debug_assert.html), **QADAPT will\\nstrip out its own code when building in release mode to guarantee no panics and no performance\\nimpact.**\\n\\nFinally, there are three ways to have QADAPT check that your code will not invoke the allocator:\\n\\n### Using a procedural macro\\n\\nThe easiest method, watch an entire function for allocator invocation:\\n\\n```rust\\nuse qadapt::no_alloc;\\nuse qadapt::QADAPT;\\n\\n#[global_allocator]\\nstatic Q: QADAPT = QADAPT;\\n\\n#[no_alloc]\\nfn push_vec(v: &mut Vec<u8>) {\\n // This triggers a panic if v.len() == v.capacity()\\n v.push(5);\\n}\\n\\nfn main() {\\n let v = Vec::with_capacity(1);\\n\\n // This will *not* trigger a panic\\n push_vec(&v);\\n\\n // This *will* trigger a panic\\n push_vec(&v);\\n}\\n```\\n\\n### Using a regular macro\\n\\nFor times when you need more precision:\\n\\n```rust\\nuse qadapt::assert_no_alloc;\\nuse qadapt::QADAPT;\\n\\n#[global_allocator]\\nstatic Q: QADAPT = QADAPT;\\n\\nfn main() {\\n let v = Vec::with_capacity(1);\\n\\n // No allocations here, we already have space reserved\\n assert_no_alloc!(v.push(5));\\n\\n // Even though we remove an item, it doesn\'t trigger a drop\\n // because it\'s a scalar. If it were a `Box<_>` type,\\n // a drop would trigger.\\n assert_no_alloc!({\\n v.pop().unwrap();\\n });\\n}\\n```\\n\\n### Using function calls\\n\\nBoth the most precise and most tedious:\\n\\n```rust\\nuse qadapt::enter_protected;\\nuse qadapt::exit_protected;\\nuse qadapt::QADAPT;\\n\\n#[global_allocator]\\nstatic Q: QADAPT = QADAPT;\\n\\nfn main() {\\n // This triggers an allocation (on non-release builds)\\n let v = Vec::with_capacity(1);\\n\\n enter_protected();\\n // This does not trigger an allocation because we\'ve reserved size\\n v.push(0);\\n exit_protected();\\n\\n // This triggers an allocation because we ran out of size,\\n // but doesn\'t panic because we\'re no longer protected.\\n v.push(1);\\n}\\n```\\n\\n### Caveats\\n\\nIt\'s important to point out that QADAPT code is synchronous, so please be careful when mixing in\\nasynchronous functions:\\n\\n```rust\\nuse futures::future::Future;\\nuse futures::future::ok;\\n\\n#[no_alloc]\\nfn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> {\\n ok(12).and_then(|e| Ok(Vec::with_capacity(e)))\\n}\\n\\nfn main() {\\n // This doesn\'t trigger a panic because the `and_then` closure\\n // wasn\'t run during the function call.\\n async_capacity();\\n\\n // Still no panic\\n assert_no_alloc!(async_capacity());\\n\\n // This will panic because the allocation happens during `unwrap`\\n // in the `assert_no_alloc!` macro\\n assert_no_alloc!(async_capacity().poll().unwrap());\\n}\\n```\\n\\n## Conclusion\\n\\nWhile there\'s a lot more to writing high-performance code than managing your usage of the allocator,\\nit\'s critical that you do use the allocator correctly. QADAPT will verify that your code is doing\\nwhat you expect. It\'s usable even on stable Rust from version 1.31 onward, which isn\'t the case for\\nmost allocators. Version 1.0 was released today, and you can check it out over at\\n[crates.io](https://crates.io/crates/qadapt) or on [github](https://github.com/bspeice/qadapt).\\n\\nI\'m hoping to write more about high-performance Rust in the future, and I expect that QADAPT will\\nhelp guide that. If there are topics you\'re interested in, let me know in the comments below!\\n\\n[qadapt]: https://crates.io/crates/qadapt"},{"id":"2018/12/what-small-business-really-means","metadata":{"permalink":"/2018/12/what-small-business-really-means","source":"@site/blog/2018-12-04-what-small-business-really-means/index.mdx","title":"More \\"what companies really mean\\"","description":"I recently stumbled across a phenomenal small article entitled","date":"2018-12-04T12:00:00.000Z","tags":[],"readingTime":1.205,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/what-small-business-really-means","title":"More \\"what companies really mean\\"","date":"2018-12-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731190109000,"prevItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"},"nextItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"}},"content":"I recently stumbled across a phenomenal small article entitled\\n[What Startups Really Mean By \\"Why Should We Hire You?\\"](https://angel.co/blog/what-startups-really-mean-by-why-should-we-hire-you).\\nHaving been interviewed by smaller companies (though not exactly startups), the questions and\\nsubtexts are the same. There\'s often a question behind the question that you\'re actually trying to\\nanswer, and I wish I spotted the nuance earlier in my career.\\n\\nLet me also make note of one more question/euphemism I\'ve come across:\\n\\n\x3c!-- truncate --\x3e\\n\\n## How do you feel about production support?\\n\\n**Translation**: _We\'re a fairly small team, and when things break on an evening/weekend/Christmas\\nDay, can we call on you to be there?_\\n\\nI\'ve met decidedly few people in my life who truly enjoy the \\"ops\\" side of \\"devops\\". They\'re\\nincredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning\\nthat into a functioning system at the end. And if they all left for lunch, we probably wouldn\'t make\\nit out the door before the zombie apocalypse.\\n\\nLarger organizations (in my experience, 500+ person organizations) have the luxury of hiring people\\nwho either enjoy that, or play along nicely enough that our systems keep working.\\n\\nSmall teams have no such luck. If you\'re interviewing at a small company, especially as a \\"data\\nscientist\\" or other somesuch position, be aware that systems can and do spontaneously combust at the\\nmost inopportune moments.\\n\\n**Terrible-but-popular answers include**: _It\'s a part of the job, and I\'m happy to contribute._"},{"id":"2018/10/case-study-optimization","metadata":{"permalink":"/2018/10/case-study-optimization","source":"@site/blog/2018-10-08-case-study-optimization/index.mdx","title":"A case study in heaptrack","description":"I remember early in my career someone joking that:","date":"2018-10-08T12:00:00.000Z","tags":[],"readingTime":4.26,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/10/case-study-optimization","title":"A case study in heaptrack","date":"2018-10-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731189722000,"prevItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"},"nextItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"}},"content":"I remember early in my career someone joking that:\\n\\n> Programmers have it too easy these days. They should learn to develop in low memory environments\\n> and be more efficient.\\n\\n...though it\'s not like the first code I wrote was for a\\n[graphing calculator](https://web.archive.org/web/20180924060530/https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-se)\\npacking a whole 24KB of RAM.\\n\\nBut the principle remains: be efficient with the resources you have, because\\n[what Intel giveth, Microsoft taketh away](http://exo-blog.blogspot.com/2007/09/what-intel-giveth-microsoft-taketh-away.html).\\n\\n\x3c!-- truncate --\x3e\\n\\nMy professional work is focused on this kind of efficiency; low-latency financial markets demand\\nthat you understand at a deep level _exactly_ what your code is doing. As I continue experimenting\\nwith Rust for personal projects, it\'s exciting to bring a utilitarian mindset with me: there\'s\\nflexibility for the times I pretend to have a garbage collector, and flexibility for the times that\\nI really care about how memory is used.\\n\\nThis post is a (small) case study in how I went from the former to the latter. And ultimately, it\'s\\nintended to be a starting toolkit to empower analysis of your own code.\\n\\n## Curiosity\\n\\nWhen I first started building the [dtparse] crate, my intention was to mirror as closely as possible\\nthe equivalent [Python library][dateutil]. Python, as you may know, is garbage collected. Very\\nrarely is memory usage considered in Python, and I likewise wasn\'t paying too much attention when\\n`dtparse` was first being built.\\n\\nThis lackadaisical approach to memory works well enough, and I\'m not planning on making `dtparse`\\nhyper-efficient. But every so often, I\'ve wondered: \\"what exactly is going on in memory?\\" With the\\nadvent of Rust 1.28 and the\\n[Global Allocator trait](https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html), I had a really\\ngreat idea: _build a custom allocator that allows you to track your own allocations._ That way, you\\ncan do things like writing tests for both correct results and correct memory usage. I gave it a\\n[shot][qadapt], but learned very quickly: **never write your own allocator**. It went from \\"fun\\nweekend project\\" to \\"I have literally no idea what my computer is doing\\" at breakneck speed.\\n\\nInstead, I\'ll highlight a separate path I took to make sense of my memory usage: [heaptrack].\\n\\n## Turning on the System Allocator\\n\\nThis is the hardest part of the post. Because Rust uses\\n[its own allocator](https://github.com/rust-lang/rust/pull/27400#issue-41256384) by default,\\n`heaptrack` is unable to properly record unmodified Rust code. To remedy this, we\'ll make use of the\\n`#[global_allocator]` attribute.\\n\\nSpecifically, in `lib.rs` or `main.rs`, add this:\\n\\n```rust\\nuse std::alloc::System;\\n\\n#[global_allocator]\\nstatic GLOBAL: System = System;\\n```\\n\\n...and that\'s it. Everything else comes essentially for free.\\n\\n## Running heaptrack\\n\\nAssuming you\'ve installed heaptrack <small>(Homebrew in Mac, package manager\\nin Linux, ??? in Windows)</small>, all that\'s left is to fire up your application:\\n\\n```\\nheaptrack my_application\\n```\\n\\nIt\'s that easy. After the program finishes, you\'ll see a file in your local directory with a name\\nlike `heaptrack.my_appplication.XXXX.gz`. If you load that up in `heaptrack_gui`, you\'ll see\\nsomething like this:\\n\\n![heaptrack](./heaptrack-before.png)\\n\\n---\\n\\nAnd even these pretty colors:\\n\\n![pretty colors](./heaptrack-flamegraph.png)\\n\\n## Reading Flamegraphs\\n\\nTo make sense of our memory usage, we\'re going to focus on that last picture - it\'s called a\\n[\\"flamegraph\\"](http://www.brendangregg.com/flamegraphs.html). These charts are typically used to\\nshow how much time your program spends executing each function, but they\'re used here to show how\\nmuch memory was allocated during those functions instead.\\n\\nFor example, we can see that all executions happened during the `main` function:\\n\\n![allocations in main](./heaptrack-main-colorized.png)\\n\\n...and within that, all allocations happened during `dtparse::parse`:\\n\\n![allocations in dtparse](./heaptrack-dtparse-colorized.png)\\n\\n...and within _that_, allocations happened in two different places:\\n\\n![allocations in parseinfo](./heaptrack-parseinfo-colorized.png)\\n\\nNow I apologize that it\'s hard to see, but there\'s one area specifically that stuck out as an issue:\\n**what the heck is the `Default` thing doing?**\\n\\n![pretty colors](./heaptrack-flamegraph-default.png)\\n\\n## Optimizing dtparse\\n\\nSee, I knew that there were some allocations during calls to `dtparse::parse`, but I was totally\\nwrong about where the bulk of allocations occurred in my program. Let me post the code and see if\\nyou can spot the mistake:\\n\\n```rust\\n/// Main entry point for using `dtparse`.\\npub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> {\\n let res = Parser::default().parse(\\n timestr, None, None, false, false,\\n None, false,\\n &HashMap::new(),\\n )?;\\n\\n Ok((res.0, res.1))\\n}\\n```\\n\\n> [dtparse](https://github.com/bspeice/dtparse/blob/4d7c5dd99572823fa4a390b483c38ab020a2172f/src/lib.rs#L1286)\\n\\n---\\n\\nBecause `Parser::parse` requires a mutable reference to itself, I have to create a new\\n`Parser::default` every time it receives a string. This is excessive! We\'d rather have an immutable\\nparser that can be re-used, and avoid allocating memory in the first place.\\n\\nArmed with that information, I put some time in to\\n[make the parser immutable](https://github.com/bspeice/dtparse/commit/741afa34517d6bc1155713bbc5d66905fea13fad#diff-b4aea3e418ccdb71239b96952d9cddb6).\\nNow that I can re-use the same parser over and over, the allocations disappear:\\n\\n![allocations cleaned up](./heaptrack-flamegraph-after.png)\\n\\nIn total, we went from requiring 2 MB of memory in\\n[version 1.0.2](https://crates.io/crates/dtparse/1.0.2):\\n\\n![memory before](./heaptrack-closeup.png)\\n\\nAll the way down to 300KB in [version 1.0.3](https://crates.io/crates/dtparse/1.0.3):\\n\\n![memory after](./heaptrack-closeup-after.png)\\n\\n## Conclusion\\n\\nIn the end, you don\'t need to write a custom allocator to be efficient with memory, great tools\\nalready exist to help you understand what your program is doing.\\n\\n**Use them.**\\n\\nGiven that [Moore\'s Law](https://en.wikipedia.org/wiki/Moore%27s_law) is\\n[dead](https://www.technologyreview.com/s/601441/moores-law-is-dead-now-what/), we\'ve all got to do\\nour part to take back what Microsoft stole.\\n\\n[dtparse]: https://crates.io/crates/dtparse\\n[dateutil]: https://github.com/dateutil/dateutil\\n[heaptrack]: https://github.com/KDE/heaptrack\\n[qadapt]: https://crates.io/crates/qadapt"},{"id":"2018/09/isomorphic-apps","metadata":{"permalink":"/2018/09/isomorphic-apps","source":"@site/blog/2018-09-15-isomorphic-apps/index.mdx","title":"Isomorphic desktop apps with Rust","description":"I both despise Javascript and am stunned by its success doing some really cool things. It\'s","date":"2018-09-15T12:00:00.000Z","tags":[],"readingTime":9.905,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/isomorphic-apps","title":"Isomorphic desktop apps with Rust","date":"2018-09-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731188450000,"prevItem":{"title":"A case study in heaptrack","permalink":"/2018/10/case-study-optimization"},"nextItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"}},"content":"I both despise Javascript and am stunned by its success doing some really cool things. It\'s\\n[this duality](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript) that\'s\\nled me to a couple of (very) late nights over the past weeks trying to reconcile myself as I\\nbootstrap a simple desktop application.\\n\\n\x3c!-- truncate --\x3e\\n\\nSee, as much as\\n[Webassembly isn\'t trying to replace Javascript](https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript),\\n**I want Javascript gone**. There are plenty of people who don\'t share my views, and they are\\nprobably nicer and more fun at parties. But I cringe every time \\"Webpack\\" is mentioned, and I think\\nit\'s hilarious that the\\n[language specification](https://ecma-international.org/publications/standards/Ecma-402.htm)\\ndramatically outpaces anyone\'s\\n[actual implementation](https://kangax.github.io/compat-table/es2016plus/). The answer to this\\nconundrum is of course to recompile code from newer versions of the language to older versions _of\\nthe same language_ before running. At least [Babel] is a nice tongue-in-cheek reference.\\n\\nYet for as much hate as [Electron] receives, it does a stunningly good job at solving a really hard\\nproblem: _how the hell do I put a button on the screen and react when the user clicks it_? GUI\\nprogramming is hard, straight up. But if browsers are already able to run everywhere, why don\'t we\\ntake advantage of someone else solving the hard problems for us? I don\'t like that I have to use\\nJavascript for it, but I really don\'t feel inclined to whip out good ol\' [wxWidgets].\\n\\nNow there are other native solutions ([libui-rs], [conrod], [oh hey wxWdidgets again!][wxrust]), but\\nthose also have their own issues with distribution, styling, etc. With Electron, I can\\n`yarn create electron-app my-app` and just get going, knowing that packaging/upgrades/etc. are built\\nin.\\n\\nMy question is: given recent innovations with WASM, _are we Electron yet_?\\n\\nNo, not really.\\n\\nInstead, **what would it take to get to a point where we can skip Javascript in Electron apps?**\\n\\n# Setting the Stage\\n\\nTruth is, WASM/Webassembly is a pretty new technology and I\'m a total beginner in this area. There\\nmay already be solutions to the issues I discuss, but I\'m totally unaware of them, so I\'m going to\\ntry and organize what I did manage to discover.\\n\\nI should also mention that the content and things I\'m talking about here are not intended to be\\nprescriptive, but more \\"if someone else is interested, what do we already know doesn\'t work?\\" _I\\nexpect everything in this post to be obsolete within two months._ Even over the course of writing\\nthis, [a separate blog post](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/) had\\nto be modified because [upstream changes](https://github.com/WebAssembly/binaryen/pull/1642) broke a\\n[Rust tool](https://github.com/rustwasm/wasm-bindgen/pull/787) the post tried to use. The post\\nultimately\\n[got updated](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477), **but\\nall this happened within the span of a week.** Things are moving quickly.\\n\\nI\'ll also note that we\'re going to skip [asm.js] and [emscripten]. Truth be told, I couldn\'t get\\neither of these to output anything, and so I\'m just going to say\\n[here be dragons.](https://en.wikipedia.org/wiki/Here_be_dragons) Everything I\'m discussing here\\nuses the `wasm32-unknown-unknown` target.\\n\\nThe code that I _did_ get running is available\\n[over here](https://github.com/speice-io/isomorphic-rust). Feel free to use it as a starting point,\\nbut I\'m mostly including the link as a reference for the things that were attempted.\\n\\n# An Example Running Application\\n\\nSo, I did _technically_ get a running application:\\n\\n![Electron app using WASM](./electron-percy-wasm.png)\\n\\n...which you can also try out if you want:\\n\\n```sh\\ngit clone https://github.com/speice-io/isomorphic-rust.git\\ncd isomorphic_rust/percy\\nyarn install && yarn start\\n```\\n\\n...but I wouldn\'t really call it a \\"high quality\\" starting point to base future work on. It\'s mostly\\nthere to prove this is possible in the first place. And that\'s something to be proud of! There\'s a\\nhuge amount of engineering that went into showing a window with the text \\"It\'s alive!\\".\\n\\nThere\'s also a lot of usability issues that prevent me from recommending anyone try Electron and\\nWASM apps at the moment, and I think that\'s the more important thing to discuss.\\n\\n# Issue the First: Complicated Toolchains\\n\\nI quickly established that [wasm-bindgen] was necessary to \\"link\\" my Rust code to Javascript. At\\nthat point you\'ve got an Electron app that starts an HTML page which ultimately fetches your WASM\\nblob. To keep things simple, the goal was to package everything using [webpack] so that I could just\\nload a `bundle.js` file on the page. That decision was to be the last thing that kinda worked in\\nthis process.\\n\\nThe first issue\\n[I ran into](https://www.reddit.com/r/rust/comments/98lpun/unable_to_load_wasm_for_electron_application/)\\nwhile attempting to bundle everything via `webpack` is a detail in the WASM spec:\\n\\n> This function accepts a Response object, or a promise for one, and ... **[if > it] does not match\\n> the `application/wasm` MIME type**, the returned promise will be rejected with a TypeError;\\n>\\n> [WebAssembly - Additional Web Embedding API](https://webassembly.org/docs/web/#additional-web-embedding-api)\\n\\nSpecifically, if you try and load a WASM blob without the MIME type set, you\'ll get an error. On the\\nweb this isn\'t a huge issue, as the server can set MIME types when delivering the blob. With\\nElectron, you\'re resolving things with a `file://` URL and thus can\'t control the MIME type:\\n\\n![TypeError: Incorrect response MIME type. Expected \'application/wasm\'.](./incorrect-MIME-type.png)\\n\\nThere are a couple of solutions depending on how far into the deep end you care to venture:\\n\\n- Embed a static file server in your Electron application\\n- Use a [custom protocol](https://electronjs.org/docs/api/protocol) and custom protocol handler\\n- Host your WASM blob on a website that you resolve at runtime\\n\\nBut all these are pretty bad solutions and defeat the purpose of using WASM in the first place.\\nInstead, my workaround was to\\n[open a PR with `webpack`](https://github.com/webpack/webpack/issues/7918) and use regex to remove\\ncalls to `instantiateStreaming` in the\\n[build script](https://github.com/speice-io/isomorphic-rust/blob/master/percy/build.sh#L21-L25):\\n\\n```sh\\ncargo +nightly build --target=wasm32-unknown-unknown && \\\\\\n wasm-bindgen \\"$WASM_DIR/debug/$WASM_NAME.wasm\\" --out-dir \\"$APP_DIR\\" --no-typescript && \\\\\\n # Have to use --mode=development so we can patch out the call to instantiateStreaming\\n \\"$DIR/node_modules/webpack-cli/bin/cli.js\\" --mode=development \\"$APP_DIR/app_loader.js\\" -o \\"$APP_DIR/bundle.js\\" && \\\\\\n sed -i \'s/.*instantiateStreaming.*//g\' \\"$APP_DIR/bundle.js\\"\\n```\\n\\nOnce that lands, the\\n[build process](https://github.com/speice-io/isomorphic-rust/blob/master/percy_patched_webpack/build.sh#L24-L27)\\nbecomes much simpler:\\n\\n```sh\\n\\ncargo +nightly build --target=wasm32-unknown-unknown && \\\\\\n wasm-bindgen \\"$WASM_DIR/debug/$WASM_NAME.wasm\\" --out-dir \\"$APP_DIR\\" --no-typescript && \\\\\\n \\"$DIR/node_modules/webpack-cli/bin/cli.js\\" --mode=production \\"$APP_DIR/app_loader.js\\" -o \\"$APP_DIR/bundle.js\\"\\n```\\n\\nBut we\'re not done yet! After we compile Rust into WASM and link WASM to Javascript (via\\n`wasm-bindgen` and `webpack`), we still have to make an Electron app. For this purpose I used a\\nstarter app from [Electron Forge], and then a\\n[`prestart` script](https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8)\\nto actually handle starting the application.\\n\\nThe\\n[final toolchain](https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8)\\nlooks something like this:\\n\\n- `yarn start` triggers the `prestart` script\\n- `prestart` checks for missing tools (`wasm-bindgen-cli`, etc.) and then:\\n - Uses `cargo` to compile the Rust code into WASM\\n - Uses `wasm-bindgen` to link the WASM blob into a Javascript file with exported symbols\\n - Uses `webpack` to bundle the page start script with the Javascript we just generated\\n - Uses `babel` under the hood to compile the `wasm-bindgen` code down from ES6 into something\\n browser-compatible\\n- The `start` script runs an Electron Forge handler to do some sanity checks\\n- Electron actually starts\\n\\n...which is complicated. I think more work needs to be done to either build a high-quality starter\\napp that can manage these steps, or another tool that \\"just handles\\" the complexity of linking a\\ncompiled WASM file into something the Electron browser can run.\\n\\n# Issue the Second: WASM tools in Rust\\n\\nFor as much as I didn\'t enjoy the Javascript tooling needed to interface with Rust, the Rust-only\\nbits aren\'t any better at the moment. I get it, a lot of projects are just starting off, and that\\nleads to a fragmented ecosystem. Here\'s what I can recommend as a starting point:\\n\\nDon\'t check in your `Cargo.lock` files to version control. If there\'s a disagreement between the\\nversion of `wasm-bindgen-cli` you have installed and the `wasm-bindgen` you\'re compiling with in\\n`Cargo.lock`, you get a nasty error:\\n\\n```\\nit looks like the Rust project used to create this wasm file was linked against\\na different version of wasm-bindgen than this binary:\\n\\nrust wasm file: 0.2.21\\n this binary: 0.2.17\\n\\nCurrently the bindgen format is unstable enough that these two version must\\nexactly match, so it\'s required that these two version are kept in sync by\\neither updating the wasm-bindgen dependency or this binary.\\n```\\n\\nNot that I ever managed to run into this myself (_coughs nervously_).\\n\\nThere are two projects attempting to be \\"application frameworks\\": [percy] and [yew]. Between those,\\nI managed to get [two](https://github.com/speice-io/isomorphic-rust/tree/master/percy)\\n[examples](https://github.com/speice-io/isomorphic-rust/tree/master/percy_patched_webpack) running\\nusing `percy`, but was unable to get an\\n[example](https://github.com/speice-io/isomorphic-rust/tree/master/yew) running with `yew` because\\nof issues with \\"missing modules\\" during the `webpack` step:\\n\\n```sh\\nERROR in ./dist/electron_yew_wasm_bg.wasm\\nModule not found: Error: Can\'t resolve \'env\' in \'/home/bspeice/Development/isomorphic_rust/yew/dist\'\\n @ ./dist/electron_yew_wasm_bg.wasm\\n @ ./dist/electron_yew_wasm.js\\n @ ./dist/app.js\\n @ ./dist/app_loader.js\\n```\\n\\nIf you want to work with the browser APIs directly, your choices are [percy-webapis] or [stdweb] (or\\neventually [web-sys]). See above for my `percy` examples, but when I tried\\n[an example with `stdweb`](https://github.com/speice-io/isomorphic-rust/tree/master/stdweb), I was\\nunable to get it running:\\n\\n```sh\\nERROR in ./dist/stdweb_electron_bg.wasm\\nModule not found: Error: Can\'t resolve \'env\' in \'/home/bspeice/Development/isomorphic_rust/stdweb/dist\'\\n @ ./dist/stdweb_electron_bg.wasm\\n @ ./dist/stdweb_electron.js\\n @ ./dist/app_loader.js\\n```\\n\\nAt this point I\'m pretty convinced that `stdweb` is causing issues for `yew` as well, but can\'t\\nprove it.\\n\\nI did also get a [minimal example](https://github.com/speice-io/isomorphic-rust/tree/master/minimal)\\nrunning that doesn\'t depend on any tools besides `wasm-bindgen`. However, it requires manually\\nwriting \\"`extern C`\\" blocks for everything you need from the browser. Es no bueno.\\n\\nFinally, from a tools and platform view, there are two up-and-coming packages that should be\\nmentioned: [js-sys] and [web-sys]. Their purpose is to be fundamental building blocks that exposes\\nthe browser\'s APIs to Rust. If you\'re interested in building an app framework from scratch, these\\nshould give you the most flexibility. I didn\'t touch either in my research, though I expect them to\\nbe essential long-term.\\n\\nSo there\'s a lot in play from the Rust side of things, and it\'s just going to take some time to\\nfigure out what works and what doesn\'t.\\n\\n# Issue the Third: Known Unknowns\\n\\nAlright, so after I managed to get an application started, I stopped there. It was a good deal of\\neffort to chain together even a proof of concept, and at this point I\'d rather learn [Typescript]\\nthan keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...\\n\\nThe important point I want to make is that there\'s a lot unknown about how any of this holds up\\noutside proofs of concept. Things I didn\'t attempt:\\n\\n- Testing\\n- Packaging\\n- Updates\\n- Literally anything related to why I wanted to use Electron in the first place\\n\\n# What it Would Take\\n\\nMuch as I don\'t like Javascript, the tools are too shaky for me to recommend mixing Electron and\\nWASM at the moment. There\'s a lot of innovation happening, so who knows? Someone might have an\\napplication in production a couple months from now. But at the moment, I\'m personally going to stay\\naway.\\n\\nLet\'s finish with a wishlist then - here are the things that I think need to happen before\\nElectron/WASM/Rust can become a thing:\\n\\n- Webpack still needs some updates. The necessary work is in progress, but hasn\'t landed yet\\n ([#7983](https://github.com/webpack/webpack/pull/7983))\\n- Browser API libraries (`web-sys` and `stdweb`) need to make sure they can support running in\\n Electron (see module error above)\\n- Projects need to stabilize. There\'s talk of `stdweb` being turned into a Rust API\\n [on top of web-sys](https://github.com/rustwasm/team/issues/226#issuecomment-418475778), and percy\\n [moving to web-sys](https://github.com/chinedufn/percy/issues/24), both of which are big changes\\n- `wasm-bindgen` is great, but still in the \\"move fast and break things\\" phase\\n- A good \\"boilerplate\\" app would dramatically simplify the start-up costs;\\n [electron-react-boilerplate](https://github.com/chentsulin/electron-react-boilerplate) comes to\\n mind as a good project to imitate\\n- More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I\'m\\n doing\\n\\n[wxwidgets]: https://wxwidgets.org/\\n[libui-rs]: https://github.com/LeoTindall/libui-rs/\\n[electron]: https://electronjs.org/\\n[babel]: https://babeljs.io/\\n[wxrust]: https://github.com/kenz-gelsoft/wxRust\\n[wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen\\n[js-sys]: https://crates.io/crates/js-sys\\n[percy-webapis]: https://crates.io/crates/percy-webapis\\n[stdweb]: https://crates.io/crates/stdweb\\n[web-sys]: https://crates.io/crates/web-sys\\n[percy]: https://chinedufn.github.io/percy/\\n[virtual-dom-rs]: https://crates.io/crates/virtual-dom-rs\\n[yew]: https://github.com/DenisKolodin/yew\\n[react]: https://reactjs.org/\\n[elm]: http://elm-lang.org/\\n[asm.js]: http://asmjs.org/\\n[emscripten]: https://kripken.github.io/emscripten-site/\\n[typescript]: https://www.typescriptlang.org/\\n[electron forge]: https://electronforge.io/\\n[conrod]: https://github.com/PistonDevelopers/conrod\\n[webpack]: https://webpack.js.org/"},{"id":"2018/09/primitives-in-rust-are-weird","metadata":{"permalink":"/2018/09/primitives-in-rust-are-weird","source":"@site/blog/2018-09-01-primitives-in-rust-are-weird/index.mdx","title":"Primitives in Rust are weird (and cool)","description":"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it","date":"2018-09-01T12:00:00.000Z","tags":[],"readingTime":6.945,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/09/primitives-in-rust-are-weird","title":"Primitives in Rust are weird (and cool)","date":"2018-09-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"},"nextItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"}},"content":"I wrote a really small Rust program a while back because I was curious. I was 100% convinced it\\ncouldn\'t possibly run:\\n\\n```rust\\nfn main() {\\n println!(\\"{}\\", 8.to_string())\\n}\\n```\\n\\nAnd to my complete befuddlement, it compiled, ran, and produced a completely sensible output.\\n\\n\x3c!-- truncate --\x3e\\n\\nThe reason I was so surprised has to do with how Rust treats a special category of things I\'m going to\\ncall _primitives_. In the current version of the Rust book, you\'ll see them referred to as\\n[scalars][rust_scalar], and in older versions they\'ll be called [primitives][rust_primitive], but\\nwe\'re going to stick with the name _primitive_ for the time being. Explaining why this program is so\\ncool requires talking about a number of other programming languages, and keeping a consistent\\nterminology makes things easier.\\n\\n**You\'ve been warned:** this is going to be a tedious post about a relatively minor issue that\\ninvolves Java, Python, C, and x86 Assembly. And also me pretending like I know what I\'m talking\\nabout with assembly.\\n\\n## Defining primitives (Java)\\n\\nThe reason I\'m using the name _primitive_ comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there\'s a special\\nname for some specific types of values:\\n\\n> ```\\n> bool char byte\\n> short int long\\n> float double\\n> ```\\n\\nThey are referred to as [primitives][java_primitive]. And relative to the other bits of Java,\\nthey have two unique features. First, they don\'t have to worry about the\\n[billion-dollar mistake](https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions);\\nprimitives in Java can never be `null`. Second: *they can\'t have instance methods*.\\nRemember that Rust program from earlier? Java has no idea what to do with it:\\n\\n```java\\nclass Main {\\n public static void main(String[] args) {\\n int x = 8;\\n System.out.println(x.toString()); // Triggers a compiler error\\n }\\n}\\n````\\n\\nThe error is:\\n\\n```\\nMain.java:5: error: int cannot be dereferenced\\n System.out.println(x.toString());\\n ^\\n1 error\\n```\\n\\nSpecifically, Java\'s [`Object`](https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html)\\nand things that inherit from it are pointers under the hood, and we have to dereference them before\\nthe fields and methods they define can be used. In contrast, _primitive types are just values_ -\\nthere\'s nothing to be dereferenced. In memory, they\'re just a sequence of bits.\\n\\nIf we really want, we can turn the `int` into an\\n[`Integer`](https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html) and then dereference\\nit, but it\'s a bit wasteful:\\n\\n```java\\nclass Main {\\n public static void main(String[] args) {\\n int x = 8;\\n Integer y = Integer.valueOf(x);\\n System.out.println(y.toString());\\n }\\n}\\n```\\n\\nThis creates the variable `y` of type `Integer` (which inherits `Object`), and at run time we\\ndereference `y` to locate the `toString()` function and call it. Rust obviously handles things a bit\\ndifferently, but we have to dig into the low-level details to see it in action.\\n\\n## Low Level Handling of Primitives (C)\\n\\nWe first need to build a foundation for reading and understanding the assembly code the final answer\\nrequires. Let\'s begin with showing how the `C` language (and your computer) thinks about \\"primitive\\"\\nvalues in memory:\\n\\n```c\\nvoid my_function(int num) {}\\n\\nint main() {\\n int x = 8;\\n my_function(x);\\n}\\n```\\n\\nThe [compiler explorer](https://godbolt.org/z/lgNYcc) gives us an easy way of showing off the\\nassembly-level code that\'s generated: <small>whose output has been lightly\\nedited</small>\\n\\n```nasm\\nmain:\\n push rbp\\n mov rbp, rsp\\n sub rsp, 16\\n\\n ; We assign the value `8` to `x` here\\n mov DWORD PTR [rbp-4], 8\\n\\n ; And copy the bits making up `x` to a location\\n ; `my_function` can access (`edi`)\\n mov eax, DWORD PTR [rbp-4]\\n mov edi, eax\\n\\n ; Call `my_function` and give it control\\n call my_function\\n\\n mov eax, 0\\n leave\\n ret\\n\\nmy_function:\\n push rbp\\n mov rbp, rsp\\n\\n ; Copy the bits out of the pre-determined location (`edi`)\\n ; to somewhere we can use\\n mov DWORD PTR [rbp-4], edi\\n nop\\n\\n pop rbp\\n ret\\n```\\n\\nAt a really low level of memory, we\'re copying bits around using the [`mov`][x86_guide] instruction;\\nnothing crazy. But to show how similar Rust is, let\'s take a look at our program translated from C\\nto Rust:\\n\\n```rust\\nfn my_function(x: i32) {}\\n\\nfn main() {\\n let x = 8;\\n my_function(x)\\n}\\n```\\n\\nAnd the assembly generated when we stick it in the\\n[compiler explorer](https://godbolt.org/z/cAlmk0): <small>again, lightly\\nedited</small>\\n\\n```nasm\\nexample::main:\\n push rax\\n\\n ; Look familiar? We\'re copying bits to a location for `my_function`\\n ; The compiler just optimizes out holding `x` in memory\\n mov edi, 8\\n\\n ; Call `my_function` and give it control\\n call example::my_function\\n\\n pop rax\\n ret\\n\\nexample::my_function:\\n sub rsp, 4\\n\\n ; And copying those bits again, just like in C\\n mov dword ptr [rsp], edi\\n\\n add rsp, 4\\n ret\\n```\\n\\nThe generated Rust assembly is functionally pretty close to the C assembly: _When working with\\nprimitives, we\'re just dealing with bits in memory_.\\n\\nIn Java we have to dereference a pointer to call its functions; in Rust, there\'s no pointer to\\ndereference. So what exactly is going on with this `.to_string()` function call?\\n\\n## impl primitive (and Python)\\n\\nNow it\'s time to <strike>reveal my trap card</strike> show the revelation that tied all this\\ntogether: _Rust has implementations for its primitive types._ That\'s right, `impl` blocks aren\'t\\nonly for `structs` and `traits`, primitives get them too. Don\'t believe me? Check out\\n[u32](https://doc.rust-lang.org/std/primitive.u32.html),\\n[f64](https://doc.rust-lang.org/std/primitive.f64.html) and\\n[char](https://doc.rust-lang.org/std/primitive.char.html) as examples.\\n\\nBut the really interesting bit is how Rust turns those `impl` blocks into assembly. Let\'s break out\\nthe [compiler explorer](https://godbolt.org/z/6LBEwq) once again:\\n\\n```rust\\npub fn main() {\\n 8.to_string()\\n}\\n```\\n\\nAnd the interesting bits in the assembly: <small>heavily trimmed down</small>\\n\\n```nasm\\nexample::main:\\n sub rsp, 24\\n mov rdi, rsp\\n lea rax, [rip + .Lbyte_str.u]\\n mov rsi, rax\\n\\n ; Cool stuff right here\\n call <T as alloc::string::ToString>::to_string@PLT\\n\\n mov rdi, rsp\\n call core::ptr::drop_in_place\\n add rsp, 24\\n ret\\n```\\n\\nNow, this assembly is a bit more complicated, but here\'s the big revelation: **we\'re calling\\n`to_string()` as a function that exists all on its own, and giving it the instance of `8`**. Instead\\nof thinking of the value 8 as an instance of `u32` and then peeking in to find the location of the\\nfunction we want to call (like Java), we have a function that exists outside of the instance and\\njust give that function the value `8`.\\n\\nThis is an incredibly technical detail, but the interesting idea I had was this: _if `to_string()`\\nis a static function, can I refer to the unbound function and give it an instance?_\\n\\nBetter explained in code (and a [compiler explorer](https://godbolt.org/z/fJY-gA) link because I\\nseriously love this thing):\\n\\n```rust\\nstruct MyVal {\\n x: u32\\n}\\n\\nimpl MyVal {\\n fn to_string(&self) -> String {\\n self.x.to_string()\\n }\\n}\\n\\npub fn main() {\\n let my_val = MyVal { x: 8 };\\n\\n // THESE ARE THE SAME\\n my_val.to_string();\\n MyVal::to_string(&my_val);\\n}\\n```\\n\\nRust is totally fine \\"binding\\" the function call to the instance, and also as a static.\\n\\nMIND == BLOWN.\\n\\nPython does the same thing where I can both call functions bound to their instances and also call as\\nan unbound function where I give it the instance:\\n\\n```python\\nclass MyClass():\\n x = 24\\n\\n def my_function(self):\\n print(self.x)\\n\\nm = MyClass()\\n\\nm.my_function()\\nMyClass.my_function(m)\\n```\\n\\nAnd Python tries to make you _think_ that primitives can have instance methods...\\n\\n```python\\n>>> dir(8)\\n[\'__abs__\', \'__add__\', \'__and__\', \'__class__\', \'__cmp__\', \'__coerce__\',\\n\'__delattr__\', \'__div__\', \'__divmod__\', \'__doc__\', \'__float__\', \'__floordiv__\',\\n...\\n\'__setattr__\', \'__sizeof__\', \'__str__\', \'__sub__\', \'__subclasshook__\', \'__truediv__\',\\n...]\\n\\n>>> # Theoretically `8.__str__()` should exist, but:\\n\\n>>> 8.__str__()\\n File \\"<stdin>\\", line 1\\n 8.__str__()\\n ^\\nSyntaxError: invalid syntax\\n\\n>>> # It will run if we assign it first though:\\n>>> x = 8\\n>>> x.__str__()\\n\'8\'\\n```\\n\\n...but in practice it\'s a bit complicated.\\n\\nSo while Python handles binding instance methods in a way similar to Rust, it\'s still not able to\\nrun the example we started with.\\n\\n## Conclusion\\n\\nThis was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor\\ndetails like primitives leads to really cool effects. Primitives are optimized like C in how they\\nhave a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python\\n(like both instance and late binding).\\n\\nAnd when you put it together, there are areas where Rust does cool things nobody else can; as a\\nquirky feature of Rust\'s type system, `8.to_string()` is actually valid code.\\n\\nNow go forth and fool your friends into thinking you know assembly. This is all I\'ve got.\\n\\n[x86_guide]: http://www.cs.virginia.edu/~evans/cs216/guides/x86.html\\n[java_primitive]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html\\n[rust_scalar]: https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html#scalar-types\\n[rust_primitive]: https://doc.rust-lang.org/book/first-edition/primitive-types.html"},{"id":"2018/06/dateutil-parser-to-rust","metadata":{"permalink":"/2018/06/dateutil-parser-to-rust","source":"@site/blog/2018-06-25-dateutil-parser-to-rust/index.mdx","title":"What I learned porting dateutil to Rust","description":"I\'ve mostly been a lurker in Rust for a while, making a couple small contributions here and there.","date":"2018-06-25T12:00:00.000Z","tags":[],"readingTime":6.99,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/06/dateutil-parser-to-rust","title":"What I learned porting dateutil to Rust","date":"2018-06-25T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Primitives in Rust are weird (and cool)","permalink":"/2018/09/primitives-in-rust-are-weird"},"nextItem":{"title":"Hello!","permalink":"/2018/05/hello"}},"content":"I\'ve mostly been a lurker in Rust for a while, making a couple small contributions here and there.\\nSo launching [dtparse](https://github.com/bspeice/dtparse) feels like nice step towards becoming a\\nfunctioning member of society. But not too much, because then you know people start asking you to\\npay bills, and ain\'t nobody got time for that.\\n\\n\x3c!-- truncate --\x3e\\n\\nBut I built dtparse, and you can read about my thoughts on the process. Or don\'t. I won\'t tell you\\nwhat to do with your life (but you should totally keep reading).\\n\\n## Slow down, what?\\n\\nOK, fine, I guess I should start with _why_ someone would do this.\\n\\n[Dateutil](https://github.com/dateutil/dateutil) is a Python library for handling dates. The\\nstandard library support for time in Python is kinda dope, but there are a lot of extras that go\\ninto making it useful beyond just the [datetime](https://docs.python.org/3.6/library/datetime.html)\\nmodule. `dateutil.parser` specifically is code to take all the super-weird time formats people come\\nup with and turn them into something actually useful.\\n\\nDate/time parsing, it turns out, is just like everything else involving\\n[computers](https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time) and\\n[time](https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time): it\\nfeels like it shouldn\'t be that difficult to do, until you try to do it, and you realize that people\\nsuck and this is why\\n[we can\'t we have nice things](https://zachholman.com/talk/utc-is-enough-for-everyone-right). But\\nalas, we\'ll try and make contemporary art out of the rubble and give it a pretentious name like\\n_Time_.\\n\\n![A gravel mound](./gravel-mound.jpg)\\n\\n> [Time](https://www.goodfreephotos.com/united-states/montana/elkhorn/remains-of-the-mining-operation-elkhorn.jpg.php)\\n\\nWhat makes `dateutil.parser` great is that there\'s single function with a single argument that\\ndrives what programmers interact with:\\n[`parse(timestr)`](https://github.com/dateutil/dateutil/blob/6dde5d6298cfb81a4c594a38439462799ed2aef2/dateutil/parser/_parser.py#L1258).\\nIt takes in the time as a string, and gives you back a reasonable \\"look, this is the best anyone can\\npossibly do to make sense of your input\\" value. It doesn\'t expect much of you.\\n\\n[And now it\'s in Rust.](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L1332)\\n\\n## Lost in Translation\\n\\nHaving worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I\'m\\nadmittedly hesitant to publish Python code that\'s trying to be Rust. Interestingly, Rust code can\\nactually do a great job of mimicking Python. It\'s certainly not idiomatic Rust, but I\'ve had better\\nexperiences than\\n[this guy](https://webcache.googleusercontent.com/search?q=cache:wkYMpktJtnUJ:https://jackstouffer.com/blog/porting_dateutil.html+&cd=3&hl=en&ct=clnk&gl=us)\\nwho attempted the same thing for D. These are the actual take-aways:\\n\\nWhen transcribing code, **stay as close to the original library as possible**. I\'m talking about\\nusing the same variable names, same access patterns, the whole shebang. It\'s way too easy to make a\\ncouple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference\\nmanual for verbatim what your code should be means that you don\'t spend that long debugging\\ncomplicated logic, you\'re more looking for typos.\\n\\nAlso, **don\'t use nice Rust things like enums**. While\\n[one time it worked out OK for me](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L88-L94),\\nI also managed to shoot myself in the foot a couple times because `dateutil` stores AM/PM as a\\nboolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In\\ngeneral, writing nice code _should not be a first-pass priority_ when you\'re just trying to recreate\\nthe same functionality.\\n\\n**Exceptions are a pain.** Make peace with it. Python code is just allowed to skip stack frames. So\\nwhen a co-worker told me \\"Rust is getting try-catch syntax\\" I properly freaked out. Turns out\\n[he\'s not quite right](https://github.com/rust-lang/rfcs/pull/243), and I\'m OK with that. And while\\n`dateutil` is pretty well-behaved about not skipping multiple stack frames,\\n[130-line try-catch blocks](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L730-L865)\\ntake a while to verify.\\n\\nAs another Python quirk, **be very careful about\\n[long nested if-elif-else blocks](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L494-L568)**.\\nI used to think that Python\'s whitespace was just there to get you to format your code correctly. I\\nthink that no longer. It\'s way too easy to close a block too early and have incredibly weird issues\\nin the logic. Make sure you use an editor that displays indentation levels so you can keep things\\nstraight.\\n\\n**Rust macros are not free.** I originally had the\\n[main test body](https://github.com/bspeice/dtparse/blob/b0e737f088eca8e83ab4244c6621a2797d247697/tests/compat.rs#L63-L217)\\nwrapped up in a macro using [pyo3](https://github.com/PyO3/PyO3). It took two minutes to compile.\\nAfter\\n[moving things to a function](https://github.com/bspeice/dtparse/blob/e017018295c670e4b6c6ee1cfff00dbb233db47d/tests/compat.rs#L76-L205)\\ncompile times dropped down to ~5 seconds. Turns out 150 lines \\\\* 100 tests = a lot of redundant code\\nto be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually\\nfunctions that need to be liberated, man.\\n\\nFinally, **I really miss list comprehensions and dictionary comprehensions.** As a quick comparison,\\nsee\\n[this dateutil code](https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L476)\\nand\\n[the implementation in Rust](https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L619-L629).\\nI probably wrote it wrong, and I\'m sorry. Ultimately though, I hope that these comprehensions can be\\nadded through macros or syntax extensions. Either way, they\'re expressive, save typing, and are\\nsuper-readable. Let\'s get more of that.\\n\\n## Using a young language\\n\\nNow, Rust is exciting and new, which means that there\'s opportunity to make a substantive impact. On\\nmore than one occasion though, I\'ve had issues navigating the Rust ecosystem.\\n\\nWhat I\'ll call the \\"canonical library\\" is still being built. In Python, if you need datetime\\nparsing, you use `dateutil`. If you want `decimal` types, it\'s already in the\\n[standard library](https://docs.python.org/3.6/library/decimal.html). While I might\'ve gotten away\\nwith `f64`, `dateutil` uses decimals, and I wanted to follow the principle of **staying as close to\\nthe original library as possible**. Thus began my quest to find a decimal library in Rust. What I\\nquickly found was summarized in a comment:\\n\\n> Writing a BigDecimal is easy. Writing a _good_ BigDecimal is hard.\\n>\\n> [-cmr](https://github.com/rust-lang/rust/issues/8937#issuecomment-34582794)\\n\\nIn practice, this means that there are at least [4](https://crates.io/crates/bigdecimal)\\n[different](https://crates.io/crates/rust_decimal)\\n[implementations](https://crates.io/crates/decimal) [available](https://crates.io/crates/decimate).\\nAnd that\'s a lot of decisions to worry about when all I\'m thinking is \\"why can\'t\\n[calendar reform](https://en.wikipedia.org/wiki/Calendar_reform) be a thing\\" and I\'m forced to dig\\nthrough a [couple](https://github.com/rust-lang/rust/issues/8937#issuecomment-31661916)\\n[different](https://github.com/rust-lang/rfcs/issues/334)\\n[threads](https://github.com/rust-num/num/issues/8) to figure out if the library I\'m look at is dead\\nor just stable.\\n\\nAnd even when the \\"canonical library\\" exists, there\'s no guarantees that it will be well-maintained.\\n[Chrono](https://github.com/chronotope/chrono) is the _de facto_ date/time library in Rust, and just\\nreleased version 0.4.4 like two days ago. Meanwhile,\\n[chrono-tz](https://github.com/chronotope/chrono-tz) appears to be dead in the water even though\\n[there are people happy to help maintain it](https://github.com/chronotope/chrono-tz/issues/19). I\\nknow relatively little about it, but it appears that most of the release process is automated;\\nkeeping that up to date should be a no-brainer.\\n\\n## Trial Maintenance Policy\\n\\nSpecifically given \\"maintenance\\" being an\\n[oft-discussed](https://www.reddit.com/r/rust/comments/48540g/thoughts_on_initiators_vs_maintainers/)\\nissue, I\'m going to try out the following policy to keep things moving on `dtparse`:\\n\\n1. Issues/PRs needing _maintainer_ feedback will be updated at least weekly. I want to make sure\\n nobody\'s blocking on me.\\n\\n2. To keep issues/PRs needing _contributor_ feedback moving, I\'m going to (kindly) ask the\\n contributor to check in after two weeks, and close the issue without resolution if I hear nothing\\n back after a month.\\n\\nThe second point I think has the potential to be a bit controversial, so I\'m happy to receive\\nfeedback on that. And if a contributor responds with \\"hey, still working on it, had a kid and I\'m\\nrunning on 30 seconds of sleep a night,\\" then first: congratulations on sustaining human life. And\\nsecond: I don\'t mind keeping those requests going indefinitely. I just want to try and balance\\nkeeping things moving with giving people the necessary time they need.\\n\\nI should also note that I\'m still getting some best practices in place - CONTRIBUTING and\\nCONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are\\nperfect.\\n\\n## Roadmap and Conclusion\\n\\nSo if I\'ve now built a `dateutil`-compatible parser, we\'re done, right? Of course not! That\'s not\\nnearly ambitious enough.\\n\\nUltimately, I\'d love to have a library that\'s capable of parsing everything the Linux `date` command\\ncan do (and not `date` on OSX, because seriously, BSD coreutils are the worst). I know Rust has a\\ncoreutils rewrite going on, and `dtparse` would potentially be an interesting candidate since it\\ndoesn\'t bring in a lot of extra dependencies. [`humantime`](https://crates.io/crates/humantime)\\ncould help pick up some of the (current) slack in dtparse, so maybe we can share and care with each\\nother?\\n\\nAll in all, I\'m mostly hoping that nobody\'s already done this and I haven\'t spent a bit over a month\\non redundant code. So if it exists, tell me. I need to know, but be nice about it, because I\'m going\\nto take it hard.\\n\\nAnd in the mean time, I\'m looking forward to building more. Onwards."},{"id":"2018/05/hello","metadata":{"permalink":"/2018/05/hello","source":"@site/blog/2018-05-28-hello/index.mdx","title":"Hello!","description":"I\'ll do what I can to keep this short, there\'s plenty of other things we both should be doing right","date":"2018-05-28T12:00:00.000Z","tags":[],"readingTime":0.375,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/05/hello","title":"Hello!","date":"2018-05-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"},"nextItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"}},"content":"I\'ll do what I can to keep this short, there\'s plenty of other things we both should be doing right\\nnow.\\n\\n\x3c!-- truncate --\x3e\\n\\nIf you\'re here for the bread pics, and to marvel in some other culinary side projects, I\'ve got you\\ncovered:\\n\\n![Saturday Bread](./bread.jpg)\\n\\nAnd no, I\'m not posting pictures of earlier attempts that ended up turning into rocks in the oven.\\n\\nOkay, just one:\\n\\n![Bread as rock](./rocks.jpg)\\n\\nThanks, and keep it amazing."},{"id":"2018/01/captains-cookbook-part-2","metadata":{"permalink":"/2018/01/captains-cookbook-part-2","source":"@site/blog/2018-01-16-captains-cookbook-part-2/index.mdx","title":"Captain\'s Cookbook: Practical usage","description":"A look at more practical usages of Cap\'N Proto","date":"2018-01-16T13:00:00.000Z","tags":[],"readingTime":6.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-2","title":"Captain\'s Cookbook: Practical usage","date":"2018-01-16T13:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Hello!","permalink":"/2018/05/hello"},"nextItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"}},"content":"A look at more practical usages of Cap\'N Proto\\n\\n\x3c!-- truncate --\x3e\\n\\n[Part 1](/2018/01/captains-cookbook-part-1) of this series took a look at a basic starting project\\nwith Cap\'N Proto. In this section, we\'re going to take the (admittedly basic) schema and look at how we can add a pretty\\nbasic feature - sending Cap\'N Proto messages between threads. It\'s nothing complex, but I want to make sure that there\'s\\nsome documentation surrounding practical usage of the library.\\n\\nAs a quick refresher, we build a Cap\'N Proto message and go through the serialization/deserialization steps\\n[here](https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs). Our current example is going to build on\\nthe code we wrote there; after the deserialization step, we\'ll try and send the `point_reader` to a separate thread\\nfor verification.\\n\\nI\'m going to walk through the attempts as I made them and my thinking throughout.\\nIf you want to skip to the final project, check out the code available [here](https://github.com/bspeice/capnp_cookbook_2)\\n\\n## Attempt 1: Move the reference\\n\\nAs a first attempt, we\'re going to try and let Rust move the reference. Our code will look something like:\\n\\n```rust\\nfn main() {\\n\\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from\\n // somewhere else\\n\\n let deserialized = capnp::serialize::read_message(\\n &mut buffer.as_slice(),\\n capnp::message::ReaderOptions::new()\\n ).unwrap();\\n\\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\\n\\n // By using `point_reader` inside the new thread, we\'re hoping that Rust can\\n // safely move the reference and invalidate the original thread\'s usage.\\n // Since the original thread doesn\'t use `point_reader` again, this should\\n // be safe, right?\\n let handle = std::thread:spawn(move || {\\n\\n assert_eq!(point_reader.get_x(), 12);\\n\\n assert_eq!(point_reader.get_y(), 14);\\n });\\n\\n handle.join().unwrap()\\n}\\n```\\n\\nWell, the Rust compiler doesn\'t really like this. We get four distinct errors back:\\n\\n```\\nerror[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<\'_>]` \\n --\x3e src/main.rs:31:18 \\n | \\n31 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely \\n | \\n\\nerror[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<\'_>]` \\n --\x3e src/main.rs:31:18 \\n | \\n31 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely \\n | \\n\\nerror[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied \\n --\x3e src/main.rs:31:18 \\n | \\n31 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely \\n | \\n\\nerror[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + \'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<\'_>]` \\n --\x3e src/main.rs:31:18 \\n | \\n31 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + \'static>>>` cannot be sent between threads safely \\n | \\n\\nerror: aborting due to 4 previous errors\\n```\\n\\nNote, I\'ve removed the help text for brevity, but suffice to say that these errors are intimidating.\\nPay attention to the text that keeps on getting repeated though: `XYZ cannot be sent between threads safely`.\\n\\nThis is a bit frustrating: we own the `buffer` from which all the content was derived, and we don\'t have any\\nunsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there\'s no possibility\\nof the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust\\npreventing us from doing something that really should be legal?\\n\\nThis is what is known as [fighting the borrow checker](https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html).\\nLet our crusade begin.\\n\\n## Attempt 2: Put the `Reader` in a `Box`\\n\\nThe [`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) type allows us to convert a pointer we have\\n(in our case the `point_reader`) into an \\"owned\\" value, which should be easier to send across threads.\\nOur next attempt looks something like this:\\n\\n```rust\\nfn main() {\\n\\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content\\n // from somewhere else\\n\\n let deserialized = capnp::serialize::read_message(\\n &mut buffer.as_slice(),\\n capnp::message::ReaderOptions::new()\\n ).unwrap();\\n\\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\\n\\n let boxed_reader = Box::new(point_reader);\\n\\n // Now that the reader is `Box`ed, we\'ve proven ownership, and Rust can\\n // move the ownership to the new thread, right?\\n let handle = std::thread::spawn(move || {\\n\\n assert_eq!(boxed_reader.get_x(), 12);\\n\\n assert_eq!(boxed_reader.get_y(), 14);\\n });\\n\\n handle.join().unwrap();\\n}\\n```\\n\\nSpoiler alert: still doesn\'t work. Same errors still show up.\\n\\n```\\nerror[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<\'_>` \\n --\x3e src/main.rs:33:18 \\n | \\n33 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely \\n | \\n\\nerror[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<\'_>` \\n --\x3e src/main.rs:33:18 \\n | \\n33 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely \\n | \\n\\nerror[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied \\n --\x3e src/main.rs:33:18 \\n | \\n33 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely \\n | \\n\\nerror[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + \'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<\'_>` \\n --\x3e src/main.rs:33:18 \\n | \\n33 | let handle = std::thread::spawn(move || { \\n | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + \'static>>>` cannot be sent between threads safely \\n | \\n\\nerror: aborting due to 4 previous errors\\n```\\n\\nLet\'s be a little bit smarter about the exceptions this time though. What is that\\n[`std::marker::Send`](https://doc.rust-lang.org/std/marker/trait.Send.html) thing the compiler keeps telling us about?\\n\\nThe documentation is pretty clear; `Send` is used to denote:\\n\\n> Types that can be transferred across thread boundaries.\\n\\nIn our case, we are seeing the error messages for two reasons:\\n\\n1. Pointers (`*const u8`) are not safe to send across thread boundaries. While we\'re nice in our code\\nmaking sure that we wait on the child thread to finish before closing down, the Rust compiler can\'t make\\nthat assumption, and so complains that we\'re not using this in a safe manner.\\n\\n2. The `point_capnp::point::Reader` type is itself not safe to send across threads because it doesn\'t\\nimplement the `Send` trait. Which is to say, the things that make up a `Reader` are themselves not thread-safe,\\nso the `Reader` is also not thread-safe.\\n\\nSo, how are we to actually transfer a parsed Cap\'N Proto message between threads?\\n\\n## Attempt 3: The `TypedReader`\\n\\nThe `TypedReader` is a new API implemented in the Cap\'N Proto [Rust code](https://crates.io/crates/capnp/0.8.14).\\nWe\'re interested in it here for two reasons:\\n\\n1. It allows us to define an object where the _object_ owns the underlying data. In previous attempts,\\nthe current context owned the data, but the `Reader` itself had no such control.\\n\\n2. We can compose the `TypedReader` using objects that are safe to `Send` across threads, guaranteeing\\nthat we can transfer parsed messages across threads.\\n\\nThe actual type info for the [`TypedReader`](https://github.com/capnproto/capnproto-rust/blob/f0efc35d7e9bd8f97ca4fdeb7c57fd7ea348e303/src/message.rs#L181)\\nis a bit complex. And to be honest, I\'m still really not sure what the whole point of the\\n[`PhantomData`](https://doc.rust-lang.org/std/marker/struct.PhantomData.html) thing is either.\\nMy impression is that it lets us enforce type safety when we know what the underlying Cap\'N Proto\\nmessage represents. That is, technically the only thing we\'re storing is the untyped binary message;\\n`PhantomData` just enforces the principle that the binary represents some specific object that has been parsed.\\n\\nEither way, we can carefully construct something which is safe to move between threads:\\n\\n```rust\\nfn main() {\\n\\n // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else\\n\\n let deserialized = capnp::serialize::read_message(\\n &mut buffer.as_slice(),\\n capnp::message::ReaderOptions::new()\\n ).unwrap();\\n\\n let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> =\\n capnp::message::TypedReader::new(deserialized);\\n\\n // Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message\\n // (which is \'static lifetime), this is now safe\\n let handle = std::thread::spawn(move || {\\n\\n // The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader\\n // object from it\\n let point_root = point_reader.get().unwrap();\\n\\n assert_eq!(point_root.get_x(), 12);\\n\\n assert_eq!(point_root.get_y(), 14);\\n });\\n\\n handle.join().unwrap();\\n}\\n```\\n\\nAnd while we\'ve left Rust to do the dirty work of actually moving the `point_reader` into the new thread,\\nwe could also use things like [`mpsc` channels](https://doc.rust-lang.org/std/sync/mpsc/index.html) to achieve a similar effect.\\n\\nSo now we\'re able to define basic Cap\'N Proto messages, and send them all around our programs."},{"id":"2018/01/captains-cookbook-part-1","metadata":{"permalink":"/2018/01/captains-cookbook-part-1","source":"@site/blog/2018-01-16-captains-cookbok-part-1/index.mdx","title":"Captain\'s Cookbook: Project setup","description":"A basic introduction to getting started with Cap\'N Proto.","date":"2018-01-16T12:00:00.000Z","tags":[],"readingTime":7.555,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-1","title":"Captain\'s Cookbook: Project setup","date":"2018-01-16T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"},"nextItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"}},"content":"A basic introduction to getting started with Cap\'N Proto.\\n\\n\x3c!-- truncate --\x3e\\n\\nI\'ve been working a lot with [Cap\'N Proto](https://capnproto.org/) recently with Rust, but there\'s a real dearth of information\\non how to set up and get going quickly. In the interest of trying to get more people using this (because I think it\'s\\nfantastic), I\'m going to work through a couple of examples detailing what exactly should be done to get going.\\n\\nSo, what is Cap\'N Proto? It\'s a data serialization library. It has contemporaries with [Protobuf](https://developers.google.com/protocol-buffers/)\\nand [FlatBuffers](https://google.github.io/flatbuffers/), but is better compared with FlatBuffers. The whole point behind it\\nis to define a schema language and serialization format such that:\\n\\n1. Applications that do not share the same base programming language can communicate\\n2. The data and schema you use can naturally evolve over time as your needs change\\n\\nAccompanying this are typically code generators that take the schemas you define for your application and give you back\\ncode for different languages to get data to and from that schema.\\n\\nNow, what makes Cap\'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way\\nas is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.\\n\\nWe\'re going to take a look at a series of progressively more complex projects that use Cap\'N Proto in an effort to provide some\\nexamples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects.\\nIf you want to follow along, feel free. If not, I\'ve posted [the final result](https://github.com/bspeice/capnp_cookbook_1)\\nfor reference.\\n\\n## Step 1: Installing `capnp`\\n\\nThe `capnp` binary itself is needed for taking the schema files you write and turning them into a format that can be used by the\\ncode generation libraries. Don\'t ask me what that actually means, I just know that you need to make sure this is installed.\\n\\nI\'ll refer you to [Cap\'N Proto\'s installation instructions](https://capnproto.org/install.html) here. As a quick TLDR though:\\n\\n- Linux users will likely have a binary shipped by their package manager - On Ubuntu, `apt install capnproto` is enough\\n- OS X users can use [Homebrew](https://brew.sh/) as an easy install path. Just `brew install capnp`\\n- Windows users are a bit more complicated. If you\'re using [Chocolatey](https://chocolatey.org/), there\'s [a package](https://chocolatey.org/packages/capnproto/) available. If that doesn\'t work however, you need to download [a release zip](https://capnproto.org/capnproto-c++-win32-0.6.1.zip) and make sure that the `capnp.exe` binary is in your `%PATH%` environment variable\\n\\nThe way you know you\'re done with this step is if the following command works in your shell:\\n\\n```bash\\ncapnp id\\n```\\n\\n## Step 2: Starting a Cap\'N Proto Rust project\\n\\nAfter the `capnp` binary is set up, it\'s time to actually create our Rust project. Nothing terribly complex here, just a simple\\n\\n```bash\\nmkdir capnp_cookbook_1\\ncd capnp_cookbook_1\\ncargo init --bin\\n```\\n\\nWe\'ll put the following content into `Cargo.toml`:\\n\\n```\\n[package]\\nname = \\"capnp_cookbook_1\\"\\nversion = \\"0.1.0\\"\\nauthors = [\\"Bradlee Speice <bspeice@kcg.com>\\"]\\n\\n[build-dependencies]\\ncapnpc = \\"0.8\\" # 1\\n\\n[dependencies]\\ncapnp = \\"0.8\\" # 2\\n```\\n\\nThis sets up: \\n\\n1. The Rust code generator (CAPNProto Compiler)\\n2. The Cap\'N Proto runtime library (CAPNProto runtime)\\n\\nWe\'ve now got everything prepared that we need for writing a Cap\'N Proto project.\\n\\n## Step 3: Writing a basic schema\\n\\nWe\'re going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure\\nyou get familiar with how to start from a basic project.\\n\\nFirst, we\'re going to create a top-level directory for storing the schema files in:\\n\\n```bash\\n# Assuming we\'re starting from the `capnp_cookbook_1` directory created earlier\\n\\nmkdir schema\\ncd schema\\n```\\n\\nNow, we\'re going to put the following content in `point.capnp`:\\n\\n```\\n@0xab555145c708dad2;\\n\\nstruct Point {\\n x @0 :Int32;\\n y @1 :Int32;\\n}\\n```\\n\\nPretty easy, we\'ve now got structure for an object we\'ll be able to quickly encode in a binary format.\\n\\n## Step 4: Setting up the build process\\n\\nNow it\'s time to actually set up the build process to make sure that Cap\'N Proto generates the Rust code we\'ll eventually be using.\\nThis is typically done through a `build.rs` file to invoke the schema compiler.\\n\\nIn the same folder as your `Cargo.toml` file, please put the following content in `build.rs`:\\n\\n```rust\\nextern crate capnpc;\\n\\nfn main() {\\n ::capnpc::CompilerCommand::new()\\n .src_prefix(\\"schema\\") // 1\\n .file(\\"schema/point.capnp\\") // 2\\n .run().expect(\\"compiling schema\\");\\n}\\n```\\n\\nThis sets up the protocol compiler (`capnpc` from earlier) to compile the schema we\'ve built so far.\\n\\n1. Because Cap\'N Proto schema files can re-use types specified in other files, the `src_prefix()` tells the compiler\\nwhere to look for those extra files at.\\n2. We specify the schema file we\'re including by hand. In a much larger project, you could presumably build the `CompilerCommand`\\ndynamically, but we won\'t worry too much about that one for now.\\n\\n## Step 5: Running the build\\n\\nIf you\'ve done everything correctly so far, you should be able to actually build the project and see the auto-generated code.\\nRun a `cargo build` command, and if you don\'t see `cargo` complaining, you\'re doing just fine!\\n\\nSo where exactly does the generated code go to? I think it\'s critically important for people to be able to see what the generated\\ncode looks like, because you need to understand what you\'re actually programming against. The short answer is: the generated code lives\\nsomewhere in the `target/` directory.\\n\\nThe long answer is that you\'re best off running a `find` command to get the actual file path:\\n\\n```bash\\n# Assuming we\'re running from the capnp_cookbook_1 project folder\\nfind . -name point_capnp.rs\\n```\\n\\nAlternately, if the `find` command isn\'t available, the path will look something like:\\n\\n```\\n./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs\\n```\\n\\nSee if there are any paths in your target directory that look similar.\\n\\nNow, the file content looks pretty nasty. I\'ve included an example [here](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs)\\nif you aren\'t following along at home. There are a couple things I\'ll try and point out though so you can get an idea of how\\nthe schema we wrote for the \\"Point\\" message is tied to the generated code.\\n\\nFirst, the Cap\'N Proto library splits things up into `Builder` and `Reader` structs. These are best thought of the same way\\nRust separates `mut` from non-`mut` code. `Builder`s are `mut` versions of your message, and `Reader`s are immutable versions.\\n\\nFor example, the [`Builder` impl](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L90) for `point` defines [`get_x()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L105), [`set_x()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L109), [`get_y()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L113), and [`set_y()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L117) methods.\\nIn comparison, the [`Reader` impl](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L38) only defines [`get_x()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L47) and [`get_y()`](https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L51) methods.\\n\\nSo now we know that there are some `get` and `set` methods available for our `x` and `y` coordinates;\\nbut what do we actually do with those?\\n\\n## Step 6: Making a point\\n\\nSo we\'ve install Cap\'N Proto, gotten a project set up, and can generate schema code now. It\'s time to actually start building\\nCap\'N Proto messages! I\'m going to put the code you need here because it\'s small, and put some extra long comments inline. This code\\nshould go in [`src/main.rs`](https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs):\\n\\n```rust\\n// Note that we use `capnp` here, NOT `capnpc`\\nextern crate capnp;\\n\\n// We create a module here to define how we are to access the code\\n// being included.\\npub mod point_capnp {\\n // The environment variable OUT_DIR is set by Cargo, and\\n // is the location of all the code that was built as part\\n // of the codegen step.\\n // point_capnp.rs is the actual file to include\\n include!(concat!(env!(\\"OUT_DIR\\"), \\"/point_capnp.rs\\"));\\n}\\n\\nfn main() {\\n\\n // The process of building a Cap\'N Proto message is a bit tedious.\\n // We start by creating a generic Builder; it acts as the message\\n // container that we\'ll later be filling with content of our `Point`\\n let mut builder = capnp::message::Builder::new_default();\\n\\n // Because we need a mutable reference to the `builder` later,\\n // we fence off this part of the code to allow sequential mutable\\n // borrows. As I understand it, non-lexical lifetimes:\\n // https://github.com/rust-lang/rust-roadmap/issues/16\\n // will make this no longer necessary\\n {\\n // And now we can set up the actual message we\'re trying to create\\n let mut point_msg = builder.init_root::<point_capnp::point::Builder>();\\n\\n // Stuff our message with some content\\n point_msg.set_x(12);\\n\\n point_msg.set_y(14);\\n }\\n\\n // It\'s now time to serialize our message to binary. Let\'s set up a buffer for that:\\n let mut buffer = Vec::new();\\n\\n // And actually fill that buffer with our data\\n capnp::serialize::write_message(&mut buffer, &builder).unwrap();\\n\\n // Finally, let\'s deserialize the data\\n let deserialized = capnp::serialize::read_message(\\n &mut buffer.as_slice(),\\n capnp::message::ReaderOptions::new()\\n ).unwrap();\\n\\n // `deserialized` is currently a generic reader; it understands\\n // the content of the message we gave it (i.e. that there are two\\n // int32 values) but doesn\'t really know what they represent (the Point).\\n // This is where we map the generic data back into our schema.\\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\\n\\n // We can now get our x and y values back, and make sure they match\\n assert_eq!(point_reader.get_x(), 12);\\n assert_eq!(point_reader.get_y(), 14);\\n}\\n```\\n\\nAnd with that, we\'ve now got a functioning project. Here\'s the content I\'m planning to go over next as we build up\\nsome practical examples of Cap\'N Proto in action:"},{"id":"2016/11/pca-audio-compression","metadata":{"permalink":"/2016/11/pca-audio-compression","source":"@site/blog/2016-11-01-PCA-audio-compression/index.mdx","title":"PCA audio compression","description":"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.","date":"2016-11-01T12:00:00.000Z","tags":[],"readingTime":10.39,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/11/pca-audio-compression","title":"PCA audio compression","date":"2016-11-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"},"nextItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"}},"content":"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.\\n\\n\x3c!-- truncate --\x3e\\n\\nTowards a new (and pretty poor) compression scheme\\n--------------------------------------------------\\n\\nI\'m going to be working with some audio data for a while as I get prepared for a term project this semester. I\'ll be working (with a partner) to design a system for separating voices from music. Given my total lack of experience with [Digital Signal Processing][1] I figured that now was as good a time as ever to work on a couple of fun projects that would get me back up to speed.\\n\\nThe first project I want to work on: Designing a new compression scheme for audio data.\\n\\nA Brief Introduction to Audio Compression\\n-----------------------------------------\\n\\nAudio files when uncompressed (files ending with `.wav`) are huge. Like, 10.5 Megabytes per minute huge. Storage is cheap these days, but that\'s still an incredible amount of data that we don\'t really need. Instead, we\'d like to compress that data so that it\'s not taking up so much space. There are broadly two ways to accomplish this:\\n\\n1. Lossless compression - Formats like [FLAC][2], [ALAC][3], and [Monkey\'s Audio (.ape)][4] all go down this route. The idea is that when you compress and uncompress a file, you get exactly the same as what you started with.\\n\\n2. Lossy compression - Formats like [MP3][5], [Ogg][6], and [AAC (`.m4a`)][7] are far more popular, but make a crucial tradeoff: We can reduce the file size even more during compression, but the decompressed file won\'t be the same.\\n\\nThere is a fundamental tradeoff at stake: Using lossy compression sacrifices some of the integrity of the resulting file to save on storage space. Most people (I personally believe it\'s everybody) can\'t hear the difference, so this is an acceptable tradeoff. You have files that take up a 10<sup>th</sup> of the space, and nobody can tell there\'s a difference in audio quality.\\n\\nA PCA-based Compression Scheme\\n------------------------------\\n\\nWhat I want to try out is a [PCA][8] approach to encoding audio. The PCA technique comes from Machine Learning, where it is used for a process called [Dimensionality Reduction][9]. Put simply, the idea is the same as lossy compression: if we can find a way that represents the data well enough, we can save on space. There are a lot of theoretical concerns that lead me to believe this compression style will not end well, but I\'m interested to try it nonetheless.\\n\\nPCA works as follows: Given a dataset with a number of features, I find a way to approximate those original features using some \\"new features\\" that are statistically as close as possible to the original ones. This is comparable to a scheme like MP3: Given an original signal, I want to find a way of representing it that gets approximately close to what the original was. The difference is that PCA is designed for statistical data, and not signal data. But we won\'t let that stop us.\\n\\nThe idea is as follows: Given a signal, reshape it into 1024 columns by however many rows are needed (zero-padded if necessary). Run the PCA algorithm, and do dimensionality reduction with a couple different settings. The number of components I choose determines the quality: If I use 1024 components, I will essentially be using the original signal. If I use a smaller number of components, I start losing some of the data that was in the original file. This will give me an idea of whether it\'s possible to actually build an encoding scheme off of this, or whether I\'m wasting my time.\\n\\nRunning the Algorithm\\n---------------------\\n\\nThe audio I will be using comes from the song [Tabulasa][10], by [Broke for Free][11]. I\'ll be loading in the audio signal to Python and using [Scikit-Learn][12] to actually run the PCA algorithm.\\n\\nWe first need to convert the FLAC file I have to a WAV:\\n\\n[1]: https://en.wikipedia.org/wiki/Digital_signal_processing\\n[2]: https://en.wikipedia.org/wiki/FLAC\\n[3]: https://en.wikipedia.org/wiki/Apple_Lossless\\n[4]: https://en.wikipedia.org/wiki/Monkey%27s_Audio\\n[5]: https://en.wikipedia.org/wiki/MP3\\n[6]: https://en.wikipedia.org/wiki/Vorbis\\n[7]: https://en.wikipedia.org/wiki/Advanced_Audio_Coding\\n[8]: https://en.wikipedia.org/wiki/Principal_component_analysis\\n[9]: https://en.wikipedia.org/wiki/Dimensionality_reduction\\n[10]: https://brokeforfree.bandcamp.com/track/tabulasa\\n[11]: https://brokeforfree.bandcamp.com/album/xxvii\\n[12]: http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html#sklearn.decomposition.PCA\\n\\n\\n```python\\n!ffmpeg -hide_banner -loglevel panic -i \\"Broke For Free/XXVII/01 Tabulasa.flac\\" \\"Tabulasa.wav\\" -c wav\\n```\\n\\nThen, let\'s go ahead and load a small sample so you can hear what is going on.\\n\\n\\n```python\\nfrom IPython.display import Audio\\nfrom scipy.io import wavfile\\n\\nsamplerate, tabulasa = wavfile.read(\'Tabulasa.wav\')\\n\\nstart = samplerate * 14 # 10 seconds in\\nend = start + samplerate * 10 # 5 second duration\\nAudio(data=tabulasa[start:end, 0], rate=samplerate)\\n```\\n\\nimport wav1 from \\"./1.wav\\";\\n\\n<audio controls src={wav1}/>\\n\\nNext, we\'ll define the code we will be using to do PCA. It\'s very short, as the PCA algorithm is very simple.\\n\\n\\n```python\\nfrom sklearn.decomposition import PCA\\nimport numpy as np\\n\\ndef pca_reduce(signal, n_components, block_size=1024):\\n \\n # First, zero-pad the signal so that it is divisible by the block_size\\n samples = len(signal)\\n hanging = block_size - np.mod(samples, block_size)\\n padded = np.lib.pad(signal, (0, hanging), \'constant\', constant_values=0)\\n \\n # Reshape the signal to have 1024 dimensions\\n reshaped = padded.reshape((len(padded) // block_size, block_size))\\n \\n # Second, do the actual PCA process\\n pca = PCA(n_components=n_components)\\n pca.fit(reshaped)\\n \\n transformed = pca.transform(reshaped)\\n reconstructed = pca.inverse_transform(transformed).reshape((len(padded)))\\n return pca, transformed, reconstructed\\n```\\n\\nNow that we\'ve got our functions set up, let\'s try actually running something. First, we\'ll use `n_components == block_size`, which implies that we should end up with the same signal we started with.\\n\\n\\n```python\\ntabulasa_left = tabulasa[:,0]\\n\\n_, _, reconstructed = pca_reduce(tabulasa_left, 1024, 1024)\\n\\nAudio(data=reconstructed[start:end], rate=samplerate)\\n```\\n\\nimport wav2 from \\"./2.wav\\";\\n\\n<audio controls src={wav2}/>\\n\\nOK, that does indeed sound like what we originally had. Let\'s drastically cut down the number of components we\'re doing this with as a sanity check: the audio quality should become incredibly poor.\\n\\n\\n```python\\n_, _, reconstructed = pca_reduce(tabulasa_left, 32, 1024)\\n\\nAudio(data=reconstructed[start:end], rate=samplerate)\\n```\\n\\nimport wav3 from \\"./3.wav\\";\\n\\n<audio controls src={wav3}/>\\n\\nAs expected, our reconstructed audio does sound incredibly poor! But there\'s something else very interesting going on here under the hood. Did you notice that the bassline comes across very well, but that there\'s no midrange or treble? The drums are almost entirely gone.\\n\\n[Drop the (Treble)][13]\\n-----------------------\\n\\nIt will help to understand PCA more fully when trying to read this part, but I\'ll do my best to break it down. PCA tries to find a way to best represent the dataset using \\"components.\\" Think of each \\"component\\" as containing some of the information you need in order to reconstruct the full audio. For example, you might have a \\"low frequency\\" component that contains all the information you need in order to hear the bassline. There might be other components that explain the high frequency things like singers, or melodies, that you also need.\\n\\nWhat makes PCA interesting is that it attempts to find the \\"most important\\" components in explaining the signal. In a signal processing world, this means that PCA is trying to find the signal amongst the noise in your data. In our case, this means that PCA, when forced to work with small numbers of components, will chuck out the noisy components first. It\'s doing it\'s best job to reconstruct the signal, but it has to make sacrifices somewhere.\\n\\nSo I\'ve mentioned that PCA identifies the \\"noisy\\" components in our dataset. This is equivalent to saying that PCA removes the \\"high frequency\\" components in this case: it\'s very easy to represent a low-frequency signal like a bassline. It\'s far more difficult to represent a high-frequency signal because it\'s changing all the time. When you force PCA to make a tradeoff by using a small number of components, the best it can hope to do is replicate the low-frequency sections and skip the high-frequency things.\\n\\nThis is a very interesting insight, and it also has echos (pardon the pun) of how humans understand music in general. Other encoding schemes (like MP3, etc.) typically chop off a lot of the high-frequency range as well. There is typically a lot of high-frequency noise in audio that is nearly impossible to hear, so it\'s easy to remove it without anyone noticing. PCA ends up doing something similar, and while that certainly wasn\'t the intention, it is an interesting effect.\\n\\n## A More Realistic Example\\n\\nSo we\'ve seen the edge cases so far: Using a large number of components results in audio very close to the original, and using a small number of components acts as a low-pass filter. How about we develop something that sounds \\"good enough\\" in practice, that we can use as a benchmark for size? We\'ll use ourselves as judges of audio quality, and build another function to help us estimate how much space we need to store everything in.\\n\\n[13]: https://youtu.be/Ua0KpfJsxKo?t=1m17s\\n\\n\\n```python\\nfrom bz2 import compress\\nimport pandas as pd\\n\\ndef raw_estimate(transformed, pca):\\n # We assume that we\'ll be storing things as 16-bit WAV,\\n # meaning two bytes per sample\\n signal_bytes = transformed.tobytes()\\n # PCA stores the components as floating point, we\'ll assume\\n # that means 32-bit floats, so 4 bytes per element\\n component_bytes = transformed.tobytes()\\n \\n # Return a result in megabytes\\n return (len(signal_bytes) + len(component_bytes)) / (2**20)\\n\\n# Do an estimate for lossless compression applied on top of our\\n# PCA reduction\\ndef bz2_estimate(transformed, pca):\\n bytestring = transformed.tobytes() + b\';\' + pca.components_.tobytes()\\n compressed = compress(bytestring)\\n return len(compressed) / (2**20)\\n\\ncompression_attempts = [\\n (1, 1),\\n (1, 2),\\n (1, 4),\\n (4, 32),\\n (16, 256),\\n (32, 256),\\n (64, 256),\\n (128, 1024),\\n (256, 1024),\\n (512, 1024),\\n (128, 2048),\\n (256, 2048),\\n (512, 2048),\\n (1024, 2048)\\n]\\n\\ndef build_estimates(signal, n_components, block_size):\\n pca, transformed, recon = pca_reduce(tabulasa_left, n_components, block_size)\\n raw_pca_estimate = raw_estimate(transformed, pca)\\n bz2_pca_estimate = bz2_estimate(transformed, pca)\\n raw_size = len(recon.tobytes()) / (2**20)\\n return raw_size, raw_pca_estimate, bz2_pca_estimate\\n\\npca_compression_results = pd.DataFrame([\\n build_estimates(tabulasa_left, n, bs)\\n for n, bs in compression_attempts\\n ])\\n\\npca_compression_results.columns = [\\"Raw\\", \\"PCA\\", \\"PCA w/ BZ2\\"]\\npca_compression_results.index = compression_attempts\\npca_compression_results\\n```\\n\\n<div>\\n<table>\\n <thead>\\n <tr>\\n <th></th>\\n <th>Raw</th>\\n <th>PCA</th>\\n <th>PCA w/ BZ2</th>\\n </tr>\\n </thead>\\n <tbody>\\n <tr>\\n <th>(1, 1)</th>\\n <td>69.054298</td>\\n <td>138.108597</td>\\n <td>16.431797</td>\\n </tr>\\n <tr>\\n <th>(1, 2)</th>\\n <td>69.054306</td>\\n <td>69.054306</td>\\n <td>32.981380</td>\\n </tr>\\n <tr>\\n <th>(1, 4)</th>\\n <td>69.054321</td>\\n <td>34.527161</td>\\n <td>16.715032</td>\\n </tr>\\n <tr>\\n <th>(4, 32)</th>\\n <td>69.054443</td>\\n <td>17.263611</td>\\n <td>8.481735</td>\\n </tr>\\n <tr>\\n <th>(16, 256)</th>\\n <td>69.054688</td>\\n <td>8.631836</td>\\n <td>4.274846</td>\\n </tr>\\n <tr>\\n <th>(32, 256)</th>\\n <td>69.054688</td>\\n <td>17.263672</td>\\n <td>8.542909</td>\\n </tr>\\n <tr>\\n <th>(64, 256)</th>\\n <td>69.054688</td>\\n <td>34.527344</td>\\n <td>17.097543</td>\\n </tr>\\n <tr>\\n <th>(128, 1024)</th>\\n <td>69.054688</td>\\n <td>17.263672</td>\\n <td>9.430644</td>\\n </tr>\\n <tr>\\n <th>(256, 1024)</th>\\n <td>69.054688</td>\\n <td>34.527344</td>\\n <td>18.870387</td>\\n </tr>\\n <tr>\\n <th>(512, 1024)</th>\\n <td>69.054688</td>\\n <td>69.054688</td>\\n <td>37.800940</td>\\n </tr>\\n <tr>\\n <th>(128, 2048)</th>\\n <td>69.062500</td>\\n <td>8.632812</td>\\n <td>6.185015</td>\\n </tr>\\n <tr>\\n <th>(256, 2048)</th>\\n <td>69.062500</td>\\n <td>17.265625</td>\\n <td>12.366942</td>\\n </tr>\\n <tr>\\n <th>(512, 2048)</th>\\n <td>69.062500</td>\\n <td>34.531250</td>\\n <td>24.736506</td>\\n </tr>\\n <tr>\\n <th>(1024, 2048)</th>\\n <td>69.062500</td>\\n <td>69.062500</td>\\n <td>49.517493</td>\\n </tr>\\n </tbody>\\n</table>\\n</div>\\n\\n\\n\\nAs we can see, there are a couple of instances where we do nearly 20 times better on storage space than the uncompressed file. Let\'s here what that sounds like:\\n\\n\\n```python\\n_, _, reconstructed = pca_reduce(tabulasa_left, 16, 256)\\nAudio(data=reconstructed[start:end], rate=samplerate)\\n```\\n\\nimport wav4 from \\"./4.wav\\";\\n\\n<audio controls src={wav4}/>\\n\\nIt sounds incredibly poor though. Let\'s try something that\'s a bit more realistic:\\n\\n\\n```python\\n_, _, reconstructed = pca_reduce(tabulasa_left, 1, 4)\\nAudio(data=reconstructed[start:end], rate=samplerate)\\n```\\n\\nimport wav5 from \\"./5.wav\\";\\n\\n<audio controls src={wav5}/>\\n\\nAnd just out of curiosity, we can try something that has the same ratio of components to block size. This should be close to an apples-to-apples comparison.\\n\\n\\n```python\\n_, _, reconstructed = pca_reduce(tabulasa_left, 64, 256)\\nAudio(data=reconstructed[start:end], rate=samplerate)\\n```\\n\\nimport wav6 from \\"./6.wav\\"\\n\\n<audio controls src={wav6}/>\\n\\nThe smaller block size definitely has better high-end response, but I personally think the larger block size sounds better overall.\\n\\n## Conclusions\\n\\nSo, what do I think about audio compression using PCA?\\n\\nStrangely enough, it actually works pretty well relative to what I expected. That said, it\'s a terrible idea in general.\\n\\nFirst off, you don\'t really save any space. The component matrix needed to actually run the PCA algorithm takes up a lot of space on its own, so it\'s very difficult to save space without sacrificing a huge amount of audio quality. And even then, codecs like AAC sound very nice even at bitrates that this PCA method could only dream of.\\n\\nSecond, there\'s the issue of audio streaming. PCA relies on two components: the datastream, and a matrix used to reconstruct the original signal. While it is easy to stream the data, you can\'t stream that matrix. And even if you divided the stream up into small blocks to give you a small matrix, you must guarantee that the matrix arrives; if you don\'t have that matrix, the data stream will make no sense whatsoever.\\n\\nAll said, this was an interesting experiment. It\'s really cool seeing PCA used for signal analysis where I haven\'t seen it applied before, but I don\'t think it will lead to any practical results. Look forward to more signal processing stuff in the future!"},{"id":"2016/10/rustic-repodcasting","metadata":{"permalink":"/2016/10/rustic-repodcasting","source":"@site/blog/2016-10-22-rustic-repodcasting/index.mdx","title":"A Rustic re-podcasting server","description":"Learning Rust by fire (it sounds better than learning by corrosion)","date":"2016-10-22T12:00:00.000Z","tags":[],"readingTime":10.405,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/10/rustic-repodcasting","title":"A Rustic re-podcasting server","date":"2016-10-22T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"},"nextItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"}},"content":"Learning Rust by fire (it sounds better than learning by corrosion)\\n\\n\x3c!-- truncate --\x3e\\n\\nI listen to a lot of Drum and Bass music, because it\'s beautiful music. And\\nthere\'s a particular site, [Bassdrive.com](http://bassdrive.com/) that hosts\\na lot of great content. Specifically, the\\n[archives](http://archives.bassdrivearchive.com/) section of the site has a\\nlist of the past shows that you can download and listen to. The issue is, it\'s\\njust a [giant list of links to download](http://archives.bassdrivearchive.com/6%20-%20Saturday/Electronic%20Warfare%20-%20The%20Overfiend/). I\'d really like\\nthis in a podcast format to take with me on the road, etc.\\n\\nSo I wrote the [elektricity](https://github.com/bspeice/elektricity) web\\napplication to actually accomplish all that. Whenever you request a feed, it\\ngoes out to Bassdrive, processes all the links on a page, and serves up some\\nfresh, tasty RSS to satisfy your ears. I hosted it on Heroku using the free\\ntier because it\'s really not resource-intensive at all.\\n\\n**The issue so far** is that I keep running out of free tier hours during a\\nmonth because my podcasting application likes to have a server scan for new\\nepisodes constantly. Not sure why it\'s doing that, but I don\'t have a whole\\nlot of control over it. It\'s a phenomenal application otherwise.\\n\\n**My (over-engineered) solution**: Re-write the application using the\\n[Rust](https://www.rust-lang.org/en-US/) programming language. I\'d like to run\\nthis on a small hacker board I own, and doing this in Rust would allow me to\\neasily cross-compile it. Plus, I\'ve been very interested in the Rust language\\nfor a while and this would be a great opportunity to really learn it well.\\nThe code is available [here](https://github.com/bspeice/nutone) as development\\nprogresses.\\n\\n## The Setup\\n\\nWe\'ll be using the [iron](http://ironframework.io/) library to handle the\\nserver, and [hyper](http://hyper.rs/) to fetch the data we need from elsewhere\\non the interwebs. [HTML5Ever](http://doc.servo.org/html5ever/index.html) allows\\nus to ingest the content that will be coming from Bassdrive, and finally,\\noutput is done with [handlebars-rust](http://sunng87.github.io/handlebars-rust/handlebars/index.html).\\n\\nIt will ultimately be interesting to see how much more work must be done to\\nactually get this working over another language like Python. Coming from a\\ndynamic state of mind it\'s super easy to just chain stuff together, ship it out,\\nand call it a day. I think I\'m going to end up getting much dirtier trying to\\nwrite all of this out.\\n\\n## Issue 1: Strings\\n\\nStrings in Rust are hard. I acknowledge Python can get away with some things\\nthat make strings super easy (and Python 3 has gotten better at cracking down\\non some bad cases, `str <-> bytes` specifically), but Rust is hard.\\n\\nLet\'s take for example the `404` error handler I\'m trying to write. The result\\nshould be incredibly simple: All I want is to echo back\\n`Didn\'t find URL: <url>`. Shouldn\'t be that hard right? In Python I\'d just do\\nsomething like:\\n\\n```python\\ndef echo_handler(request):\\n return \\"You\'re visiting: {}\\".format(request.uri)\\n```\\n\\nAnd we\'d call it a day. Rust isn\'t so simple. Let\'s start with the trivial\\nexamples people post online:\\n\\n```rust\\nfn hello_world(req: &mut Request) -> IronResult<Response> {\\n Ok(Response::with((status::Ok, \\"You found the server!\\")))\\n}\\n```\\n\\nDoesn\'t look too bad right? In fact, it\'s essentially the same as the Python\\nversion! All we need to do is just send back a string of some form. So, we\\nlook up the documentation for [`Request`](http://ironframework.io/doc/iron/request/struct.Request.html) and see a `url` field that will contain\\nwhat we want. Let\'s try the first iteration:\\n\\n```rust\\nfn hello_world(req: &mut Request) -> IronResult<Response> {\\n Ok(Response::with((status::Ok, \\"You found the URL: \\" + req.url)))\\n}\\n```\\n\\nWhich yields the error:\\n\\n```\\n error[E0369]: binary operation `+` cannot be applied to type `&\'static str`\\n```\\n\\nOK, what\'s going on here? Time to start Googling for [\\"concatenate strings in Rust\\"](https://www.google.com/#q=concatenate+strings+in+rust). That\'s what we\\nwant to do right? Concatenate a static string and the URL.\\n\\nAfter Googling, we come across a helpful [`concat!`](https://doc.rust-lang.org/std/macro.concat!.html) macro that looks really nice! Let\'s try that one:\\n\\n```rust\\nfn hello_world(req: &mut Request) -> IronResult<Response> {\\n Ok(Response::with((status::Ok, concat!(\\"You found the URL: \\", req.url))))\\n}\\n```\\n\\nAnd the error:\\n\\n```\\n error: expected a literal\\n```\\n\\nTurns out Rust actually blows up because the `concat!` macro expects us to know\\nat compile time what `req.url` is. Which, in my outsider opinion, is a bit\\nstrange. `println!` and `format!`, etc., all handle values they don\'t know at\\ncompile time. Why can\'t `concat!`? By any means, we need a new plan of attack.\\nHow about we try formatting strings?\\n\\n```rust\\nfn hello_world(req: &mut Request) -> IronResult<Response> {\\n Ok(Response::with((status::Ok, format!(\\"You found the URL: {}\\", req.url))))\\n}\\n```\\n\\nAnd at long last, it works. Onwards!\\n\\n## Issue 2: Fighting with the borrow checker\\n\\nRust\'s single coolest feature is how the compiler can guarantee safety in your\\nprogram. As long as you don\'t use `unsafe` pointers in Rust, you\'re guaranteed\\nsafety. And not having truly manual memory management is really cool; I\'m\\ntotally OK with never having to write `malloc()` again.\\n\\nThat said, even [the Rust documentation](https://doc.rust-lang.org/book/ownership.html) makes a specific note:\\n\\n> Many new users to Rust experience something we like to call\\n> \u2018fighting with the borrow checker\u2019, where the Rust compiler refuses to\\n> compile a program that the author thinks is valid.\\n\\nIf you have to put it in the documentation, it\'s not a helpful note:\\nit\'s hazing.\\n\\nSo now that we have a handler which works with information from the request, we\\nwant to start making something that looks like an actual web application.\\nThe router provided by `iron` isn\'t terribly difficult so I won\'t cover it.\\nInstead, the thing that had me stumped for a couple hours was trying to\\ndynamically create routes.\\n\\nThe unfortunate thing with Rust (in my limited experience at the moment) is that\\nthere is a severe lack of non-trivial examples. Using the router is easy when\\nyou want to give an example of a static function. But how do you you start\\nworking on things that are a bit more complex?\\n\\nWe\'re going to cover that here. Our first try: creating a function which returns\\nother functions. This is a principle called [currying](http://stackoverflow.com/a/36321/1454178). We set up a function that allows us to keep some data in scope\\nfor another function to come later.\\n\\n```rust\\nfn build_handler(message: String) -> Fn(&mut Request) -> IronResult<Response> {\\n move |_: &mut Request| {\\n Ok(Response::with((status::Ok, message)))\\n }\\n}\\n```\\n\\nWe\'ve simply set up a function that returns another anonymous function with the\\n`message` parameter scoped in. If you compile this, you get not 1, not 2, but 5\\nnew errors. 4 of them are the same though:\\n\\n```\\n error[E0277]: the trait bound `for<\'r, \'r, \'r> std::ops::Fn(&\'r mut iron::Request<\'r, \'r>) -> std::result::Result<iron::Response, iron::IronError> + \'static: std::marker::Sized` is not satisfied\\n```\\n\\n...oookay. I for one, am not going to spend time trying to figure out what\'s\\ngoing on there.\\n\\nAnd it is here that I will save the audience many hours of frustrated effort.\\nAt this point, I decided to switch from `iron` to pure `hyper` since using\\n`hyper` would give me a much simpler API. All I would have to do is build a\\nfunction that took two parameters as input, and we\'re done. That said, it\\nultimately posed many more issues because I started getting into a weird fight\\nwith the `\'static` [lifetime](https://doc.rust-lang.org/book/lifetimes.html)\\nand being a Rust newbie I just gave up on trying to understand it.\\n\\nInstead, we will abandon (mostly) the curried function attempt, and instead\\ntake advantage of something Rust actually intends us to use: `struct` and\\n`trait`.\\n\\nRemember when I talked about a lack of non-trivial examples on the Internet?\\nThis is what I was talking about. I could only find *one* example of this\\navailable online, and it was incredibly complex and contained code we honestly\\ndon\'t need or care about. There was no documentation of how to build routes that\\ndidn\'t use static functions, etc. But, I\'m assuming you don\'t really care about\\nmy whining, so let\'s get to it.\\n\\nThe `iron` documentation mentions the [`Handler`](http://ironframework.io/doc/iron/middleware/trait.Handler.html) trait as being something we can implement.\\nDoes the function signature for that `handle()` method look familiar? It\'s what\\nwe\'ve been working with so far.\\n\\nThe principle is that we need to define a new `struct` to hold our data, then\\nimplement that `handle()` method to return the result. Something that looks\\nlike this might do:\\n\\n```rust\\nstruct EchoHandler {\\n message: String\\n}\\n\\nimpl Handler for EchoHandler {\\n fn handle(&self, _: &mut Request) -> IronResult<Response> {\\n Ok(Response::with((status::Ok, self.message)))\\n }\\n}\\n\\n// Later in the code when we set up the router...\\nlet echo = EchoHandler {\\n message: \\"Is it working yet?\\"\\n}\\nrouter.get(\\"/\\", echo.handle, \\"index\\");\\n```\\n\\nWe attempt to build a struct, and give its `handle` method off to the router\\nso the router knows what to do.\\n\\nYou guessed it, more errors:\\n\\n```\\n error: attempted to take value of method `handle` on type `EchoHandler`\\n```\\n\\nNow, the Rust compiler is actually a really nice fellow, and offers us help:\\n\\n```\\n help: maybe a `()` to call it is missing? If not, try an anonymous function\\n```\\n\\nWe definitely don\'t want to call that function, so maybe try an anonymous\\nfunction as it recommends?\\n\\n```rust\\nrouter.get(\\"/\\", |req: &mut Request| echo.handle(req), \\"index\\");\\n```\\n\\nAnother error:\\n\\n```\\n error[E0373]: closure may outlive the current function, but it borrows `echo`, which is owned by the current function\\n```\\n\\nAnother helpful message:\\n\\n```\\n help: to force the closure to take ownership of `echo` (and any other referenced variables), use the `move` keyword\\n```\\n\\nWe\'re getting closer though! Let\'s implement this change:\\n\\n```rust\\nrouter.get(\\"/\\", move |req: &mut Request| echo.handle(req), \\"index\\");\\n```\\n\\nAnd here\'s where things get strange:\\n\\n```\\n error[E0507]: cannot move out of borrowed content\\n --\x3e src/main.rs:18:40\\n |\\n 18 | Ok(Response::with((status::Ok, self.message)))\\n | ^^^^ cannot move out of borrowed content\\n```\\n\\nNow, this took me another couple hours to figure out. I\'m going to explain it,\\nbut **keep this in mind: Rust only allows one reference at a time** (exceptions\\napply of course).\\n\\nWhen we attempt to use `self.message` as it has been created in the earlier\\n`struct`, we essentially are trying to give it away to another piece of code.\\nRust\'s semantics then state that *we may no longer access it* unless it is\\nreturned to us (which `iron`\'s code does not do). There are two ways to fix\\nthis:\\n\\n1. Only give away references (i.e. `&self.message` instead of `self.message`)\\ninstead of transferring ownership\\n2. Make a copy of the underlying value which will be safe to give away\\n\\nI didn\'t know these were the two options originally, so I hope this helps the\\naudience out. Because `iron` won\'t accept a reference, we are forced into the\\nsecond option: making a copy. To do so, we just need to change the function\\nto look like this:\\n\\n```rust\\nOk(Response::with((status::Ok, self.message.clone())))\\n```\\n\\nNot so bad, huh? My only complaint is that it took so long to figure out exactly\\nwhat was going on.\\n\\nAnd now we have a small server that we can configure dynamically. At long last.\\n\\n> Final sidenote: You can actually do this without anonymous functions. Just\\n> change the router line to:\\n> `router.get(\\"/\\", echo, \\"index\\");`\\n>\\n> Rust\'s type system seems to figure out that we want to use the `handle()` method.\\n\\n## Conclusion\\n\\nAfter a good long days\' work, we now have the routing functionality set up on\\nour application. We should be able to scale this pretty well in the future:\\nthe RSS content we need to deliver in the future can be treated as a string, so\\nthe building blocks are in place.\\n\\nThere are two important things I learned starting with Rust today:\\n\\n1. Rust is a new language, and while the code is high-quality, the mindshare is coming.\\n2. I\'m a terrible programmer.\\n\\nNumber 1 is pretty obvious and not surprising to anyone. Number two caught me\\noff guard. I\'ve gotten used to having either a garbage collector (Java, Python,\\netc.) or playing a little fast and loose with scoping rules (C, C++). You don\'t\\nhave to worry about object lifetime there. With Rust, it\'s forcing me to fully\\nunderstand and use well the memory in my applications. In the final mistake I\\nfixed (using `.clone()`) I would have been fine in C++ to just give away that\\nreference and never use it again. I wouldn\'t have run into a \\"use-after-free\\"\\nerror, but I would have potentially been leaking memory. Rust forced me to be\\nincredibly precise about how I use it.\\n\\nAll said I\'m excited for using Rust more. I think it\'s super cool, it\'s just\\ngoing to take me a lot longer to do this than I originally thought."},{"id":"2016/06/event-studies-and-earnings-releases","metadata":{"permalink":"/2016/06/event-studies-and-earnings-releases","source":"@site/blog/2016-06-08-event-studies-and-earnings-releases/index.mdx","title":"Event studies and earnings releases","description":"Or, being suspicious of market insiders.","date":"2016-06-08T12:00:00.000Z","tags":[],"readingTime":16.01,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/06/event-studies-and-earnings-releases","title":"Event studies and earnings releases","date":"2016-06-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"},"nextItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"}},"content":"Or, being suspicious of market insiders.\\n\\n\x3c!-- truncate --\x3e\\n\\n## The Market Just Knew\\n\\nI recently saw two examples of stock charts that have kept me thinking for a while. And now that the semester is complete, I finally have enough time to really look at them and give them the treatment they deserve. The first is good old Apple:\\n\\n\\n<details>\\n<summary>Code</summary>\\n\\n```python\\nfrom secrets import QUANDL_KEY\\nimport matplotlib.pyplot as plt\\nfrom matplotlib.dates import date2num\\nfrom matplotlib.finance import candlestick_ohlc\\nfrom matplotlib.dates import DateFormatter, WeekdayLocator,\\\\\\n DayLocator, MONDAY\\nimport quandl\\nfrom datetime import datetime\\nimport pandas as pd\\n%matplotlib inline\\n\\ndef fetch_ticker(ticker, start, end):\\n # Quandl is currently giving me issues with returning\\n # the entire dataset and not slicing server-side.\\n # So instead, we\'ll do it client-side!\\n q_format = \'%Y-%m-%d\'\\n ticker_data = quandl.get(\'YAHOO/\' + ticker,\\n start_date=start.strftime(q_format),\\n end_date=end.strftime(q_format),\\n authtoken=QUANDL_KEY)\\n return ticker_data\\n\\ndef ohlc_dataframe(data, ax=None):\\n # Much of this code re-used from:\\n # http://matplotlib.org/examples/pylab_examples/finance_demo.html\\n if ax is None:\\n f, ax = plt.subplots()\\n \\n vals = [(date2num(date), *(data.loc[date]))\\n for date in data.index]\\n candlestick_ohlc(ax, vals)\\n \\n mondays = WeekdayLocator(MONDAY)\\n alldays = DayLocator()\\n weekFormatter = DateFormatter(\'%b %d\')\\n ax.xaxis.set_major_locator(mondays)\\n ax.xaxis.set_minor_locator(alldays)\\n ax.xaxis.set_major_formatter(weekFormatter)\\n return ax\\n```\\n</details>\\n\\n```python\\nAAPL = fetch_ticker(\'AAPL\', datetime(2016, 3, 1), datetime(2016, 5, 1))\\nax = ohlc_dataframe(AAPL)\\nplt.vlines(date2num(datetime(2016, 4, 26, 12)),\\n ax.get_ylim()[0], ax.get_ylim()[1],\\n color=\'b\',\\n label=\'Earnings Release\')\\nplt.legend(loc=3)\\nplt.title(\\"Apple Price 3/1/2016 - 5/1/2016\\");\\n```\\n\\n![png](_notebook_files/_notebook_3_0.png)\\n\\nThe second chart is from Facebook:\\n\\n```python\\nFB = fetch_ticker(\'FB\', datetime(2016, 3, 1), datetime(2016, 5, 5))\\nax = ohlc_dataframe(FB)\\nplt.vlines(date2num(datetime(2016, 4, 27, 12)),\\n ax.get_ylim()[0], ax.get_ylim()[1],\\n color=\'b\', label=\'Earnings Release\')\\nplt.title(\'Facebook Price 3/5/2016 - 5/5/2016\')\\nplt.legend(loc=2);\\n```\\n \\n![png](_notebook_files/_notebook_5_0.png)\\n \\nThese two charts demonstrate two very specific phonomena: how the market prepares for earnings releases. Let\'s look at those charts again, but with some extra information. As we\'re about the see, the market \\"knew\\" in advance that Apple was going to perform poorly. The market expected that Facebook was going to perform poorly, and instead shot the lights out. Let\'s see that trend in action:\\n\\n<details>\\n<summary>Code</summary>\\n\\n```python\\ndef plot_hilo(ax, start, end, data):\\n ax.plot([date2num(start), date2num(end)],\\n [data.loc[start][\'High\'], data.loc[end][\'High\']],\\n color=\'b\')\\n ax.plot([date2num(start), date2num(end)],\\n [data.loc[start][\'Low\'], data.loc[end][\'Low\']],\\n color=\'b\')\\n\\nf, axarr = plt.subplots(1, 2)\\n\\nax_aapl = axarr[0]\\nax_fb = axarr[1]\\n\\n# Plot the AAPL trend up and down\\nohlc_dataframe(AAPL, ax=ax_aapl)\\nplot_hilo(ax_aapl, datetime(2016, 3, 1), datetime(2016, 4, 15), AAPL)\\nplot_hilo(ax_aapl, datetime(2016, 4, 18), datetime(2016, 4, 26), AAPL)\\nax_aapl.vlines(date2num(datetime(2016, 4, 26, 12)),\\n ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],\\n color=\'g\', label=\'Earnings Release\')\\nax_aapl.legend(loc=2)\\nax_aapl.set_title(\'AAPL Price History\')\\n\\n# Plot the FB trend down and up\\nohlc_dataframe(FB, ax=ax_fb)\\nplot_hilo(ax_fb, datetime(2016, 3, 30), datetime(2016, 4, 27), FB)\\nplot_hilo(ax_fb, datetime(2016, 4, 28), datetime(2016, 5, 5), FB)\\nax_fb.vlines(date2num(datetime(2016, 4, 27, 12)),\\n ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],\\n color=\'g\', label=\'Earnings Release\')\\nax_fb.legend(loc=2)\\nax_fb.set_title(\'FB Price History\')\\n\\nf.set_size_inches(18, 6)\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_7_0.png)\\n\\nAs we can see above, the market broke a prevailing trend on Apple in order to go down, and ultimately predict the earnings release. For Facebook, the opposite happened. While the trend was down, the earnings were fantastic and the market corrected itself much higher.\\n\\n## Formulating the Question\\n\\nWhile these are two specific examples, there are plenty of other examples you could cite one way or another. Even if the preponderance of evidence shows that the market correctly predicts earnings releases, we need not accuse people of collusion; for a company like Apple with many suppliers we can generally forecast how Apple has done based on those same suppliers.\\n\\nThe question then, is this: **how well does the market predict the earnings releases?** It\'s an incredibly broad question that I want to disect in a couple of different ways:\\n\\n1. Given a stock that has been trending down over the past N days before an earnings release, how likely does it continue downward after the release?\\n2. Given a stock trending up, how likely does it continue up?\\n3. Is there a difference in accuracy between large- and small-cap stocks?\\n4. How often, and for how long, do markets trend before an earnings release?\\n\\n**I want to especially thank Alejandro Saltiel for helping me retrieve the data.** He\'s great. And now for all of the interesting bits.\\n\\n## Event Studies\\n\\nBefore we go too much further, I want to introduce the actual event study. Each chart intends to capture a lot of information and present an easy-to-understand pattern:\\n\\n<details>\\n<summary>Code</summary>\\n\\n```python\\nimport numpy as np\\nimport pandas as pd\\nfrom pandas.tseries.holiday import USFederalHolidayCalendar\\nfrom pandas.tseries.offsets import CustomBusinessDay\\nfrom datetime import datetime, timedelta\\n\\n# If you remove rules, it removes them from *all* calendars\\n# To ensure we don\'t pop rules we don\'t want to, first make\\n# sure to fully copy the object\\ntrade_calendar = USFederalHolidayCalendar()\\ntrade_calendar.rules.pop(6) # Remove Columbus day\\ntrade_calendar.rules.pop(7) # Remove Veteran\'s day\\nTradeDay = lambda days: CustomBusinessDay(days, calendar=trade_calendar)\\n\\ndef plot_study(array):\\n # Given a 2-d array, we assume the event happens at index `lookback`,\\n # and create all of our summary statistics from there.\\n lookback = int((array.shape[1] - 1) / 2)\\n norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)\\n centered_data = array / norm_factor - 1\\n lookforward = centered_data.shape[1] - lookback\\n means = centered_data.mean(axis=0)\\n lookforward_data = centered_data[:,lookforward:]\\n std_dev = np.hstack([0, lookforward_data.std(axis=0)])\\n maxes = lookforward_data.max(axis=0)\\n mins = lookforward_data.min(axis=0)\\n \\n f, axarr = plt.subplots(1, 2)\\n range_begin = -lookback\\n range_end = lookforward\\n axarr[0].plot(range(range_begin, range_end), means)\\n axarr[1].plot(range(range_begin, range_end), means)\\n axarr[0].fill_between(range(0, range_end),\\n means[-lookforward:] + std_dev,\\n means[-lookforward:] - std_dev,\\n alpha=.5, label=\\"$\\\\pm$ 1 s.d.\\")\\n axarr[1].fill_between(range(0, range_end),\\n means[-lookforward:] + std_dev,\\n means[-lookforward:] - std_dev,\\n alpha=.5, label=\\"$\\\\pm$ 1 s.d.\\")\\n \\n max_err = maxes - means[-lookforward+1:]\\n min_err = means[-lookforward+1:] - mins\\n axarr[0].errorbar(range(1, range_end),\\n means[-lookforward+1:],\\n yerr=[min_err, max_err], label=\'Max & Min\')\\n axarr[0].legend(loc=2)\\n axarr[1].legend(loc=2)\\n \\n axarr[0].set_xlim((-lookback-1, lookback+1))\\n axarr[1].set_xlim((-lookback-1, lookback+1))\\n \\ndef plot_study_small(array):\\n # Given a 2-d array, we assume the event happens at index `lookback`,\\n # and create all of our summary statistics from there.\\n lookback = int((array.shape[1] - 1) / 2)\\n norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1)\\n centered_data = array / norm_factor - 1\\n lookforward = centered_data.shape[1] - lookback\\n means = centered_data.mean(axis=0)\\n lookforward_data = centered_data[:,lookforward:]\\n std_dev = np.hstack([0, lookforward_data.std(axis=0)])\\n maxes = lookforward_data.max(axis=0)\\n mins = lookforward_data.min(axis=0)\\n \\n range_begin = -lookback\\n range_end = lookforward\\n plt.plot(range(range_begin, range_end), means)\\n plt.fill_between(range(0, range_end),\\n means[-lookforward:] + std_dev,\\n means[-lookforward:] - std_dev,\\n alpha=.5, label=\\"$\\\\pm$ 1 s.d.\\")\\n \\n max_err = maxes - means[-lookforward+1:]\\n min_err = means[-lookforward+1:] - mins\\n plt.errorbar(range(1, range_end),\\n means[-lookforward+1:],\\n yerr=[min_err, max_err], label=\'Max & Min\')\\n plt.legend(loc=2)\\n plt.xlim((-lookback-1, lookback+1))\\n \\ndef fetch_event_data(ticker, events, horizon=5):\\n # Use horizon+1 to account for including the day of the event,\\n # and half-open interval - that is, for a horizon of 5,\\n # we should be including 11 events. Additionally, using the\\n # CustomBusinessDay means we automatically handle issues if\\n # for example a company reports Friday afternoon - the date\\n # calculator will turn this into a \\"Saturday\\" release, but\\n # we effectively shift that to Monday with the logic below.\\n td_back = TradeDay(horizon+1)\\n td_forward = TradeDay(horizon+1)\\n \\n start_date = min(events) - td_back\\n end_date = max(events) + td_forward\\n total_data = fetch_ticker(ticker, start_date, end_date)\\n event_data = [total_data.ix[event-td_back:event+td_forward]\\\\\\n [0:horizon*2+1]\\\\\\n [\'Adjusted Close\']\\n for event in events]\\n return np.array(event_data)\\n```\\n</details>\\n\\n```python\\n# Generate a couple of random events\\n\\nevent_dates = [datetime(2016, 5, 27) - timedelta(days=1) - TradeDay(x*20) for x in range(1, 40)]\\ndata = fetch_event_data(\'CELG\', event_dates)\\nplot_study_small(data)\\nplt.legend(loc=3)\\nplt.gcf().set_size_inches(12, 6);\\n\\n\\nplt.annotate(\'Mean price for days leading up to each event\',\\n (-5, -.01), (-4.5, .025),\\n arrowprops=dict(facecolor=\'black\', shrink=0.05))\\nplt.annotate(\'\', (-.1, .005), (-.5, .02),\\n arrowprops={\'facecolor\': \'black\', \'shrink\': .05})\\nplt.annotate(\'$\\\\pm$ 1 std. dev. each day\', (5, .055), (2.5, .085),\\n arrowprops={\'facecolor\': \'black\', \'shrink\': .05})\\nplt.annotate(\'Min/Max each day\', (.9, -.07), (-1, -.1),\\n arrowprops={\'facecolor\': \'black\', \'shrink\': .05});\\n```\\n\\n\\n \\n![png](_notebook_files/_notebook_11_0.png)\\n \\n\\n\\nAnd as a quick textual explanation as well:\\n\\n- The blue line represents the mean price for each day, represented as a percentage of the price on the \'0-day\'. For example, if we defined an \'event\' as whenever the stock price dropped for three days, we would see a decreasing blue line to the left of the 0-day.\\n- The blue shaded area represents one standard deviation above and below the mean price for each day following an event. This is intended to give us an idea of what the stock price does in general following an event.\\n- The green bars are the minimum and maximum price for each day following an event. This instructs us as to how much it\'s possible for the stock to move.\\n\\n## Event Type 1: Trending down over the past N days\\n\\nThe first type of event I want to study is how stocks perform when they\'ve been trending down over the past couple of days prior to a release. However, we need to clarify what exactly is meant by \\"trending down.\\" To do so, we\'ll use the following metric: **the midpoint between each day\'s opening and closing price goes down over a period of N days**.\\n\\nIt\'s probably helpful to have an example:\\n\\n<details>\\n<summary>Code</summary>\\n```python\\nf, axarr = plt.subplots(1, 2)\\nf.set_size_inches(18, 6)\\n\\nFB_plot = axarr[0]\\nohlc_dataframe(FB[datetime(2016, 4, 18):], FB_plot)\\n\\nFB_truncated = FB[datetime(2016, 4, 18):datetime(2016, 4, 27)]\\nmidpoint = FB_truncated[\'Open\']/2 + FB_truncated[\'Close\']/2\\nFB_plot.plot(FB_truncated.index, midpoint, label=\'Midpoint\')\\nFB_plot.vlines(date2num(datetime(2016, 4, 27, 12)),\\n ax_fb.get_ylim()[0], ax_fb.get_ylim()[1],\\n color=\'g\', label=\'Earnings Release\')\\nFB_plot.legend(loc=2)\\nFB_plot.set_title(\'FB Midpoint Plot\')\\n\\nAAPL_plot = axarr[1]\\nohlc_dataframe(AAPL[datetime(2016, 4, 10):], AAPL_plot)\\nAAPL_truncated = AAPL[datetime(2016, 4, 10):datetime(2016, 4, 26)]\\nmidpoint = AAPL_truncated[\'Open\']/2 + AAPL_truncated[\'Close\']/2\\nAAPL_plot.plot(AAPL_truncated.index, midpoint, label=\'Midpoint\')\\nAAPL_plot.vlines(date2num(datetime(2016, 4, 26, 12)),\\n ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1],\\n color=\'g\', label=\'Earnings Release\')\\nAAPL_plot.legend(loc=3)\\nAAPL_plot.set_title(\'AAPL Midpoint Plot\');\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_14_0.png)\\n\\nGiven these charts, we can see that FB was trending down for the four days preceding the earnings release, and AAPL was trending down for a whopping 8 days (we don\'t count the peak day). This will define the methodology that we will use for the study.\\n\\nSo what are the results? For a given horizon, how well does the market actually perform?\\n\\n<details>\\n<summary>Code</summary>\\n\\n```python\\n# Read in the events for each stock;\\n# The file was created using the first code block in the Appendix\\nimport yaml\\nfrom dateutil.parser import parse\\nfrom progressbar import ProgressBar\\n\\ndata_str = open(\'earnings_dates.yaml\', \'r\').read()\\n# Need to remove invalid lines\\nfiltered = filter(lambda x: \'{\' not in x, data_str.split(\'\\\\n\'))\\nearnings_data = yaml.load(\'\\\\n\'.join(filtered))\\n\\n# Convert our earnings data into a list of (ticker, date) pairs\\n# to make it easy to work with.\\n# This is horribly inefficient, but should get us what we need\\nticker_dates = []\\nfor ticker, date_list in earnings_data.items():\\n for iso_str in date_list:\\n ticker_dates.append((ticker, parse(iso_str)))\\n\\ndef does_trend_down(ticker, event, horizon):\\n # Figure out if the `event` has a downtrend for\\n # the `horizon` days preceding it\\n # As an interpretation note: it is assumed that\\n # the closing price of day `event` is the reference\\n # point, and we want `horizon` days before that.\\n # The price_data.hdf was created in the second appendix code block\\n try:\\n ticker_data = pd.read_hdf(\'price_data.hdf\', ticker)\\n data = ticker_data[event-TradeDay(horizon):event]\\n midpoints = data[\'Open\']/2 + data[\'Close\']/2\\n\\n # Shift dates one forward into the future and subtract\\n # Effectively: do we trend down over all days?\\n elems = midpoints - midpoints.shift(1)\\n return len(elems)-1 == len(elems.dropna()[elems <= 0])\\n except KeyError:\\n # If the stock doesn\'t exist, it doesn\'t qualify as trending down\\n # Mostly this is here to make sure the entire analysis doesn\'t \\n # blow up if there were issues in data retrieval\\n return False\\n\\ndef study_trend(horizon, trend_function):\\n five_day_events = np.zeros((1, horizon*2 + 1))\\n invalid_events = []\\n for ticker, event in ProgressBar()(ticker_dates):\\n if trend_function(ticker, event, horizon):\\n ticker_data = pd.read_hdf(\'price_data.hdf\', ticker)\\n event_data = ticker_data[event-TradeDay(horizon):event+TradeDay(horizon)][\'Close\']\\n\\n try:\\n five_day_events = np.vstack([five_day_events, event_data])\\n except ValueError:\\n # Sometimes we don\'t get exactly the right number of values due to calendar\\n # issues. I\'ve fixed most everything I can, and the few issues that are left\\n # I assume don\'t systemically bias the results (i.e. data could be missing\\n # because it doesn\'t exist, etc.). After running through, ~1% of events get\\n # discarded this way\\n invalid_events.append((ticker, event))\\n \\n\\n # Remove our initial zero row\\n five_day_events = five_day_events[1:,:]\\n plot_study(five_day_events)\\n plt.gcf().suptitle(\'Action over {} days: {} events\'\\n .format(horizon,five_day_events.shape[0]))\\n plt.gcf().set_size_inches(18, 6)\\n \\n# Start with a 5 day study\\nstudy_trend(5, does_trend_down)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:21:38 Time: 0:21:38\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_16_1.png)\\n\\nWhen a stock has been trending down for 5 days, once the earnings are announced it really doesn\'t move on average. However, the variability is *incredible*. This implies two important things:\\n\\n1. The market is just as often wrong about an earnings announcement before it happens as it is correct\\n2. The incredible width of the min/max bars and standard deviation area tell us that the market reacts *violently* after the earnings are released.\\n\\nLet\'s repeat the same study, but over a time horizon of 8 days and 3 days. Presumably if a stock has been going down for 8 days at a time before the earnings, the market should be more accurate.\\n\\n<details>\\n<summary>Code</summary>\\n\\n```python\\n# 8 day study next\\nstudy_trend(8, does_trend_down)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:29 Time: 0:20:29\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_18_1.png)\\n\\nHowever, looking only at stocks that trended down for 8 days prior to a release, the same pattern emerges: on average, the stock doesn\'t move, but the market reaction is often incredibly violent.\\n\\n\\n<details>\\n<summary>Code</summary>\\n```python\\n# 3 day study after that\\nstudy_trend(3, does_trend_down)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:26 Time: 0:26:26\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_20_1.png)\\n\\nFinally, when we look at a 3-day horizon, we start getting some incredible outliers. Stocks have a potential to move over ~300% up, and the standard deviation width is again, incredible. The results for a 3-day horizon follow the same pattern we\'ve seen in the 5- and 8-day horizons.\\n\\n## Event Type 2: Trending up for N days\\n\\nWe\'re now going to repeat the analysis, but do it for uptrends instead. That is, instead of looking at stocks that have been trending down over the past number of days, we focus only on stocks that have been trending up.\\n\\n<details>\\n<summary>Code</summary>\\n```python\\ndef does_trend_up(ticker, event, horizon):\\n # Figure out if the `event` has an uptrend for\\n # the `horizon` days preceding it\\n # As an interpretation note: it is assumed that\\n # the closing price of day `event` is the reference\\n # point, and we want `horizon` days before that.\\n # The price_data.hdf was created in the second appendix code block\\n try:\\n ticker_data = pd.read_hdf(\'price_data.hdf\', ticker)\\n data = ticker_data[event-TradeDay(horizon):event]\\n midpoints = data[\'Open\']/2 + data[\'Close\']/2\\n\\n # Shift dates one forward into the future and subtract\\n # Effectively: do we trend down over all days?\\n elems = midpoints - midpoints.shift(1)\\n return len(elems)-1 == len(elems.dropna()[elems >= 0])\\n except KeyError:\\n # If the stock doesn\'t exist, it doesn\'t qualify as trending down\\n # Mostly this is here to make sure the entire analysis doesn\'t \\n # blow up if there were issues in data retrieval\\n return False\\n\\nstudy_trend(5, does_trend_up)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:22:51 Time: 0:22:51\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_23_1.png)\\n\\nThe patterns here are very similar. With the exception of noting that stocks can go to nearly 400% after an earnings announcement (most likely this included a takeover announcement, etc.), we still see large min/max bars and wide standard deviation of returns.\\n\\nWe\'ll repeat the pattern for stocks going up for both 8 and 3 days straight, but at this point, the results should be very predictable:\\n\\n<details>\\n<summary>Code</summary>\\n```python\\nstudy_trend(8, does_trend_up)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:51 Time: 0:20:51\\n```\\n</details>\\n \\n![png](_notebook_files/_notebook_25_1.png)\\n\\n<details>\\n<summary>Code</summary>\\n```python\\nstudy_trend(3, does_trend_up)\\n```\\n\\n```\\n 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:56 Time: 0:26:56\\n```\\n</details>\\n\\n![png](_notebook_files/_notebook_26_1.png)\\n\\n## Conclusion and Summary\\n\\nI guess the most important thing to summarize with is this: **looking at the entire market, stock performance prior to an earnings release has no bearing on the stock\'s performance.** Honestly: given the huge variability of returns after an earnings release, even when the stock has been trending for a long time, you\'re best off divesting before an earnings release and letting the market sort itself out.\\n\\n*However*, there is a big caveat. These results are taken when we look at the entire market. So while we can say that the market as a whole knows nothing and just reacts violently, I want to take a closer look into this data. Does the market typically perform poorly on large-cap/high liquidity stocks? Do smaller companies have investors that know them better and can thus predict performance better? Are specific market sectors better at prediction? Presumably technology stocks are more volatile than the industrials.\\n\\nSo there are some more interesting questions I still want to ask with this data. Knowing that the hard work of data processing is largely already done, it should be fairly simple to continue this analysis and get much more refined with it. Until next time.\\n\\n# Appendix\\n\\nExport event data for Russell 3000 companies:\\n\\n<details>\\n<summary>Code</summary>\\n```python\\nimport pandas as pd\\nfrom html.parser import HTMLParser\\nfrom datetime import datetime, timedelta\\nimport requests\\nimport re\\nfrom dateutil import parser\\nimport progressbar\\nfrom concurrent import futures\\nimport yaml\\n\\nclass EarningsParser(HTMLParser):\\n store_dates = False\\n earnings_offset = None\\n dates = []\\n \\n def __init__(self, *args, **kwargs):\\n super().__init__(*args, **kwargs)\\n self.dates = []\\n \\n def handle_starttag(self, tag, attrs):\\n if tag == \'table\':\\n self.store_dates = True\\n \\n def handle_data(self, data):\\n if self.store_dates:\\n match = re.match(r\'\\\\d+/\\\\d+/\\\\d+\', data)\\n if match:\\n self.dates.append(match.group(0))\\n \\n # If a company reports before the bell, record the earnings date\\n # being at midnight the day before. Ex: WMT reports 5/19/2016,\\n # but we want the reference point to be the closing price on 5/18/2016\\n if \'After Close\' in data:\\n self.earnings_offset = timedelta(days=0)\\n elif \'Before Open\' in data:\\n self.earnings_offset = timedelta(days=-1)\\n \\n def handle_endtag(self, tag):\\n if tag == \'table\':\\n self.store_dates = False\\n \\ndef earnings_releases(ticker):\\n #print(\\"Looking up ticker {}\\".format(ticker))\\n user_agent = \'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) \'\\\\\\n \'Gecko/20100101 Firefox/46.0\'\\n headers = {\'user-agent\': user_agent}\\n base_url = \'http://www.streetinsider.com/ec_earnings.php?q={}\'\\\\\\n .format(ticker)\\n e = EarningsParser()\\n s = requests.Session()\\n a = requests.adapters.HTTPAdapter(max_retries=0)\\n s.mount(\'http://\', a)\\n e.feed(str(s.get(base_url, headers=headers).content))\\n \\n if e.earnings_offset is not None:\\n dates = map(lambda x: parser.parse(x) + e.earnings_offset, e.dates)\\n past = filter(lambda x: x < datetime.now(), dates)\\n return list(map(lambda d: d.isoformat(), past))\\n\\n# Use a Russell-3000 ETF tracker (ticker IWV) to get a list of holdings\\nr3000 = pd.read_csv(\'https://www.ishares.com/us/products/239714/\'\\n \'ishares-russell-3000-etf/1449138789749.ajax?\'\\n \'fileType=csv&fileName=IWV_holdings&dataType=fund\',\\n header=10)\\nr3000_equities = r3000[(r3000[\'Exchange\'] == \'NASDAQ\') |\\n (r3000[\'Exchange\'] == \'New York Stock Exchange Inc.\')]\\n\\ndates_file = open(\'earnings_dates.yaml\', \'w\')\\n\\nwith futures.ThreadPoolExecutor(max_workers=8) as pool:\\n fs = {pool.submit(earnings_releases, r3000_equities.ix[t][\'Ticker\']): t\\n for t in r3000_equities.index}\\n pbar = progressbar.ProgressBar(term_width=80,\\n max_value=r3000_equities.index.max())\\n \\n for future in futures.as_completed(fs):\\n i = fs[future]\\n pbar.update(i)\\n dates_file.write(yaml.dump({r3000_equities.ix[i][\'Ticker\']:\\n future.result()}))\\n```\\n</details>\\n\\nDownloading stock price data needed for the event studies:\\n\\n<details>\\n<summary>Code</summary>\\n```python\\nfrom secrets import QUANDL_KEY\\nimport pandas as pd\\nimport yaml\\nfrom dateutil.parser import parse\\nfrom datetime import timedelta\\nimport quandl\\nfrom progressbar import ProgressBar\\n\\ndef fetch_ticker(ticker, start, end):\\n # Quandl is currently giving me issues with returning\\n # the entire dataset and not slicing server-side.\\n # So instead, we\'ll do it client-side!\\n q_format = \'%Y-%m-%d\'\\n ticker_data = quandl.get(\'YAHOO/\' + ticker,\\n start_date=start.strftime(q_format),\\n end_date=end.strftime(q_format),\\n authtoken=QUANDL_KEY)\\n return ticker_data\\n \\ndata_str = open(\'earnings_dates.yaml\', \'r\').read()\\n# Need to remove invalid lines\\nfiltered = filter(lambda x: \'{\' not in x, data_str.split(\'\\\\n\'))\\nearnings_data = yaml.load(\'\\\\n\'.join(filtered))\\n\\n# Get the first 1500 keys - split up into two statements\\n# because of Quandl rate limits\\ntickers = list(earnings_data.keys())\\n\\nprice_dict = {}\\ninvalid_tickers = []\\nfor ticker in ProgressBar()(tickers[0:1500]):\\n try:\\n # Replace \'.\' with \'-\' in name for some tickers\\n fixed = ticker.replace(\'.\', \'-\')\\n event_strs = earnings_data[ticker]\\n events = [parse(event) for event in event_strs]\\n td = timedelta(days=20)\\n price_dict[ticker] = fetch_ticker(fixed,\\n min(events)-td, max(events)+td)\\n except quandl.NotFoundError:\\n invalid_tickers.append(ticker)\\n \\n# Execute this after 10 minutes have passed\\nfor ticker in ProgressBar()(tickers[1500:]):\\n try:\\n # Replace \'.\' with \'-\' in name for some tickers\\n fixed = ticker.replace(\'.\', \'-\')\\n event_strs = earnings_data[ticker]\\n events = [parse(event) for event in event_strs]\\n td = timedelta(days=20)\\n price_dict[ticker] = fetch_ticker(fixed,\\n min(events)-td, max(events)+td)\\n except quandl.NotFoundError:\\n invalid_tickers.append(ticker)\\n \\nprices_store = pd.HDFStore(\'price_data.hdf\')\\nfor ticker, prices in price_dict.items():\\n prices_store[ticker] = prices\\n```\\n</details>"},{"id":"2016/05/the-unfair-casino","metadata":{"permalink":"/2016/05/the-unfair-casino","source":"@site/blog/2016-05-15-the-unfair-casino/index.mdx","title":"The unfair casino","description":"Trying to figure out how exactly two dice are loaded in a cheating casino.","date":"2016-05-15T12:00:00.000Z","tags":[],"readingTime":14.62,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/05/the-unfair-casino","title":"The unfair casino","date":"2016-05-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730679360000,"prevItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"},"nextItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"}},"content":"Trying to figure out how exactly two dice are loaded in a cheating casino.\\n\\n\x3c!-- truncate --\x3e\\n\\nIn the ongoing eternal cycle of mathematicians asking generally useless questions about probability, I dreamt up another one. The scenario is as follows:\\n\\n**You\'re playing a game with two die, and you do not get to see what the outcome of the die are on each roll. All you get to see is their sum. Given an arbitrarily long list of the sum of two rolls, can you determine if one or both die are loaded, and what those loadings are?**\\n\\n## Proving we can detect cheating\\n\\nMy first question is simply, is this possible? There\'s a lot of trivial cases that make it obvious that there\'s cheating going on. But there are some edge cases that might give us more difficulty. First though, let\'s get a picture of what the fair distribution looks like. In principle, we can only detect cheating if the distribution of the fair die differs from the distribution of the loaded die.\\n\\n\\n```python\\nimport numpy as np\\nimport pandas as pd\\nimport matplotlib.pyplot as plt\\n%matplotlib inline\\n\\nfair_1 = np.random.randint(1, 7, 10000)\\nfair_2 = np.random.randint(1, 7, 10000)\\n\\npd.Series(fair_1 + fair_2).plot(kind=\'hist\', bins=11);\\nplt.title(\'Fair Distribution\');\\n```\\n \\n![png](_notebook_files/_notebook_1_0.png)\\n\\nThis distribution makes sense: there are many ways to make a 7 (the most frequent observed value) and very few ways to make a 12 or 2; an important symmetry. As a special note, you can notice that the sum of two fair dice is a discrete case of the [Triangle Distribution][1], which is itself a special case of the [Irwin-Hall Distribution][2].\\n\\n## The Edge Cases\\n\\nGiven that we understand how the results of two fair dice are distributed, let\'s see some of the interesting edge cases that come up. This will give us assurance that when a casino is cheating, it is detectable (given sufficient data). To make this as hard as possible, we will think of scenarios where the expected value of the sum of loaded dice is the same as the expected value of the sum of fair dice.\\n\\n### Edge Case 1\\nWhat happens when one die is biased low, and one die is biased high? That is, where:\\n\\n$$\\n\\\\begin{align*}\\n\\\\begin{array}{cc}\\nD_1 = \\\\left\\\\{\\n\\\\begin{array}{lr}\\n1 & w.p. 1/3\\\\\\\\\\n2 & w.p. 1/3\\\\\\\\\\n3 & w.p. 1/12\\\\\\\\\\n4 & w.p. 1/12\\\\\\\\\\n5 & w.p. 1/12\\\\\\\\\\n6 & w.p. 1/12\\n\\\\end{array}\\n\\\\right. &\\nD_2 = \\\\left\\\\{\\n\\\\begin{array}{lr}\\n1 & w.p. 1/12\\\\\\\\\\n2 & w.p. 1/12\\\\\\\\\\n3 & w.p. 1/12\\\\\\\\\\n4 & w.p. 1/12\\\\\\\\\\n5 & w.p. 1/3\\\\\\\\\\n6 & w.p. 1/3\\n\\\\end{array}\\n\\\\right. \\\\\\\\\\n\\\\mathbb{E}[D_1] = 2.5 & \\\\mathbb{E}[D_2] = 4.5\\n\\\\end{array}\\\\\\\\\\n\\\\mathbb{E}[D_1 + D_2] = 7 = \\\\mathbb{E}[D_{fair} + D_{fair}]\\n\\\\end{align*}\\n$$\\n\\n[1]: https://en.wikipedia.org/wiki/Triangular_distribution\\n[2]: https://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution\\n\\n\\n```python\\ndef unfair_die(p_vals, n):\\n x = np.random.multinomial(1, p_vals, n)\\n return x.nonzero()[1] + 1\\n\\nd1 = [1/3, 1/3, 1/12, 1/12, 1/12, 1/12]\\nd2 = [1/12, 1/12, 1/12, 1/12, 1/3, 1/3]\\n\\nx1 = unfair_die(d1, 10000)\\nx2 = unfair_die(d2, 10000)\\n\\npd.Series(x1 + x2).plot(kind=\'hist\', bins=11);\\nplt.title(\'$D_1$ biased low, $D_2$ biased high\');\\n```\\n\\n![png](_notebook_files/_notebook_3_0.png)\\n\\nWe can see that while the 7 value remains the most likely (as expected), the distribution is not so nicely shaped any more. \\n\\n### Edge Case 2\\n\\nWhen one die is loaded low, and one is loaded high, we\'ve seen how we can detect them. How about when two die are loaded both low and high? That is, we have the following distribution:\\n\\n$$\\n\\\\begin{align*}\\n\\\\begin{array}{cc}\\nD_1 = \\\\left\\\\{\\n\\\\begin{array}{lr}\\n1 & w.p. 1/3\\\\\\\\\\n2 & w.p. 1/12\\\\\\\\\\n3 & w.p. 1/12\\\\\\\\\\n4 & w.p. 1/12\\\\\\\\\\n5 & w.p. 1/12\\\\\\\\\\n6 & w.p. 1/3\\n\\\\end{array}\\n\\\\right. &\\nD_2 = \\\\left\\\\{\\n\\\\begin{array}{lr}\\n1 & w.p. 1/3\\\\\\\\\\n2 & w.p. 1/12\\\\\\\\\\n3 & w.p. 1/12\\\\\\\\\\n4 & w.p. 1/12\\\\\\\\\\n5 & w.p. 1/12\\\\\\\\\\n6 & w.p. 1/3\\n\\\\end{array}\\n\\\\right. \\\\\\\\\\n\\\\mathbb{E}[D_1] = 3.5 & \\\\mathbb{E}[D_2] = 3.5\\n\\\\end{array}\\\\\\\\\\n\\\\mathbb{E}[D_1 + D_2] = 7 = \\\\mathbb{E}[D_{fair} + D_{fair}]\\n\\\\end{align*}\\n$$\\n\\nWe can see even that the expected value of each individual die is the same as the fair die! However, the distribution (if we are doing this correctly) should still be skewed:\\n\\n```python\\nd1 = [1/3, 1/12, 1/12, 1/12, 1/12, 1/3]\\nd2 = d1\\n\\nx1 = unfair_die(d1, 10000)\\nx2 = unfair_die(d2, 10000)\\n\\npd.Series(x1 + x2).plot(kind=\'hist\', bins=11)\\nplt.title(\\"$D_1$ and $D_2$ biased to 1 and 6\\");\\n```\\n \\n![png](_notebook_files/_notebook_5_0.png)\\n\\nIn a very un-subtle way, we have of course made the values 2 and 12 far more likely.\\n\\n## Detection Conclusion\\n\\nThere are some trivial examples of cheating that are easy to detect: whenever the expected value of the sum of two fair dice deviates from the expected value for the sum of two fair dice, we can immediately conclude that there is cheating at stake.\\n\\nThe interesting edge cases occur when the expected value of the sum of loaded dice matches the expected value of the sum of fair dice. Considering the above examples (and a couple more I ran through in developing this), we have seen that in every circumstance having two unfair dice leads to a distribution of results different from the fair results.\\n\\nWe can thus finally state: **just by looking at the distribution of results from this game, we can immediately conclude whether there is cheating.**\\n\\n## Simulated Annealing\\n\\nWhat we really would like to do though, is see if there is any way to determine how exactly the dice are loaded. This is significantly more complicated, but we can borrow some algorithms from Machine Learning to figure out exactly how to perform this process. I\'m using the Simulated Annealing algorithm, and I discuss why this works and why I chose it over some of the alternatives in the [justification](#Justification-of-Simulated-Annealing). If you don\'t care about how I set up the model and just want to see the code, check out [the actual code](#The-actual-code).\\n\\n[Simulated Annealing][3] is a variation of the [Metropolis-Hastings Algorithm][4], but the important thing for us is: Simulated Annealing allows us to quickly optimize high-dimensional problems. But what exactly are we trying to optimize? Ideally, we want a function that can tell us whether one distribution for the dice better explains the results than another distribution. This is known as the **likelihood** function.\\n\\n### Deriving the Likelihood function\\n\\nTo derive our likelihood function, we want to know: **what is the probability of seeing a specific result given those hidden parameters?** This is actually a surprisingly difficult problem. While we can do a lot of calculations by hand, we need a more general solution since we will be working with very some interesting die distributions.\\n\\nWe first note that the sum of two dice can take on 11 different values - 2 through 12. This implies that each individual sum follows a [Categorical distribution](https://en.wikipedia.org/wiki/Categorical_distribution). That is:\\n\\n$$\\n\\\\begin{align*}\\n\\\\mathcal{L(x)} = \\\\left\\\\{\\n\\\\begin{array}{lr}\\np_2 & x = 2\\\\\\\\\\np_3 & x = 3\\\\\\\\\\n\\\\ldots & \\\\\\\\\\np_{11} & x = 11\\\\\\\\\\np_{12} & x = 12\\n\\\\end{array}\\n\\\\right.\\n\\\\end{align*}\\n$$\\n\\nWhere each $p_i$ is the probability of seeing that specific result. However, we need to calculate what each probability is! I\'ll save you the details, but [this author](http://math.stackexchange.com/a/1646360/320784) explains how to do it.\\n\\nNow, we would like to know the likelihood of our entire data-set. This is trivial:\\n\\n$$\\n\\\\begin{align*}\\n\\\\mathcal{L(\\\\mathbf{X})} &= \\\\prod_{i=1}^n L(x)\\n\\\\end{align*}\\n$$\\n\\nHowever, it\'s typically much easier to work with the $\\\\log(\\\\mathcal{L})$ function instead. This is critically important from a computational perspective: when you multiply so many small numbers together (i.e. the product of $L(x)$ terms) the computer suffers from rounding error; if we don\'t control for this, we will find that no matter the distributions we choose for each die, the \\"likelihood\\" will be close to zero because the computer is not precise enough.\\n\\n$$\\n\\\\begin{align*}\\n\\\\log(\\\\mathcal{L}) &= \\\\sum_{i=1}^n \\\\log(L)\\n\\\\end{align*}\\n$$\\n\\n### The process of Simulated Annealing\\n\\nThe means by which we optimize our likelihood function is the simulated annealing algorithm. The way it works is as follows:\\n\\n1. Start with a random guess for the parameters we are trying to optimize. In our case we are trying to guess the distribution of two dice, and so we \\"optimize\\" until we have a distribution that matches the data.\\n\\n2. For each iteration of the algorithm:\\n\\n 1. Generate a new \\"proposed\\" set of parameters based on the current parameters -\\n i.e. slightly modify the current parameters to get a new set of parameters.\\n 2. Calculate the value of $\\\\log(\\\\mathcal{L})$ for each set of parameters. If the function value for the\\n proposed parameter set is higher than for the current, automatically switch to the new parameter set\\n and continue the next iteration.\\n 3. Given the new parameter set performs worse, determine a probability of switching to the new parameter set anyways: $\\\\mathcal{P}(p_{current}, p_{proposed})$\\n 4. Switch to the new parameter set with probability $\\\\mathcal{P}$. If you fail to switch, begin the next iteration.\\n \\n3. The algorithm is complete after we fail to make a transition $n$ times in a row.\\n\\nIf everything goes according to plan, we will have a value that is close to the true distribution of each die.\\n\\n## The actual code\\n\\nWe start by defining the score function. This will tell us how well the proposed die densities actually explain the results.\\n\\n[3]:https://en.wikipedia.org/wiki/Simulated_annealing\\n[4]:https://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm\\n\\n\\n```python\\nimport numpy as np\\nfrom numpy import polynomial\\n\\ndef density_coef(d1_density, d2_density):\\n # Calculating the probabilities of each outcome was taken\\n # from this author: http://math.stackexchange.com/a/1710392/320784\\n d1_p = polynomial.Polynomial(d1_density)\\n d2_p = polynomial.Polynomial(d2_density)\\n coefs = (d1_p * d2_p).coef\\n return coefs\\n\\ndef score(x, d1_density, d2_density):\\n # We\'ve now got the probabilities of each event, but we need\\n # to shift the array a bit so we can use the x values to actually\\n # index into it. This will allow us to do all the calculations\\n # incredibly quickly\\n coefs = density_coef(d1_density, d2_density)\\n coefs = np.hstack((0, 0, coefs))\\n return np.log(coefs[x]).sum()\\n```\\n\\nAfterward, we need to write something to permute the proposal densities. We make random modifications, and eventually the best one survives.\\n\\n\\n```python\\ndef permute(d1_density, d2_density):\\n # To ensure we have legitimate densities, we will randomly\\n # increase one die face probability by `change`,\\n # and decrease one by `change`.\\n # This means there are something less than (1/`change`)^12 possibilities\\n # we are trying to search over.\\n change = .01\\n \\n d1_index1, d1_index2 = np.random.randint(0, 6, 2)\\n d2_index1, d2_index2 = np.random.randint(0, 6, 2)\\n \\n # Also make sure to copy. I\'ve had some weird aliasing issues\\n # in the past that made everything blow up.\\n new_d1 = np.float64(np.copy(d1_density))\\n new_d2 = np.float64(np.copy(d2_density))\\n \\n # While this doesn\'t account for the possibility that some\\n # values go negative, in practice this never happens\\n new_d1[d1_index1] += change\\n new_d1[d1_index2] -= change\\n new_d2[d2_index1] += change\\n new_d2[d2_index2] -= change\\n \\n return new_d1, new_d2\\n```\\n\\nNow we\'ve got the main algorithm code to do. This is what brings all the pieces together.\\n\\n\\n```python\\ndef optimize(data, conv_count=10, max_iter=1e4):\\n switch_failures = 0\\n iter_count = 0\\n \\n # Start with guessing fair dice\\n cur_d1 = np.repeat(1/6, 6)\\n cur_d2 = np.repeat(1/6, 6)\\n cur_score = score(data, cur_d1, cur_d2)\\n \\n # Keep track of our best guesses - may not be\\n # what we end with\\n max_score = cur_score\\n max_d1 = cur_d1\\n max_d2 = cur_d2\\n \\n # Optimization stops when we have failed to switch `conv_count`\\n # times (presumably because we have a great guess), or we reach\\n # the maximum number of iterations.\\n while switch_failures < conv_count and iter_count < max_iter:\\n iter_count += 1\\n if iter_count % (max_iter / 10) == 0:\\n print(\'Iteration: {}; Current score (higher is better): {}\'.format(\\n iter_count, cur_score))\\n \\n new_d1, new_d2 = permute(cur_d1, cur_d2)\\n new_score = score(data, new_d1, new_d2)\\n \\n if new_score > max_score:\\n max_score = new_score\\n max_d1 = new_d1\\n max_d2 = new_d2\\n \\n if new_score > cur_score:\\n # If the new permutation beats the old one,\\n # automatically select it.\\n cur_score = new_score\\n cur_d1 = new_d1\\n cur_d2 = new_d2\\n switch_failures = 0\\n else:\\n # We didn\'t beat the current score, but allow\\n # for possibly switching anyways.\\n accept_prob = np.exp(new_score - cur_score)\\n coin_toss = np.random.rand()\\n if coin_toss < accept_prob:\\n # We randomly switch to the new distribution\\n cur_score = new_score\\n cur_d1 = new_d1\\n cur_d2 = new_d2\\n switch_failures = 0\\n else:\\n switch_failures += 1\\n \\n # Return both our best guess, and the ending guess\\n return max_d1, max_d2, cur_d1, cur_d2\\n```\\n\\nAnd now we have finished the hard work!\\n\\n## Catching the Casino\\n\\nLet\'s go through a couple of scenarios and see if we can catch the casino cheating with some loaded dice. **In every scenario we start with an assumption of fair dice**, and then try our hand to figure out what the *actual* distribution was.\\n\\n### Attempt 1\\n\\n\\nThe casino is using two dice that are both biased low. How well can we recover the distribution?\\n\\n\\n```python\\nimport time\\ndef simulate_casino(d1_dist, d2_dist, n=10000):\\n d1_vals = unfair_die(d1_dist, n)\\n d2_vals = unfair_die(d2_dist, n)\\n \\n start = time.perf_counter()\\n max_d1, max_d2, final_d1, final_d2 = optimize(d1_vals + d2_vals)\\n end = time.perf_counter()\\n print(\\"Simulated Annealing time: {:.02f}s\\".format(end - start))\\n \\n coef_range = np.arange(2, 13) - .5\\n plt.subplot(221)\\n plt.bar(coef_range, density_coef(d1_dist, d2_dist), width=1)\\n plt.title(\'True Distribution\')\\n \\n plt.subplot(222)\\n plt.hist(d1_vals + d2_vals, bins=11)\\n plt.title(\'Empirical Distribution\')\\n \\n plt.subplot(223)\\n plt.bar(coef_range, density_coef(max_d1, max_d2), width=1)\\n plt.title(\'Recovered Distribution\')\\n \\n plt.gcf().set_size_inches(10, 10)\\n\\n\\nsimulate_casino([2/9, 2/9, 2/9, 1/9, 1/9, 1/9],\\n [2/9, 2/9, 2/9, 1/9, 1/9, 1/9])\\n```\\n\\n```\\n Iteration: 1000; Current score (higher is better): -22147.004400281654\\n Simulated Annealing time: 0.30s\\n```\\n \\n![png](_notebook_files/_notebook_14_1.png)\\n\\n### Attempt 2\\n\\nThe casino now uses dice that are both biased towards 1 and 6.\\n\\n```python\\nsimulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],\\n [1/3, 1/12, 1/12, 1/12, 1/12, 1/3])\\n```\\n\\n```\\n Simulated Annealing time: 0.08s\\n```\\n \\n![png](_notebook_files/_notebook_16_1.png)\\n\\n### Attempt 3\\n\\nThe casino will now use one die biased towards 1 and 6, and one die towards 3 and 4.\\n\\n\\n```python\\nsimulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3],\\n [1/12, 1/12, 1/3, 1/3, 1/12, 1/12])\\n```\\n\\n```\\n Simulated Annealing time: 0.09s\\n```\\n \\n![png](_notebook_files/_notebook_18_1.png)\\n\\n### Attempt 4\\n\\nWe\'ll now finally go to a fair casino to make sure that we can still recognize a positive result.\\n\\n```python\\nsimulate_casino(np.repeat(1/6, 6), np.repeat(1/6, 6))\\n```\\n\\n```\\n Simulated Annealing time: 0.02s\\n```\\n \\n![png](_notebook_files/_notebook_20_1.png)\\n\\n### Attempt 5\\n\\nWe\'ve so far been working with a large amount of data - 10,000 data points. Can we now scale things back to only 250 throws? We\'ll start with two dice biased high.\\n\\n\\n```python\\nsimulate_casino([1/9, 1/9, 1/9, 2/9, 2/9, 2/9],\\n [1/9, 1/9, 1/9, 2/9, 2/9, 2/9],\\n n=250)\\n```\\n\\n```\\n Iteration: 1000; Current score (higher is better): -551.6995384525453\\n Iteration: 2000; Current score (higher is better): -547.7803673440676\\n Iteration: 3000; Current score (higher is better): -547.9805613193807\\n Iteration: 4000; Current score (higher is better): -546.7574874775273\\n Iteration: 5000; Current score (higher is better): -549.5798007672656\\n Iteration: 6000; Current score (higher is better): -545.0354060154496\\n Iteration: 7000; Current score (higher is better): -550.1134504086606\\n Iteration: 8000; Current score (higher is better): -549.9306537114975\\n Iteration: 9000; Current score (higher is better): -550.7075182119111\\n Iteration: 10000; Current score (higher is better): -549.400679551826\\n Simulated Annealing time: 1.94s\\n```\\n \\n![png](_notebook_files/_notebook_22_1.png)\\n\\nThe results are surprisingly good. While the actual optimization process took much longer to finish than in the other examples, we still have a very good guess. As a caveat though: the recovered distribution tends to overfit the data. That is, if the data doesn\'t fit the underlying distribution well, the model will also fail.\\n\\n## Conclusion\\n\\nGiven the results above, we can see that we have indeed come up with a very good algorithm to determine the distribution of two dice given their results. As a benefit, we have even seen that results come back very quickly; it\'s not uncommon for the optimization to converge within a tenth of a second.\\n\\nAdditionally, we have seen that the algorithm can intuit the distribution even when there is not much data. While the final example shows that we can \'overfit\' on the dataset, we can still get valuable information from a relatively small dataset.\\n\\nWe can declare at long last: **the mathematicians have again triumphed over the casino**.\\n\\n---\\n\\n## Justification of Simulated Annealing\\n\\n### Why Simulated Annealing?\\n\\nSo why even use an algorithm with a fancy title like Simulated Annealing? First of all, because the title is sexy. Second of all, because this is a reasonably complicated problem to try and solve. We have a parameter space where each value $p_{ij} \\\\in (0, 1); i, j \\\\in \\\\{1, \\\\ldots, 6\\\\}$, for a total of 12 different variables we are trying to optimize over. Additionally, given a 12-dimensional function we are trying to optimize, simulated annealing makes sure that we don\'t fall into a local minimum.\\n\\n### Why not something else?\\n\\nThis is a fair question. There are two classes of algorithms that can also be used to solve this problem: [Non-linear optimization](https://en.wikipedia.org/wiki/Nonlinear_programming) methods, and the [EM algorithm](https://en.wikipedia.org/wiki/Expectation%E2%80%93maximization_algorithm).\\n\\n1. I chose not to use non-linear optimization simply because I\'m a bit concerned that it will trap me in a local maximum. Instead of running multiple different optimizations from different starting points, I can just use simulated annealing to take that into account. In addition, throughout the course of testing the simulated annealing code converged *incredibly* quickly - far more quickly than any non-linear solver would be able to accomplish. \\n\\n2. The EM Algorithm was originally what I intended to write this blog post with. Indeed, the post was inspired by the [crooked casino](http://web.stanford.edu/class/stats366/hmmR2.html) example which uses the EM algorithm to solve it. However, after modeling the likelihood function I realized that the algebra would very quickly get out of hand. Trying to compute all the polynomial terms would not be fun, which would be needed to actually optimize for each parameter. So while the EM algorithm would likely be much faster in raw speed terms, the amount of time needed to program and verify it meant that I was far better off using a different method for optimization."},{"id":"2016/04/tick-tock","metadata":{"permalink":"/2016/04/tick-tock","source":"@site/blog/2016-04-06-tick-tock/index.mdx","title":"Tick tock...","description":"If all we have is a finite number of heartbeats left, what about me?","date":"2016-04-06T12:00:00.000Z","tags":[],"readingTime":10.125,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/04/tick-tock","title":"Tick tock...","date":"2016-04-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"},"nextItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"}},"content":"If all we have is a finite number of heartbeats left, what about me?\\n\\n\x3c!-- truncate --\x3e\\n\\nWarning: this one is a bit creepier. But that\'s what you get when you come up with data science ideas as you\'re drifting off to sleep.\\n\\n## 2.5 Billion\\n\\nIf [PBS][1] is right, that\'s the total number of heartbeats we get. Approximately once every second that number goes down, and down, and down again...\\n\\n[1]: http://www.pbs.org/wgbh/nova/heart/heartfacts.html\\n\\n```python\\ntotal_heartbeats = 2500000000\\n```\\n\\nI got a Fitbit this past Christmas season, mostly because I was interested in the data and trying to work on some data science projects with it. This is going to be the first project, but there will likely be more (and not nearly as morbid). My idea was: If this is the final number that I\'m running up against, how far have I come, and how far am I likely to go? I\'ve currently had about 3 months\' time to estimate what my data will look like, so let\'s go ahead and see: given a lifetime 2.5 billion heart beats, how much time do I have left?\\n\\n## Statistical Considerations\\n\\nSince I\'m starting to work with health data, there are a few considerations I think are important before I start digging through my data.\\n\\n1. The concept of 2.5 billion as an agreed-upon number is tenuous at best. I\'ve seen anywhere from [2.21 billion][2] to [3.4 billion][3] so even if I knew exactly how many times my heart had beaten so far, the ending result is suspect at best. I\'m using 2.5 billion because that seems to be about the midpoint of the estimates I\'ve seen so far.\\n2. Most of the numbers I\'ve seen so far are based on extrapolating number of heart beats from life expectancy. As life expectancy goes up, the number of expected heart beats goes up too.\\n3. My estimation of the number of heartbeats in my life so far is based on 3 months worth of data, and I\'m extrapolating an entire lifetime based on this.\\n\\nSo while the ending number is **not useful in any medical context**, it is still an interesting project to work with the data I have on hand.\\n\\n## Getting the data\\n\\n[Fitbit](https://www.fitbit.com/) has an [API available](https://dev.fitbit.com/) for people to pull their personal data off the system. It requires registering an application, authentication with OAuth, and some other complicated things. **If you\'re not interested in how I fetch the data, skip [here](#Wild-Extrapolations-from-Small-Data)**.\\n\\n## Registering an application\\n\\nI\'ve already [registered a personal application](https://dev.fitbit.com/apps/new) with Fitbit, so I can go ahead and retrieve things like the client secret from a file.\\n\\n[1]: http://www.pbs.org/wgbh/nova/heart/heartfacts.html\\n[2]: http://gizmodo.com/5982977/how-many-heartbeats-does-each-species-get-in-a-lifetime\\n[3]: http://wonderopolis.org/wonder/how-many-times-does-your-heart-beat-in-a-lifetime/\\n\\n\\n```python\\n# Import all the OAuth secret information from a local file\\nfrom secrets import CLIENT_SECRET, CLIENT_ID, CALLBACK_URL\\n```\\n\\n### Handling OAuth 2\\n\\nSo, all the people that know what OAuth 2 is know what\'s coming next. For those who don\'t: OAuth is how people allow applications to access other data without having to know your password. Essentially the dialog goes like this:\\n\\n```\\nApplication: I\'ve got a user here who wants to use my application, but I need their data.\\nFitbit: OK, what data do you need access to, and for how long?\\nApplication: I need all of these scopes, and for this amount of time.\\nFitbit: OK, let me check with the user to make sure they really want to do this.\\n\\nFitbit: User, do you really want to let this application have your data?\\nUser: I do! And to prove it, here\'s my password.\\nFitbit: OK, everything checks out. I\'ll let the application access your data.\\n\\nFitbit: Application, you can access the user\'s data. Use this special value whenever you need to request data from me.\\nApplication: Thank you, now give me all the data.\\n```\\n\\nEffectively, this allows an application to gain access to a user\'s data without ever needing to know the user\'s password. That way, even if the other application is hacked, the user\'s original data remains safe. Plus, the user can let the data service know to stop providing the application access any time they want. All in all, very secure.\\n\\nIt does make handling small requests a bit challenging, but I\'ll go through the steps here. We\'ll be using the [Implicit Grant](https://dev.fitbit.com/docs/oauth2/) workflow, as it requires fewer steps in processing.\\n\\nFirst, we need to set up the URL the user would visit to authenticate:\\n\\n\\n```python\\nimport urllib\\n\\nFITBIT_URI = \'https://www.fitbit.com/oauth2/authorize\'\\nparams = {\\n # If we need more than one scope, must be a CSV string\\n \'scope\': \'heartrate\',\\n \'response_type\': \'token\',\\n \'expires_in\': 86400, # 1 day\\n \'redirect_uri\': CALLBACK_URL,\\n \'client_id\': CLIENT_ID\\n}\\n\\nrequest_url = FITBIT_URI + \'?\' + urllib.parse.urlencode(params)\\n```\\n\\nNow, here you would print out the request URL, go visit it, and get the full URL that it sends you back to. Because that is very sensitive information (specifically containing my `CLIENT_ID` that I\'d really rather not share on the internet), I\'ve skipped that step in the code here, but it happens in the background.\\n\\n\\n```python\\n# The `response_url` variable contains the full URL that\\n# FitBit sent back to us, but most importantly,\\n# contains the token we need for authorization.\\naccess_token = dict(urllib.parse.parse_qsl(response_url))[\'access_token\']\\n```\\n\\n### Requesting the data\\n\\nNow that we\'ve actually set up our access via the `access_token`, it\'s time to get the actual [heart rate data](https://dev.fitbit.com/docs/heart-rate/). I\'ll be using data from January 1, 2016 through March 31, 2016, and extrapolating wildly from that.\\n\\nFitbit only lets us fetch intraday data one day at a time, so I\'ll create a date range using pandas and iterate through that to pull down all the data.\\n\\n\\n```python\\nfrom requests_oauthlib import OAuth2Session\\nimport pandas as pd\\nfrom datetime import datetime\\n\\nsession = OAuth2Session(token={\\n \'access_token\': access_token,\\n \'token_type\': \'Bearer\'\\n })\\n\\nformat_str = \'%Y-%m-%d\'\\nstart_date = datetime(2016, 1, 1)\\nend_date = datetime(2016, 3, 31)\\ndr = pd.date_range(start_date, end_date)\\n\\nurl = \'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json\'\\nhr_responses = [session.get(url.format(d.strftime(format_str))) for d in dr]\\n\\ndef record_to_df(record):\\n if \'activities-heart\' not in record:\\n return None\\n date_str = record[\'activities-heart\'][0][\'dateTime\']\\n df = pd.DataFrame(record[\'activities-heart-intraday\'][\'dataset\'])\\n \\n df.index = df[\'time\'].apply(\\n lambda x: datetime.strptime(date_str + \' \' + x, \'%Y-%m-%d %H:%M:%S\'))\\n return df\\n\\nhr_dataframes = [record_to_df(record.json()) for record in hr_responses]\\nhr_df_concat = pd.concat(hr_dataframes)\\n\\n\\n# There are some minutes with missing data, so we need to correct that\\nfull_daterange = pd.date_range(hr_df_concat.index[0],\\n hr_df_concat.index[-1],\\n freq=\'min\')\\nhr_df_full = hr_df_concat.reindex(full_daterange, method=\'nearest\')\\n\\nprint(\\"Heartbeats from {} to {}: {}\\".format(hr_df_full.index[0],\\n hr_df_full.index[-1],\\n hr_df_full[\'value\'].sum()))\\n```\\n\\n```\\n Heartbeats from 2016-01-01 00:00:00 to 2016-03-31 23:59:00: 8139060\\n```\\n\\nAnd now we\'ve retrieved all the available heart rate data for January 1<sup>st</sup> through March 31<sup>st</sup>! Let\'s get to the actual analysis.\\n\\n## Wild Extrapolations from Small Data\\n\\nA fundamental issue of this data is that it\'s pretty small. I\'m using 3 months of data to make predictions about my entire life. But, purely as an exercise, I\'ll move forward.\\n\\n### How many heartbeats so far?\\n\\nThe first step is figuring out how many of the 2.5 billion heartbeats I\'ve used so far. We\'re going to try and work backward from the present day to when I was born to get that number. The easy part comes first: going back to January 1<sup>st</sup>, 1992. That\'s because I can generalize how many 3-month increments there were between now and then, account for leap years, and call that section done.\\n\\nBetween January 1992 and January 2016 there were 96 quarters, and 6 leap days. The number we\'re looking for is:\\n\\n$$\\n\\\\begin{equation*}\\nhr_q \\\\cdot n - hr_d \\\\cdot (n-m)\\n\\\\end{equation*}\\n$$\\n\\n- $hr_q$: Number of heartbeats per quarter\\n- $hr_d$: Number of heartbeats on leap day\\n- $n$: Number of quarters, in this case 96\\n- $m$: Number of leap days, in this case 6\\n\\n\\n```python\\nquarterly_count = hr_df_full[\'value\'].sum()\\nleap_day_count = hr_df_full[(hr_df_full.index.month == 2) &\\n (hr_df_full.index.day == 29)][\'value\'].sum()\\nnum_quarters = 96\\nleap_days = 6\\n\\njan_92_jan_16 = quarterly_count * num_quarters - leap_day_count * (num_quarters - leap_days)\\njan_92_jan_16\\n```\\n\\n```\\n 773609400\\n```\\n\\nSo between January 1992 and January 2016 I\'ve used $\\\\approx$ 774 million heartbeats. Now, I need to go back to my exact birthday. I\'m going to first find on average how many heartbeats I use in a minute, and multiply that by the number of minutes between my birthday and January 1992.\\n\\nFor privacy purposes I\'ll put the code here that I\'m using, but without any identifying information:\\n\\n\\n```python\\nminute_mean = hr_df_full[\'value\'].mean()\\n# Don\'t you wish you knew?\\n# birthday_minutes = ???\\n\\nbirthday_heartbeats = birthday_minutes * minute_mean\\n\\nheartbeats_until_2016 = int(birthday_heartbeats + jan_92_jan_16)\\nremaining_2016 = total_heartbeats - heartbeats_until_2016\\n\\nprint(\\"Heartbeats so far: {}\\".format(heartbeats_until_2016))\\nprint(\\"Remaining heartbeats: {}\\".format(remaining_2016))\\n```\\n\\n```\\n Heartbeats so far: 775804660\\n Remaining heartbeats: 1724195340\\n```\\n\\nIt would appear that my heart has beaten 775,804,660 times between my moment of birth and January 1<sup>st</sup> 2016, and that I have 1.72 billion left.\\n\\n### How many heartbeats longer?\\n\\nNow comes the tricky bit. I know how many heart beats I\'ve used so far, and how many I have remaining, so I\'d like to come up with a (relatively) accurate estimate of when exactly my heart should give out. We\'ll do this in a few steps, increasing in granularity.\\n\\nFirst step, how many heartbeats do I use in a 4-year period? I have data for a single quarter including leap day, so I want to know:\\n\\n$$\\n\\\\begin{equation*}\\nhr_q \\\\cdot n - hr_d \\\\cdot (n - m)\\n\\\\end{equation*}\\n$$\\n\\n- $hr_q$: Heartbeats per quarter\\n- $hr_d$: Heartbeats per leap day\\n- $n$: Number of quarters = 16\\n- $m$: Number of leap days = 1\\n\\n\\n```python\\nheartbeats_4year = quarterly_count * 16 - leap_day_count * (16 - 1)\\nheartbeats_4year\\n```\\n\\n```\\n 128934900\\n```\\n\\nNow, I can fast forward from 2016 the number of periods of 4 years I have left.\\n\\n```python\\nfour_year_periods = remaining_2016 // heartbeats_4year\\nremaining_4y = remaining_2016 - four_year_periods * heartbeats_4year\\n\\nprint(\\"Four year periods remaining: {}\\".format(four_year_periods))\\nprint(\\"Remaining heartbeats after 4 year periods: {}\\".format(remaining_4y))\\n```\\n\\n```\\n Four year periods remaining: 13\\n Remaining heartbeats after 4 year periods: 48041640\\n```\\n\\nGiven that there are 13 four-year periods left, I can move from 2016 all the way to 2068, and find that I will have 48 million heart beats left. Let\'s drop down to figuring out how many quarters that is. I know that 2068 will have a leap day (unless someone finally decides to get rid of them), so I\'ll subtract that out first. Then, I\'m left to figure out how many quarters exactly are left.\\n\\n```python\\nremaining_leap = remaining_4y - leap_day_count\\n# Ignore leap day in the data set\\nheartbeats_quarter = hr_df_full[(hr_df_full.index.month != 2) &\\n (hr_df_full.index.day != 29)][\'value\'].sum()\\nquarters_left = remaining_leap // heartbeats_quarter\\nremaining_year = remaining_leap - quarters_left * heartbeats_quarter\\n\\nprint(\\"Quarters left starting 2068: {}\\".format(quarters_left))\\nprint(\\"Remaining heartbeats after that: {}\\".format(remaining_year))\\n```\\n\\n```\\n Quarters left starting 2068: 8\\n Remaining heartbeats after that: 4760716\\n```\\n\\nSo, that analysis gets me through until January 1<sup>st</sup> 2070. Final step, using that minute estimate to figure out how many minutes past that I\'m predicted to have:\\n\\n\\n```python\\nfrom datetime import timedelta\\n\\nbase = datetime(2070, 1, 1)\\nminutes_left = remaining_year // minute_mean\\n\\nkaput = timedelta(minutes=minutes_left)\\nbase + kaput\\n```\\n\\n```\\n datetime.datetime(2070, 2, 23, 5, 28)\\n```\\n\\nAccording to this, I\'ve got until February 23<sup>rd</sup>, 2070 at 5:28 PM in the evening before my heart gives out.\\n\\n## Summary\\n\\nWell, that\'s kind of a creepy date to know. As I said at the top though, **this number is totally useless in any medical context**. It ignores the rate at which we continue to get better at making people live longer, and is extrapolating from 3 months\' worth of data the rest of my life. Additionally, throughout my time developing this post I made many minor mistakes. I think they\'re all fixed now, but it\'s easy to mix a number up here or there and the analysis gets thrown off by a couple years.\\n\\nEven still, I think philosophically humans have a desire to know how much time we have left in the world. [Man is but a breath](https://www.biblegateway.com/passage/?search=psalm+144&version=ESV), and it\'s scary to think just how quickly that date may be coming up. This analysis asks an important question though: what are you going to do with the time you have left?\\n\\nThanks for sticking with me on this one, I promise it will be much less depressing next time!"},{"id":"2016/03/tweet-like-me","metadata":{"permalink":"/2016/03/tweet-like-me","source":"@site/blog/2016-03-28-tweet-like-me/index.mdx","title":"Tweet like me","description":"In which I try to create a robot that will tweet like I tweet.","date":"2016-03-28T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/tweet-like-me","title":"Tweet like me","date":"2016-03-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"},"nextItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"}},"content":"In which I try to create a robot that will tweet like I tweet.\\n\\n\x3c!-- truncate --\x3e\\n\\nSo, I\'m taking a Machine Learning course this semester in school, and one of the topics we keep coming back to is natural language processing and the \'bag of words\' data structure. That is, given a sentence:\\n\\n`How much wood would a woodchuck chuck if a woodchuck could chuck wood?`\\n\\nWe can represent that sentence as the following list:\\n\\n`{\\n How: 1\\n much: 1\\n wood: 2\\n would: 2\\n a: 2\\n woodchuck: 2\\n chuck: 2\\n if: 1\\n}`\\n\\nIgnoring *where* the words happened, we\'re just interested in how *often* the words occurred. That got me thinking: I wonder what would happen if I built a robot that just imitated how often I said things? It\'s dangerous territory when computer scientists ask \\"what if,\\" but I got curious enough I wanted to follow through.\\n\\n## The Objective\\n\\nGiven an input list of Tweets, build up the following things:\\n\\n1. The distribution of starting words; since there are no \\"prior\\" words to go from, we need to treat this as a special case.\\n2. The distribution of words given a previous word; for example, every time I use the word `woodchuck` in the example sentence, there is a 50% chance it is followed by `chuck` and a 50% chance it is followed by `could`. I need this distribution for all words.\\n3. The distribution of quantity of hashtags; Do I most often use just one? Two? Do they follow something like a Poisson distribution?\\n4. Distribution of hashtags; Given a number of hashtags, what is the actual content? I\'ll treat hashtags as separate from the content of a tweet.\\n\\n## The Data\\n\\nI\'m using as input my tweet history. I don\'t really use Twitter anymore, but it seems like a fun use of the dataset. I\'d like to eventually build this to a point where I can imitate anyone on Twitter using their last 100 tweets or so, but I\'ll start with this as example code.\\n\\n## The Algorithm\\n\\nI\'ll be using the [NLTK](http://www.nltk.org/) library for doing a lot of the heavy lifting. First, let\'s import the data:\\n\\n\\n```python\\nimport pandas as pd\\n\\ntweets = pd.read_csv(\'tweets.csv\')\\ntext = tweets.text\\n\\n# Don\'t include tweets in reply to or mentioning people\\nreplies = text.str.contains(\'@\')\\ntext_norep = text.loc[~replies]\\n```\\n\\nAnd now that we\'ve got data, let\'s start crunching. First, tokenize and build out the distribution of first word:\\n\\n\\n```python\\nfrom nltk.tokenize import TweetTokenizer\\ntknzr = TweetTokenizer()\\ntokens = text_norep.map(tknzr.tokenize)\\n\\nfirst_words = tokens.map(lambda x: x[0])\\nfirst_words_alpha = first_words[first_words.str.isalpha()]\\nfirst_word_dist = first_words_alpha.value_counts() / len(first_words_alpha)\\n```\\n\\nNext, we need to build out the conditional distributions. That is, what is the probability of the next word given the current word is $X$? This one is a bit more involved. First, find all unique words, and then find what words proceed them. This can probably be done in a more efficient manner than I\'m currently doing here, but we\'ll ignore that for the moment.\\n\\n\\n```python\\nfrom functools import reduce\\n\\n# Get all possible words\\nall_words = reduce(lambda x, y: x+y, tokens, [])\\nunique_words = set(all_words)\\nactual_words = set([x if x[0] != \'.\' else None for x in unique_words])\\n\\nword_dist = {}\\nfor word in iter(actual_words):\\n indices = [i for i, j in enumerate(all_words) if j == word]\\n proceeding = [all_words[i+1] for i in indices]\\n word_dist[word] = proceeding\\n```\\n\\nNow that we\'ve got the tweet analysis done, it\'s time for the fun part: hashtags! Let\'s count how many hashtags are in each tweet, I want to get a sense of the distribution.\\n\\n\\n```python\\nimport matplotlib.pyplot as plt\\n%matplotlib inline\\n\\nhashtags = text_norep.str.count(\'#\')\\nbins = hashtags.unique().max()\\nhashtags.plot(kind=\'hist\', bins=bins)\\n```\\n\\n```\\n <matplotlib.axes._subplots.AxesSubplot at 0x18e59dc28d0>\\n```\\n\\n \\n![png](_notebook_files/_notebook_7_1.png)\\n \\n\\nThat looks like a Poisson distribution, kind of as I expected. I\'m guessing my number of hashtags per tweet is $\\\\sim Poi(1)$, but let\'s actually find the [most likely estimator](https://en.wikipedia.org/wiki/Poisson_distribution#Maximum_likelihood) which in this case is just $\\\\bar{\\\\lambda}$:\\n\\n\\n```python\\nmle = hashtags.mean()\\nmle\\n```\\n\\n```\\n 0.870236869207003\\n```\\n\\n\\nPretty close! So we can now simulate how many hashtags are in a tweet. Let\'s also find what hashtags are actually used:\\n\\n\\n```python\\nhashtags = [x for x in all_words if x[0] == \'#\']\\nn_hashtags = len(hashtags)\\n\\nunique_hashtags = list(set([x for x in unique_words if x[0] == \'#\']))\\nhashtag_dist = pd.DataFrame({\'hashtags\': unique_hashtags,\\n \'prob\': [all_words.count(h) / n_hashtags\\n for h in unique_hashtags]})\\nlen(hashtag_dist)\\n```\\n\\n```\\n 603\\n```\\n\\nTurns out I have used 603 different hashtags during my time on Twitter. That means I was using a unique hashtag for about every third tweet.\\n\\nIn better news though, we now have all the data we need to go about actually constructing tweets! The process will happen in a few steps:\\n\\n1. Randomly select what the first word will be.\\n2. Randomly select the number of hashtags for this tweet, and then select the actual hashtags.\\n3. Fill in the remaining space of 140 characters with random words taken from my tweets.\\n\\nAnd hopefully, we won\'t have anything too crazy come out the other end. The way we do the selection follows a [Multinomial Distribution](https://en.wikipedia.org/wiki/Multinomial_distribution): given a lot of different values with specific probability, pick one. Let\'s give a quick example:\\n\\n```\\nx: .33\\ny: .5\\nz: .17\\n```\\n\\nThat is, I pick `x` with probability 33%, `y` with probability 50%, and so on. In context of our sentence construction, I\'ve built out the probabilities of specific words already - now I just need to simulate that distribution. Time for the engine to actually be developed!\\n\\n\\n```python\\nimport numpy as np\\n\\ndef multinom_sim(n, vals, probs):\\n occurrences = np.random.multinomial(n, probs)\\n results = occurrences * vals\\n return \' \'.join(results[results != \'\'])\\n\\ndef sim_n_hashtags(hashtag_freq):\\n return np.random.poisson(hashtag_freq)\\n\\ndef sim_hashtags(n, hashtag_dist):\\n return multinom_sim(n, hashtag_dist.hashtags, hashtag_dist.prob)\\n\\ndef sim_first_word(first_word_dist):\\n probs = np.float64(first_word_dist.values)\\n return multinom_sim(1, first_word_dist.reset_index()[\'index\'], probs)\\n\\ndef sim_next_word(current, word_dist):\\n dist = pd.Series(word_dist[current])\\n probs = np.ones(len(dist)) / len(dist)\\n return multinom_sim(1, dist, probs)\\n```\\n\\n## Pulling it all together\\n\\nI\'ve now built out all the code I need to actually simulate a sentence written by me. Let\'s try doing an example with five words and a single hashtag:\\n\\n\\n```python\\nfirst = sim_first_word(first_word_dist)\\nsecond = sim_next_word(first, word_dist)\\nthird = sim_next_word(second, word_dist)\\nfourth = sim_next_word(third, word_dist)\\nfifth = sim_next_word(fourth, word_dist)\\nhashtag = sim_hashtags(1, hashtag_dist)\\n\\n\' \'.join((first, second, third, fourth, fifth, hashtag))\\n```\\n\\n```\\n \'My first all-nighter of friends #oldschool\'\\n```\\n\\nLet\'s go ahead and put everything together! We\'re going to simulate a first word, simulate the hashtags, and then simulate to fill the gap until we\'ve either taken up all the space or reached a period.\\n\\n\\n```python\\ndef simulate_tweet():\\n chars_remaining = 140\\n first = sim_first_word(first_word_dist)\\n n_hash = sim_n_hashtags(mle)\\n hashtags = sim_hashtags(n_hash, hashtag_dist)\\n \\n chars_remaining -= len(first) + len(hashtags)\\n \\n tweet = first\\n current = first\\n while chars_remaining > len(tweet) + len(hashtags) and current[0] != \'.\' and current[0] != \'!\':\\n current = sim_next_word(current, word_dist)\\n tweet += \' \' + current\\n \\n tweet = tweet[:-2] + tweet[-1]\\n \\n return \' \'.join((tweet, hashtags)).strip()\\n```\\n\\n## The results\\n\\nAnd now for something completely different: twenty random tweets dreamed up by my computer and my Twitter data. Here you go:\\n\\n\\n```python\\nfor i in range(0, 20):\\n print(simulate_tweet())\\n print()\\n```\\n\\n```\\n Also , I\'m at 8 this morning. #thursdaysgohard #ornot\\n \\n Turns out of us breathe the code will want to my undergraduate career is becoming more night trying ? Religion is now as a chane #HYPE\\n \\n You know what recursion is to review the UNCC. #ornot\\n \\n There are really sore 3 bonfires in my first writing the library ground floor if awesome. #realtalk #impressed\\n \\n So we can make it out there\'s nothing but I\'m not let us so hot I could think I may be good. #SwingDance\\n \\n Happy Christmas , at Harris Teeter to be be godly or Roman Catholic ). #4b392b#4b392b #Isaiah26\\n \\n For context , I in the most decisive factor of the same for homework. #accomplishment\\n \\n Freaking done. #loveyouall\\n \\n New blog post : Don\'t jump in a quiz in with a knife fight. #haskell #earlybirthday\\n \\n God shows me legitimately want to get some food and one day.\\n \\n Stormed the queen city. #mindblown\\n \\n The day of a cold at least outside right before the semester ..\\n \\n Finished with the way back. #winners\\n \\n Waking up , OJ , I feel like Nick Jonas today.\\n \\n First draft of so hard drive. #humansvszombies\\n \\n Eric Whitacre is the wise creation.\\n \\n Ethics paper first , music in close to everyone who just be posting up with my sin , and Jerry Springr #TheLittleThings\\n \\n Love that you know enough time I\'ve eaten at 8 PM. #deepthoughts #stillblownaway\\n \\n Lead. #ThinkingTooMuch #Christmas\\n \\n Aamazing conference when you married #DepartmentOfRedundancyDepartment Yep , but there\'s a legitimate challenge.\\n```\\n\\n\\n...Which all ended up being a whole lot more nonsensical than I had hoped for. There are some good ones, so I\'ll call that an accomplishment! I was banking on grammar not being an issue: since my tweets use impeccable grammar, the program modeled off them should have pretty good grammar as well. There are going to be some hilarious edge cases (I\'m looking at you, `Ethics paper first, music in close to everyone`) that make no sense, and some hilarious edge cases (`Waking up, OJ, I feel like Nick Jonas today`) that make me feel like I should have a Twitter rap career. On the whole though, the structure came out alright.\\n\\n## Moving on from here\\n\\nDuring class we also talked about an interesting idea: trying to analyze corporate documents and corporate speech. I\'d be interested to know what this analysis applied to something like a couple of bank press releases could do. By any means, the code needs some work to clean it up before I get that far.\\n\\n## For further reading\\n\\nI\'m pretty confident I re-invented a couple wheels along the way - what I\'m doing feels a lot like what [Markov Chain Monte Carlo](https://en.wikipedia.org/wiki/Markov_chain_Monte_Carlo) is intended to do. But I\'ve never worked explicitly with that before, so more research is needed."},{"id":"2016/03/predicting-santander-customer-happiness","metadata":{"permalink":"/2016/03/predicting-santander-customer-happiness","source":"@site/blog/2016-03-05-predicting-santander-customer-happiness/index.mdx","title":"Predicting Santander customer happiness","description":"My first Kaggle competition.","date":"2016-03-05T12:00:00.000Z","tags":[],"readingTime":6.95,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/predicting-santander-customer-happiness","title":"Predicting Santander customer happiness","date":"2016-03-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"},"nextItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"}},"content":"My first Kaggle competition.\\n\\n\x3c!-- truncate --\x3e\\n\\nIt\'s time! After embarking on a Machine Learning class this semester, and with a Saturday in which I don\'t have much planned, I wanted to put this class and training to work. It\'s my first competition submission. I want to walk you guys through how I\'m approaching this problem, because I thought it would be really neat. The competition is Banco Santander\'s [Santander Customer Satisfaction][1] competition. It seemed like an easy enough problem I could actually make decent progress on it.\\n\\n## Data Exploration\\n\\nFirst up: we need to load our data and do some exploratory work. Because we\'re going to be using this data for model selection prior to testing, we need to make a further split. I\'ve already gone ahead and done this work, please see the code in the [appendix below](#appendix).\\n\\n[1]: https://www.kaggle.com/c/santander-customer-satisfaction\\n\\n\\n```python\\nimport pandas as pd\\nimport numpy as np\\nimport matplotlib.pyplot as plt\\n%matplotlib inline\\n\\n# Record how long it takes to run the notebook - I\'m curious.\\nfrom datetime import datetime\\nstart = datetime.now()\\n\\ndataset = pd.read_csv(\'split_train.csv\')\\ndataset.index = dataset.ID\\nX = dataset.drop([\'TARGET\', \'ID\', \'ID.1\'], 1)\\ny = dataset.TARGET\\n```\\n\\n\\n```python\\ny.unique()\\n```\\n\\n```\\n array([0, 1], dtype=int64)\\n```\\n\\n```python\\nlen(X.columns)\\n```\\n\\n```\\n 369\\n```\\n\\nOkay, so there are only [two classes we\'re predicting][2]: 1 for unsatisfied customers, 0 for satisfied customers. I would have preferred this to be something more like a regression, or predicting multiple classes: maybe the customer isn\'t the most happy, but is nowhere near closing their accounts. For now though, that\'s just the data we\'re working with.\\n\\nNow, I\'d like to make a scatter matrix of everything going on. Unfortunately as noted above, we have 369 different features. There\'s no way I can graphically make sense of that much data to start with.\\n\\nWe\'re also not told what the data actually represents: Are these survey results? Average time between contact with a customer care person? Frequency of contacting a customer care person? The idea is that I need to reduce the number of dimensions we\'re predicting across.\\n\\n### Dimensionality Reduction pt. 1 - Binary Classifiers\\n\\nMy first attempt to reduce the data dimensionality is to find all the binary classifiers in the dataset \\\\(i.e. 0 or 1 values\\\\) and see if any of those are good \\\\(or anti-good\\\\) predictors of the final data.\\n\\n[2]: https://www.kaggle.com/c/santander-customer-satisfaction/data\\n\\n\\n```python\\ncols = X.columns\\nb_class = []\\nfor c in cols:\\n if len(X[c].unique()) == 2:\\n b_class.append(c)\\n \\nlen(b_class)\\n```\\n\\n```\\n 111\\n```\\n\\nSo there are 111 features in the dataset that are a binary label. Let\'s see if any of them are good at predicting the users satisfaction!\\n\\n```python\\n# First we need to `binarize` the data to 0-1; some of the labels are {0, 1},\\n# some are {0, 3}, etc.\\nfrom sklearn.preprocessing import binarize\\nX_bin = binarize(X[b_class])\\n\\naccuracy = [np.mean(X_bin[:,i] == y) for i in range(0, len(b_class))]\\nacc_df = pd.DataFrame({\\"Accuracy\\": accuracy}, index=b_class)\\nacc_df.describe()\\n```\\n\\n<div>\\n<table>\\n <thead>\\n <tr>\\n <th></th>\\n <th>Accuracy</th>\\n </tr>\\n </thead>\\n <tbody>\\n <tr>\\n <th>count</th>\\n <td>111.000000</td>\\n </tr>\\n <tr>\\n <th>mean</th>\\n <td>0.905159</td>\\n </tr>\\n <tr>\\n <th>std</th>\\n <td>0.180602</td>\\n </tr>\\n <tr>\\n <th>min</th>\\n <td>0.043598</td>\\n </tr>\\n <tr>\\n <th>25%</th>\\n <td>0.937329</td>\\n </tr>\\n <tr>\\n <th>50%</th>\\n <td>0.959372</td>\\n </tr>\\n <tr>\\n <th>75%</th>\\n <td>0.960837</td>\\n </tr>\\n <tr>\\n <th>max</th>\\n <td>0.960837</td>\\n </tr>\\n </tbody>\\n</table>\\n</div>\\n\\nWow! Looks like we\'ve got some incredibly predictive features! So much so that we should be a bit concerned. My initial guess for what\'s happening is that we have a sparsity issue: so many of the values are 0, and these likely happen to line up with satisfied customers.\\n\\nSo the question we must now answer, which I likely should have asked long before now: What exactly is the distribution of un/satisfied customers?\\n\\n```python\\nunsat = y[y == 1].count()\\nprint(\\"Satisfied customers: {}; Unsatisfied customers: {}\\".format(len(y) - unsat, unsat))\\nnaive_guess = np.mean(y == np.zeros(len(y)))\\nprint(\\"Naive guess accuracy: {}\\".format(naive_guess))\\n```\\n\\n```\\n Satisfied customers: 51131; Unsatisfied customers: 2083\\n Naive guess accuracy: 0.9608561656706882\\n```\\n\\nThis is a bit discouraging. A naive guess of \\"always satisfied\\" performs as well as our best individual binary classifier. What this tells me then, is that these data columns aren\'t incredibly helpful in prediction. I\'d be interested in a polynomial expansion of this data-set, but for now, that\'s more computation than I want to take on.\\n\\n### Dimensionality Reduction pt. 2 - LDA\\n\\nKnowing that our naive guess performs so well is a blessing and a curse:\\n\\n- Curse: The threshold for performance is incredibly high: We can only \\"improve\\" over the naive guess by 4%\\n- Blessing: All the binary classification features we just discovered are worthless on their own. We can throw them out and reduce the data dimensionality from 369 to 111.\\n\\nNow, in removing these features from the dataset, I\'m not saying that there is no \\"information\\" contained within them. There might be. But the only way we\'d know is through a polynomial expansion, and I\'m not going to take that on within this post.\\n\\nMy initial thought for a \\"next guess\\" is to use the [LDA][3] model for dimensionality reduction. However, it can only reduce dimensions to $1 - p$, with $p$ being the number of classes. Since this is a binary classification, every LDA model that I try will have dimensionality one; when I actually try this, the predictor ends up being slightly less accurate than the naive guess.\\n\\nInstead, let\'s take a different approach to dimensionality reduction: [principle components analysis][4]. This allows us to perform the dimensionality reduction without worrying about the number of classes. Then, we\'ll use a [Gaussian Naive Bayes][5] model to actually do the prediction. This model is chosen simply because it doesn\'t take a long time to fit and compute; because PCA will take so long, I just want a prediction at the end of this. We can worry about using a more sophisticated LDA/QDA/SVM model later.\\n\\nNow into the actual process: We\'re going to test out PCA dimensionality reduction from 1 - 20 dimensions, and then predict using a Gaussian Naive Bayes model. The 20 dimensions upper limit was selected because the accuracy never improves after you get beyond that \\\\(I found out by running it myself\\\\). Hopefully, we\'ll find that we can create a model better than the naive guess.\\n\\n[3]:http://scikit-learn.org/stable/modules/lda_qda.html\\n[4]:http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html\\n[5]:http://scikit-learn.org/stable/modules/naive_bayes.html#gaussian-naive-bayes\\n\\n\\n```python\\nfrom sklearn.naive_bayes import GaussianNB\\nfrom sklearn.decomposition import PCA\\n\\nX_no_bin = X.drop(b_class, 1)\\n\\ndef evaluate_gnb(dims):\\n pca = PCA(n_components=dims)\\n X_xform = pca.fit_transform(X_no_bin)\\n \\n gnb = GaussianNB()\\n gnb.fit(X_xform, y)\\n return gnb.score(X_xform, y)\\n\\ndim_range = np.arange(1, 21)\\nplt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label=\\"Gaussian NB Accuracy\\")\\nplt.axhline(naive_guess, label=\\"Naive Guess\\", c=\'k\')\\nplt.axhline(1 - naive_guess, label=\\"Inverse Naive Guess\\", c=\'k\')\\nplt.gcf().set_size_inches(12, 6)\\nplt.legend();\\n```\\n\\n![png](_notebook_files/_notebook_11_0.png)\\n\\n**sigh...** After all the effort and computational power, we\'re still at square one: we have yet to beat out the naive guess threshold. With PCA in play we end up performing terribly, but not terribly enough that we can guess against ourselves.\\n\\nLet\'s try one last-ditch attempt using the entire data set:\\n\\n\\n```python\\ndef evaluate_gnb_full(dims):\\n pca = PCA(n_components=dims)\\n X_xform = pca.fit_transform(X)\\n \\n gnb = GaussianNB()\\n gnb.fit(X_xform, y)\\n return gnb.score(X_xform, y)\\n\\ndim_range = np.arange(1, 21)\\nplt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label=\\"Gaussian NB Accuracy\\")\\nplt.axhline(naive_guess, label=\\"Naive Guess\\", c=\'k\')\\nplt.axhline(1 - naive_guess, label=\\"Inverse Naive Guess\\", c=\'k\')\\nplt.gcf().set_size_inches(12, 6)\\nplt.legend();\\n```\\n\\n![png](_notebook_files/_notebook_13_0.png)\\n\\nNothing. It is interesting to note that the graphs are almost exactly the same: This would imply again that the variables we removed earlier (all the binary classifiers) indeed have almost no predictive power. It seems this problem is high-dimensional, but with almost no data that can actually inform our decisions.\\n\\n## Summary for Day 1\\n\\nAfter spending a couple hours with this dataset, there seems to be a fundamental issue in play: We have very high-dimensional data, and it has no bearing on our ability to actually predict customer satisfaction. This can be a huge issue: it implies that **no matter what model we use, we fundamentally can\'t perform well.** I\'m sure most of this is because I\'m not an experienced data scientist. Even so, we have yet to develop a strategy that can actually beat out the village idiot; **so far, the bank is best off just assuming all its customers are satisfied.** Hopefully more to come soon.\\n\\n\\n```python\\nend = datetime.now()\\nprint(\\"Running time: {}\\".format(end - start))\\n```\\n\\n```\\n Running time: 0:00:58.715714\\n```\\n\\n## Appendix\\n\\nCode used to split the initial training data:\\n\\n```python\\nfrom sklearn.cross_validation import train_test_split\\ndata = pd.read_csv(\'train.csv\')\\ndata.index = data.ID\\n\\ndata_train, data_validate = train_test_split(\\n data, train_size=.7)\\n\\ndata_train.to_csv(\'split_train.csv\')\\ndata_validate.to_csv(\'split_validate.csv\')\\n```"},{"id":"2016/02/profitability-using-the-investment-formula","metadata":{"permalink":"/2016/02/profitability-using-the-investment-formula","source":"@site/blog/2016-02-26-profitability-using-the-investment-formula/index.mdx","title":"Profitability using the investment formula","description":"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?","date":"2016-02-26T12:00:00.000Z","tags":[],"readingTime":7.675,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/profitability-using-the-investment-formula","title":"Profitability using the investment formula","date":"2016-02-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"},"nextItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"}},"content":"After developing a formula to guide our investing, how do we actually evaluate its performance in the real world?\\n\\n\x3c!-- truncate --\x3e\\n\\nI\'ve previously talked about crafting an [Investment Formula](../2016-02-03-guaranteed-money-maker/index.mdx) that would guarantee making money if you could predict which direction the stock market was going to go. This is going to be the first in a series of posts trying to flesh out what an actual investment strategy based on this formula would look like.\\n\\nBut first, the formula doesn\'t take into account two very important things: **leverage**, and the **number of days invested**. That\'s why I want to set up what I\'m going to call the **Profitability Score**.\\n\\nThe definition is going to be very simple:\\n\\n- $p$: Profit made once you exit the investment\\n- $i$: Initial investment into the asset\\n- $m$: Maximum investment in the asset\\n- $l = m / i$: The maximum leverage of an investment, as the ratio of maximum invested to initial investment\\n- $d$: The number of days it takes to turn a profit\\n\\n$s = \\\\frac{1000 p}{i(l + d)} = \\\\frac{1000 p}{m + i\\\\cdot d}$\\n\\nCrazy, right? The score is simply the (normalized) profit you made divided by the leverage plus days invested. The $\\\\cdot 1000$ is just to turn the number into something more reasonable - people don\'t like hearing something with a profitability score of .001 for example.\\n\\n## Theoretical Justification\\n\\nThe formula itself is designed to be simple in principle: I like making a profit, and I want to penalize the leverage you incur and days you have to invest. Ideally, we want to have a stock that goes up all the time. However, the investment formula takes advantage of a different case: trying to profit from highly volatile assets. If we can make money when the investment only has one day up, let\'s do it!\\n\\nEven so, there are two potential issues: First, stocks that trend upward will have a higher profitability score - both leverage and days invested will be 1. To protect against only investing in this trend, I can do things like taking $\\\\log(d)$. I don\'t want to start biasing the scoring function until I have a practical reason to do so, so right now I\'ll leave it standing.\\n\\nThe second issue is how to penalize leverage and days invested relative to each other. As it currently stands, a leverage of 6x with only 1 day invested is the same as leveraging 2x with 3 days invested. In the future, I\'d again want to look at making the impact of days invested smaller - I can get over an extra 3 days in the market if it means that I don\'t have to incur a highly leveraged position.\\n\\nSo there could be things about the scoring function we change in the future, but I want to run some actual tests before we start worrying about things like that!\\n\\n## Running a simulation\\n\\nThis won\'t be an incredibly rigorous backtest, I just want to see some results from the work so far. Let\'s set up the simulation code again, and start looking into some random stocks. **If you\'ve read the last blog post, you can skip over the code.** The only difference is that it\'s been ported to python to make the data-wrangling easier. Julia doesn\'t yet support some of the multi-index things I\'m trying to do.\\n\\n\\n```python\\nimport numpy as np\\nimport pandas as pd\\nimport matplotlib.pyplot as plt\\nfrom Quandl import get as qget\\n%matplotlib inline\\napi_key = \'\'\\n\\nprofitability = lambda p, i, m, d: 1000*p / (m + i*d)\\n\\ndef is_profitable(current_price, purchase_history, open_history):\\n shares = (purchase_history / open_history).sum()\\n return current_price * shares > sum(purchase_history)\\n\\ndef daily_investment(current_open, current_close, purchase_history, open_history):\\n t1 = current_close / current_open - 1\\n t2 = (purchase_history - purchase_history * current_close / open_history).sum()\\n return t2 / t1\\n\\ndef simulate_day(open_vals, close_vals, init, expected, bias):\\n invested = np.array([init])\\n \\n day = 1\\n profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\\\\\n or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])\\n\\n while not profitable:\\n expected_close = open_vals[day] * expected\\n todays_purchase = daily_investment(open_vals[day], expected_close, invested, open_vals[0:day])\\n invested = np.append(invested, todays_purchase + bias)\\n # expected_profit = expected_close * (invested / open_vals[0:len(invested)]).sum() - invested.sum()\\n day += 1\\n profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\\\\\n or is_profitable(open_vals[day], invested, open_vals[0:len(invested)])\\n \\n shares = (invested / open_vals[0:len(invested)]).sum()\\n \\n # Make sure we can\'t see into the future - we know either today\'s close or tomorrow\'s open\\n # will be profitable, but we need to check which one.\\n if is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]):\\n ending_price = close_vals[day-1]\\n else:\\n ending_price = open_vals[day]\\n \\n profit = shares * ending_price - sum(invested)\\n return invested, profit\\n\\ndef simulate_ts(name, start, end, initial, expected, bias):\\n ticker_info = qget(name, trim_start=start, api_key=api_key)\\n evaluation_times = ticker_info[:end].index\\n \\n # Handle Google vs. YFinance data\\n if \\"Adjusted Close\\" in ticker_info.columns:\\n close_column = \\"Adjusted Close\\"\\n else:\\n close_column = \\"Close\\"\\n \\n sim = {d: simulate_day(ticker_info[d:][\\"Open\\"], ticker_info[d:][close_column],\\n 100, 1.02, 10) for d in evaluation_times}\\n sim_series = pd.Series(sim)\\n result = pd.DataFrame()\\n result[\\"profit\\"] = sim_series.apply(lambda x: x[1])\\n result[\\"max\\"] = sim_series.apply(lambda x: max(x[0]))\\n result[\\"days\\"] = sim_series.apply(lambda x: len(x[0]))\\n result[\\"score\\"] = sim_series.apply(lambda x: profitability(x[1], x[0][0], max(x[0]), len(x[0])))\\n result[\\"investments\\"] = sim_series.apply(lambda x: x[0])\\n \\n return result\\n\\ndef simulate_tickers(tickers):\\n from datetime import datetime\\n results = {}\\n for ticker in tickers:\\n start = datetime(2015, 1, 1)\\n results_df = simulate_ts(ticker, start, datetime(2016, 1, 1), 100, 1.01, 10)\\n results[ticker] = results_df\\n \\n return pd.concat(list(results.values()), keys=list(results.keys()), axis=1)\\n```\\n\\n## And now the interesting part\\n\\nLet\'s start looking into the data! FANG stocks have been big over the past year, let\'s see how they look:\\n\\n\\n```python\\nfang_df = simulate_tickers([\\"YAHOO/FB\\", \\"YAHOO/AAPL\\", \\"YAHOO/NFLX\\", \\"YAHOO/GOOG\\"])\\n```\\n\\n```python\\nfang_df.xs(\'days\', axis=1, level=1).hist()\\nplt.gcf().set_size_inches(18, 8);\\nplt.gcf().suptitle(\\"Distribution of Days Until Profitability\\", fontsize=18);\\n```\\n\\n![png](_notebook_files/_notebook_4_0.png)\\n\\n```python\\nfang_df.xs(\'score\', axis=1, level=1).plot()\\nplt.gcf().set_size_inches(18, 6)\\nplt.gcf().suptitle(\\"Profitability score over time\\", fontsize=18);\\n```\\n \\n![png](_notebook_files/_notebook_5_0.png)\\n \\nLet\'s think about these graphs. First, the histogram. What we like seeing is a lot of 1\'s - that means there were a lot of days that the stock went up and we didn\'t have to worry about actually implementing the strategy - we were able to close the trade at a profit.\\n\\nLooking at the profitability score over time though is a bit more interesting. First off, stocks that are more volatile will tend to have a higher profitability score, no two ways about that. However, Netflix consistently outperformed on this metric. We know that 2015 was a good year for Netflix, so that\'s a (small) sign the strategy is performing as expected.\\n\\nThe final interesting note happens around the end of August 2015. Around this period, the markets were selling off in a big way due to issues in China (not unlike what\'s happening now). Even so, all of the FANG stocks saw an uptick in profitability around this time. This is another sign that the strategy being developed performs better during periods of volatility, rather than from riding markets up or down.\\n\\nWhat about FANG vs. some cyclicals?\\n\\n```python\\ncyclic_df = simulate_tickers([\\"YAHOO/X\\", \\"YAHOO/CAT\\", \\"YAHOO/NFLX\\", \\"YAHOO/GOOG\\"])\\n```\\n\\n```python\\ncyclic_df.xs(\'days\', axis=1, level=1).hist()\\nplt.gcf().set_size_inches(18, 8);\\nplt.gcf().suptitle(\\"Distribution of Days Until Profitability\\", fontsize=18);\\n```\\n \\n![png](_notebook_files/_notebook_8_0.png)\\n \\n\\n```python\\ncyclic_df.xs(\'score\', axis=1, level=1).plot()\\nplt.gcf().set_size_inches(18, 6)\\nplt.gcf().suptitle(\\"Profitability score over time\\", fontsize=18);\\n```\\n\\n![png](_notebook_files/_notebook_9_0.png)\\n\\nSome more interesting results come from this as well. First off, US Steel (X) has a much smoother distribution of days until profitability - it doesn\'t have a huge number of values at 1 and then drop off. Intuitively, we\'re not terribly large fans of this, we want a stock to go up! However, on the profitability score it is the only serious contender to Netflix.\\n\\nSecond, we see the same trend around August - the algorithm performs well in volatile markets.\\n\\nFor a final test, let\'s try some biotech and ETFs!\\n\\n```python\\nbiotech_df = simulate_tickers([\'YAHOO/REGN\', \'YAHOO/CELG\', \'GOOG/NASDAQ_BIB\', \'GOOG/NASDAQ_IBB\'])\\n```\\n\\n```python\\nbiotech_df.xs(\'days\', axis=1, level=1).hist()\\nplt.gcf().set_size_inches(18, 8);\\nplt.gcf().suptitle(\\"Distribution of Days Until Profitability\\", fontsize=18);\\n```\\n \\n![png](_notebook_files/_notebook_12_0.png)\\n \\n```python\\nbiotech_df.xs(\'score\', axis=1, level=1).plot()\\nplt.gcf().set_size_inches(18, 6)\\nplt.gcf().suptitle(\\"Profitability score over time\\", fontsize=18);\\n```\\n \\n![png](_notebook_files/_notebook_13_0.png)\\n\\nIn this example, we don\'t see a whole lot of interesting things: the scores are all fairly close together with notable exceptions in late August, and mid-October.\\n\\nWhat is interesting is that during the volatile period, the ETF\'s performed significantly better than the stocks did in terms of profitability. The leveraged ETF (BIB) performed far above anyone else, and it appears that indeed, it is most profitable during volatile periods. Even so, it was far more likely to take multiple days to give a return. Its count of 1-day investments trails the other ETF and both stocks by a decent margin.\\n\\nAnd consider me an OCD freak, but I just really like Celgene\'s distribution - it looks nice and smooth.\\n\\n## Summary and plans for the next post\\n\\nSo far I\'m really enjoying playing with this strategy - there\'s a lot of depth here to understand, though the preliminary results seem to indicate that it profits mostly from taking the other side of a volatile trade. I\'d be interested to run results later on data from January - It\'s been a particularly volatile start to the year so it would be neat to see whether this strategy would work then.\\n\\nFor the next post, I want to start playing with some of the parameters: How do the bias and expected close influence the process? The values have been fairly conservative so far, it will be interesting to see how the simulations respond afterward."},{"id":"2016/02/guaranteed-money-maker","metadata":{"permalink":"/2016/02/guaranteed-money-maker","source":"@site/blog/2016-02-03-guaranteed-money-maker/index.mdx","title":"Guaranteed money maker","description":"Developing an investment strategy based on the Martingale betting strategy","date":"2016-02-03T12:00:00.000Z","tags":[],"readingTime":7.695,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/guaranteed-money-maker","title":"Guaranteed money maker","date":"2016-02-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"},"nextItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"}},"content":"Developing an investment strategy based on the Martingale betting strategy\\n\\nIf you can see into the future, that is.\\n\\n\x3c!-- truncate --\x3e\\n\\nMy previous class in Stochastic Calculus covered a lot of interesting topics, and the important one for today is the [Gambler\'s Ruin][1] problem. If you\'re interested in some of the theory behind it, also make sure to check out [random walks][2]. The important bit is that we studied the [Martingale Betting Strategy][3], which describes for us a **guaranteed way** to <small>eventually</small> make money.\\n\\nThe strategy goes like this: You are going to toss a fair coin with a friend. If you guess heads or tails correctly, you get back double the money you bet. If you guess incorrectly, you lose money. How should you bet?\\n\\nThe correct answer is that you should double your bet each time you lose. Then when you finally win, you\'ll be guaranteed to make back everything you lost and then $1 extra! Consider the scenario:\\n\\n1. You bet $1, and guess incorrectly. You\'re 1 dollar in the hole.\\n2. You bet $2, and guess incorrectly. You\'re 3 dollars in the hole now.\\n3. You bet $4, and guess incorrectly. You\'re 7 dollars in the hole.\\n4. You bet $8, and guess correctly! You now get back those 8 dollars you bet, plus 8 extra for winning, for a **total profit of one dollar**!\\n\\nMathematically, we can prove that as long as you have unlimited money to bet, you are guaranteed to make money.\\n\\n## Applying the Martingale Strategy\\n\\nBut we\'re all realistic people, and once you start talking about \\"unlimited money\\" eyebrows should be raised. Even still, this is an interesting strategy to investigate, and I want to apply it to the stock market. As long as we can guarantee there\'s a single day in which the stock goes up, we should be able to make money right? The question is just how much we have to invest to guarantee this.\\n\\nNow it\'s time for the math. We\'ll use the following definitions:\\n\\n- $o_i$ = the share price at the opening of day $i$\\n- $c_i$ = the share price at the close of day $i$\\n- $d_i$ = the amount of money we want to invest at the beginning of day $i$\\n\\nWith those definitions in place, I\'d like to present the formula that is **guaranteed to make you money**. I call it *Bradlee\'s Investment Formula*:\\n\\n$c_n \\\\sum_{i=1}^n \\\\frac{d_i}{o_i} > \\\\sum_{i=1}^{n} d_i$\\n\\nIt might not look like much, but if you can manage to make it so that this formula holds true, you will be guaranteed to make money. The intuition behind the formula is this: The closing share price times the number of shares you have purchased ends up greater than the amount of money you invested.\\n\\nThat is, on day $n$, <small>if you know what the closing price will be</small> you can set up the amount of money you invest that day to **guarantee you make money**. I\'ll even teach you to figure out how much money that is! Take a look:\\n\\n$$\\n\\\\begin{align*}\\nc_n \\\\sum_{i=1}^{n-1} \\\\frac{d_i}{o_i} + \\\\frac{c_nd_n}{o_n} &> \\\\sum_{i=1}^{n-1}d_i + d_n\\\\\\\\\\n\\\\frac{c_nd_n}{o_n} - d_n &> \\\\sum_{i=1}^{n-1}(d_i - \\\\frac{c_nd_i}{o_i})\\\\\\\\\\nd_n (\\\\frac{c_n - o_n}{o_n}) &> \\\\sum_{i=1}^{n-1} d_i(1 - \\\\frac{c_n}{o_i})\\\\\\\\\\nd_n &> \\\\frac{o_n}{c_n - o_n} \\\\sum_{i=1}^{n-1} d_i(1 - \\\\frac{1}{o_i})\\n\\\\end{align*}\\n$$\\n\\nIf you invest exactly $d_n$ that day, you\'ll break even. But if you can make sure the money you invest is greater than that quantity on the right <small>(which requires that you have a crystal ball tell you the stock\'s closing price)</small> you are **guaranteed to make money!**\\n\\n## Interesting Implications\\n\\nOn a more serious note though, the formula above tells us a couple of interesting things:\\n\\n1. It\'s impossible to make money without the closing price at some point being greater than the opening price (or vice-versa if you are short selling) - there is no amount of money you can invest that will turn things in your favor.\\n2. Close prices of the past aren\'t important if you\'re concerned about the bottom line. While chart technicians use price history to make judgment calls, in the end, the closing price on anything other than the last day is irrelevant.\\n3. It\'s possible to make money as long as there is a single day where the closing price is greater than the opening price! You might have to invest a lot to do so, but it\'s possible.\\n4. You must make a prediction about where the stock will close at if you want to know how much to invest. That is, we can set up our investment for the day to make money if the stock goes up 1%, but if it only goes up .5% we\'ll still lose money.\\n5. It\'s possible the winning move is to scale back your position. Consider the scenario:\\n - You invest money and the stock closes down the day .5%\\n - You invest tomorrow expecting the stock to go up 1%\\n - The winning investment to break even (assuming a 1% increase) is to scale back the position, since the shares you purchased at the beginning would then be profitable\\n\\n## Running the simulation\\n\\nSo now that we\'ve defined our investment formula,we need to tweak a couple things in order to make an investment strategy we can actually work with. There are two issues we need to address:\\n\\n1. The formula only tells us how much to invest if we want to break even ($d_n$). If we actually want to turn a profit, we need to invest more than that, which we will refer to as the **bias**.\\n2. The formula assumes we know what the closing price will be on any given day. If we don\'t know this, we can still invest assuming the stock price will close at a level we choose. If the price doesn\'t meet this objective, we try again tomorrow! This predetermined closing price will be referred to as the **expectation**.\\n\\nNow that we\'ve defined our *bias* and *expectation*, we can actually build a strategy we can simulate. Much like the martingale strategy told you to bet twice your previous bet in order to make money, we\'ve designed a system that tells us how much to bet in order to make money as well.\\n\\nNow, let\'s get to the code!\\n\\n[1]: https://en.wikipedia.org/wiki/Gambler\'s_ruin\\n[2]: https://en.wikipedia.org/wiki/Random_walk\\n[3]: https://en.wikipedia.org/wiki/Martingale_%28betting_system%29\\n\\n\\n```julia\\nusing Quandl\\napi_key = \\"\\"\\ndaily_investment = function(current_open, current_close, purchase_history, open_history)\\n # We\'re not going to safeguard against divide by 0 - that\'s the user\'s responsibility\\n t1 = current_close / current_open - 1\\n t2 = sum(purchase_history - purchase_history*current_close ./ open_history)\\n return t2 / t1\\nend;\\n```\\n\\nAnd let\'s code a way to run simulations quickly:\\n\\n\\n```julia\\nis_profitable = function(current_price, purchase_history, open_history)\\n shares = sum(purchase_history ./ open_history)\\n return current_price*shares > sum(purchase_history)\\nend\\n\\nsimulate = function(name, start, init, expected, bias)\\n ticker_info = quandlget(name, from=start, api_key=api_key)\\n open_vals = ticker_info[\\"Open\\"].values\\n close_vals = ticker_info[\\"Close\\"].values\\n invested = [init]\\n \\n # The simulation stops once we\'ve made a profit\\n day = 1\\n profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||\\n is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])\\n while !profitable\\n expected_close = open_vals[day+1] * expected\\n todays_purchase = daily_investment(open_vals[day+1], expected_close, invested, open_vals[1:day])\\n invested = [invested; todays_purchase + bias]\\n # expected_profit = expected_close * sum(invested ./ open_vals[1:length(invested)]) - sum(invested)\\n day += 1\\n profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||\\n is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])\\n end\\n \\n shares = sum(invested ./ open_vals[1:length(invested)])\\n max_profit = max(close_vals[day], open_vals[day+1])\\n profit = shares * max_profit - sum(invested)\\n return (invested, profit)\\nend\\n\\nsim_summary = function(investments, profit)\\n leverages = [sum(investments[1:i]) for i=1:length(investments)]\\n max_leverage = maximum(leverages) / investments[1]\\n println(\\"Max leverage: $(max_leverage)\\")\\n println(\\"Days invested: $(length(investments))\\")\\n println(\\"Profit: $profit\\")\\nend;\\n```\\n\\nNow, let\'s get some data and run a simulation! Our first test:\\n\\n- We\'ll invest 100 dollars in LMT, and expect that the stock will close up 1% every day. We\'ll invest $d_n$ + 10 dollars every day that we haven\'t turned a profit, and end the simulation once we\'ve made a profit.\\n\\n\\n```julia\\ninvestments, profit = simulate(\\"YAHOO/LMT\\", Date(2015, 11, 29), 100, 1.01, 10)\\nsim_summary(investments, profit)\\n```\\n\\n```\\n Max leverage: 5.590373200042106\\n Days invested: 5\\n Profit: 0.6894803101560001\\n```\\n\\nThe result: We need to invest 5.6x our initial position over a period of 5 days to make approximately .69¢\\n\\n- Now let\'s try the same thing, but we\'ll assume the stock closes up 2% instead.\\n\\n\\n```julia\\ninvestments, profit = simulate(\\"YAHOO/LMT\\", Date(2015, 11, 29), 100, 1.02, 10)\\nsim_summary(investments, profit)\\n```\\n\\n```\\n Max leverage: 1.854949900247809\\n Days invested: 25\\n Profit: 0.08304813163696423\\n```\\n\\nIn this example, we only get up to a 1.85x leveraged position, but it takes 25 days to turn a profit of 8¢\\n\\n## Summary\\n\\nWe\'ve defined an investment strategy that can tell us how much to invest when we know what the closing position of a stock will be. We can tweak the strategy to actually make money, but plenty of work needs to be done so that we can optimize the money invested.\\n\\nIn the next post I\'m going to post more information about some backtests and strategy tests on this strategy (unless of course this experiment actually produces a significant profit potential, and then I\'m keeping it for myself).\\n\\n### Side note and disclaimer\\n\\nThe claims made in this presentation about being able to guarantee making money are intended as a joke and do not constitute investment advice of any sort."},{"id":"2016/01/cloudy-in-seattle","metadata":{"permalink":"/2016/01/cloudy-in-seattle","source":"@site/blog/2016-01-23-cloudy-in-seattle/index.mdx","title":"Cloudy in Seattle","description":"Building on prior analysis, is Seattle\'s reputation as a depressing city actually well-earned?","date":"2016-01-23T12:00:00.000Z","tags":[],"readingTime":3.965,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/cloudy-in-seattle","title":"Cloudy in Seattle","date":"2016-01-23T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730683607000,"prevItem":{"title":"Guaranteed money maker","permalink":"/2016/02/guaranteed-money-maker"},"nextItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"}},"content":"Building on prior analysis, is Seattle\'s reputation as a depressing city actually well-earned?\\n\\n\x3c!-- truncate --\x3e\\n\\n```python\\nimport pickle\\nimport pandas as pd\\nimport numpy as np\\nfrom bokeh.plotting import output_notebook, figure, show\\nfrom bokeh.palettes import RdBu4 as Palette\\nfrom datetime import datetime\\nimport warnings\\n\\noutput_notebook()\\n```\\n\\n```\\nBokehJS successfully loaded.\\n```\\n\\n## Examining other cities\\n\\nAfter taking some time to explore how the weather in North Carolina stacked up over the past years, I was interested in doing the same analysis for other cities. Growing up with family from Binghamton, NY I was always told it was very cloudy there. And Seattle has a nasty reputation for being very depressing and cloudy. All said, the cities I want to examine are:\\n- Binghamton, NY\\n- Cary, NC\\n- Seattle, WA\\n- New York City, NY\\n\\nI\'d be interested to try this analysis worldwide at some point - comparing London and Seattle might be an interesting analysis. For now though, we\'ll stick with trying out the US data.\\n\\nThere will be plenty of charts. I want to know: **How has average cloud cover and precipitation chance changed over the years for each city mentioned?** This will hopefully tell us whether Seattle has actually earned its reputation for being a depressing city.\\n\\n\\n```python\\ncity_forecasts = pickle.load(open(\'city_forecasts.p\', \'rb\'))\\nforecasts_df = pd.DataFrame.from_dict(city_forecasts)\\n```\\n\\n\\n```python\\ncities = [\'binghamton\', \'cary\', \'nyc\', \'seattle\']\\ncity_colors = {cities[i]: Palette[i] for i in range(0, 4)}\\n\\ndef safe_cover(frame):\\n if frame and \'cloudCover\' in frame:\\n return frame[\'cloudCover\']\\n else:\\n return np.NaN\\n\\ndef monthly_avg_cloudcover(city, year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n cloud_cover_vals = list(map(lambda x: safe_cover(forecasts_df[city][x][\'currently\']), dates))\\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\\n # Ignore an issue with nanmean having all NaN values. We\'ll discuss the data issues below.\\n with warnings.catch_warnings():\\n warnings.simplefilter(\'ignore\')\\n return np.nanmean(cloud_cover_vals), cloud_cover_samples\\n```\\n\\n\\n```python\\nyears = range(1990, 2016)\\ndef city_avg_cc(city, month):\\n return [monthly_avg_cloudcover(city, y, month) for y in years]\\n\\nmonths = [\\n (\'July\', 7),\\n (\'August\', 8),\\n (\'September\', 9),\\n (\'October\', 10),\\n (\'November\', 11)\\n]\\n\\nfor month, month_id in months:\\n month_averages = {city: city_avg_cc(city, month_id) for city in cities}\\n f = figure(title=\\"{} Average Cloud Cover\\".format(month),\\n x_axis_label=\'Year\',\\n y_axis_label=\'Cloud Cover Percentage\')\\n for city in cities:\\n f.line(years, [x[0] for x in month_averages[city]],\\n legend=city, color=city_colors[city])\\n show(f)\\n```\\n\\n![July average cloud cover chart](./1.png)\\n![August average cloud cover chart](./2.png)\\n![September average cloud cover chart](./3.png)\\n![October average cloud cover chart](./4.png)\\n![November average cloud cover chart](./5.png)\\n\\nWell, as it so happens it looks like there are some data issues. July\'s data is a bit sporadic, and 2013 seems to be missing from most months as well. I think really only two things can really be confirmed here:\\n- Seattle, specifically for the months of October and November, is in fact significantly more cloudy on average than are other cities\\n- All cities surveyed have seen average cloud cover decline over the months studied. There are data issues, but the trend seems clear.\\n\\nLet\'s now move from cloud cover data to looking at average rainfall chance.\\n\\n\\n```python\\ndef safe_precip(frame):\\n if frame and \'precipProbability\' in frame:\\n return frame[\'precipProbability\']\\n else:\\n return np.NaN\\n\\ndef monthly_avg_precip(city, year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n precip_vals = list(map(lambda x: safe_precip(forecasts_df[city][x][\'currently\']), dates))\\n precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))\\n # Ignore an issue with nanmean having all NaN values. We\'ll discuss the data issues below.\\n with warnings.catch_warnings():\\n warnings.simplefilter(\'ignore\')\\n return np.nanmean(precip_vals), precip_samples\\n\\ndef city_avg_precip(city, month):\\n return [monthly_avg_precip(city, y, month) for y in years]\\n\\nfor month, month_id in months:\\n month_averages = {city: city_avg_cc(city, month_id) for city in cities}\\n f = figure(title=\\"{} Average Precipitation Chance\\".format(month),\\n x_axis_label=\'Year\',\\n y_axis_label=\'Precipitation Chance Percentage\')\\n for city in cities:\\n f.line(years, [x[0] for x in month_averages[city]],\\n legend=city, color=city_colors[city])\\n show(f)\\n```\\n\\n![July average precipitation chance chart](./6.png)\\n![August average precipitation chance chart](./7.png)\\n![September average precipitation chance chart](./8.png)\\n![October average precipitation chance chart](./9.png)\\n![November average precipitation chance chart](./10.png)\\n\\nThe same data issue caveats apply here: 2013 seems to be missing some data, and July has some issues as well. However, this seems to confirm the trends we saw with cloud cover:\\n- Seattle, specifically for the months of August, October, and November has had a consistently higher chance of rain than other cities surveyed.\\n- Average precipitation chance, just like average cloud cover, has been trending down over time.\\n\\n## Conclusion\\n\\nI have to admit I was a bit surprised after doing this analysis. Seattle showed a higher average cloud cover and average precipitation chance than did the other cities surveyed. Maybe Seattle is actually an objectively more depressing city to live in.\\n\\nWell that\'s all for weather data at the moment. It\'s been a great experiment, but I think this is about as far as I\'ll be able to get with weather data without some domain knowledge. Talk again soon!"},{"id":"2016/01/complaining-about-the-weather","metadata":{"permalink":"/2016/01/complaining-about-the-weather","source":"@site/blog/2016-01-01-complaining-about-the-weather/index.mdx","title":"Complaining about the weather","description":"Figuring out whether people should be complaining about the recent weather in North Carolina.","date":"2016-01-01T12:00:00.000Z","tags":[],"readingTime":7.475,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/complaining-about-the-weather","title":"Complaining about the weather","date":"2016-01-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"},"nextItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"}},"content":"Figuring out whether people should be complaining about the recent weather in North Carolina.\\n\\n\x3c!-- truncate --\x3e\\n\\n```python\\nfrom bokeh.plotting import figure, output_notebook, show\\nfrom bokeh.palettes import PuBuGn9 as Palette\\nimport pandas as pd\\nimport numpy as np\\nfrom datetime import datetime\\nimport pickle\\n\\noutput_notebook()\\n```\\n\\n```\\nBokehJS successfully loaded.\\n```\\n\\nI\'m originally from North Carolina, and I\'ve been hearing a lot of people talking about how often it\'s been raining recently. They\'re excited for any day that has sun.\\n\\nSo I got a bit curious: Has North Carolina over the past few months actually had more cloudy and rainy days recently than in previous years? This shouldn\'t be a particularly challenging task, but I\'m interested to know if people\'s perceptions actually reflect reality.\\n\\nThe data we\'ll use comes from [forecast.io](https://forecast.io), since they can give us a cloud cover percentage. I\'ve gone ahead and retrieved the data to a pickle file, and included the [code that was used to generate it](#Generating-the-Forecast-file). First up: What was the average cloud cover in North Carolina during August - November, and how many days were cloudy? We\'re going to assume that a \\"cloudy\\" day is defined as any day in which the cloud cover is above 50%.\\n\\n```python\\ncity_forecasts = pickle.load(open(\'city_forecasts.p\', \'rb\'))\\nforecast_df = pd.DataFrame.from_dict(city_forecasts)\\n```\\n\\n```python\\ncary_forecast = forecast_df[\'cary\']\\nyears = range(1990, 2016)\\nmonths = range(7, 12)\\nmonths_str = [\'July\', \'August\', \'September\', \'October\', \'November\']\\n\\ndef safe_cover(frame):\\n if frame and \'cloudCover\' in frame:\\n return frame[\'cloudCover\']\\n else:\\n return np.NaN\\n\\ndef monthly_avg_cloudcover(year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x][\'currently\']), dates))\\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\\n return np.nanmean(cloud_cover_vals), cloud_cover_samples\\n\\n\\nmonthly_cover_vals = [[monthly_avg_cloudcover(y, m)[0] for y in years] for m in months]\\n\\nf = figure(title=\'Monthly Average Cloud Cover\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\')\\nfor x in range(0, len(months)):\\n f.line(years, monthly_cover_vals[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n```\\n\\n![Monthly average cloud cover chart](./1.png)\\n\\nAs we can see from the chart above, on the whole the monthly average cloud cover has been generally trending down over time. The average cloud cover is also lower than it was last year - it seems people are mostly just complaining. There are some data issues that start in 2012 that we need to be aware of - the cloud cover percentage doesn\'t exist for all days. Even so, the data that we have seems to reflect the wider trend, so we\'ll assume for now that the missing data doesn\'t skew our results.\\n\\nThere\'s one more metric we want to check though - how many cloudy days were there? This is probably a better gauge of sentiment than the average monthly cover.\\n\\n\\n```python\\ndef monthly_cloudy_days(year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x][\'currently\']), dates))\\n cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals)))\\n cloudy_days = [cover > .5 for cover in cloud_cover_vals]\\n return np.count_nonzero(cloudy_days), cloud_cover_samples\\n\\nmonthly_days_vals = [[monthly_cloudy_days(y, m)[0] for y in years] for m in months]\\nmonthly_cover_samples = [[monthly_cloudy_days(y, m)[1] for y in years] for m in months]\\n\\nf = figure(title=\'Monthly Cloudy Days\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\')\\nfor x in range(0, len(months)):\\n f.line(years, monthly_days_vals[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n\\nf = figure(title=\'Monthly Cloud Cover Samples\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\',\\n height=300)\\nfor x in range(0, len(months)):\\n f.line(years, monthly_cover_samples[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n```\\n\\n![Monthly cloudy days chart](./2.png)\\n\\n![Monthly cloud cover samples chart](./3.png)\\n\\nOn the whole, the number of cloudy days seems to reflect the trend with average cloud cover - it\'s actually becoming more sunny as time progresses. That said, we need to be careful in how we view this number - because there weren\'t as many samples in 2015 as previous years, the number of days can get thrown off. In context though, even if most days not recorded were in fact cloudy, the overall count for 2015 would still be lower than previous years.\\n\\n# Tracking Precipitation Chances\\n\\nIn addition to checking cloud cover, I wanted to check precipitation data as well - what is the average precipitation chance over a month, and how many days during a month is rain likely? The thinking is that days with a high-precipitation chance will also be days in which it is cloudy or depressing.\\n\\n\\n```python\\ndef safe_precip(frame):\\n if frame and \'precipProbability\' in frame:\\n return frame[\'precipProbability\']\\n else:\\n return np.NaN\\n\\ndef monthly_avg_precip(year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n precip_vals = list(map(lambda x: safe_precip(cary_forecast[x][\'currently\']), dates))\\n precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals)))\\n return np.nanmean(precip_vals), precip_samples\\n\\nmonthly_avg_precip_vals = [[monthly_avg_precip(y, m)[0] for y in years] for m in months]\\n\\nf = figure(title=\'Monthly Average Precipitation Chance\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\')\\nfor x in range(0, len(months)):\\n f.line(years, monthly_avg_precip_vals[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n```\\n\\n![Monthly average precipitation chance chart](./4.png)\\n\\nAs we can see from the chart, the average chance of precipitation over a month more or less stays within a band of 0 - .1 for all months over all years. This is further evidence that the past few months are no more cloudy or rainy than previous years. Like the cloud cover though, we still want to get a count of all the rainy days, in addition to the average chance. We\'ll define a \\"rainy day\\" as any day in which the chance of rain is greater than 25%.\\n\\n\\n```python\\ndef monthly_rainy_days(year, month):\\n dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12),\\n end=datetime(year, month + 1, 1, 12),\\n freq=\'D\', closed=\'left\')\\n precip_prob_vals = list(map(lambda x: safe_precip(cary_forecast[x][\'currently\']), dates))\\n precip_prob_samples = len(list(filter(lambda x: x is not np.NaN, precip_prob_vals)))\\n precip_days = [prob > .25 for prob in precip_prob_vals]\\n return np.count_nonzero(precip_days), precip_prob_samples\\n\\nmonthly_precip_days_vals = [[monthly_rainy_days(y, m)[0] for y in years] for m in months]\\nmonthly_precip_samples = [[monthly_rainy_days(y, m)[1] for y in years] for m in months]\\n\\nf = figure(title=\'Monthly Rainy Days\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\')\\nfor x in range(0, len(months)):\\n f.line(years, monthly_precip_days_vals[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n\\nf = figure(title=\'Monthly Rainy Days Samples\',\\n x_range=(1990, 2015),\\n x_axis_label=\'Year\',\\n height=300)\\nfor x in range(0, len(months)):\\n f.line(years, monthly_precip_samples[x], legend=months_str[x], color=Palette[x])\\nshow(f)\\n```\\n\\n![Monthly rainy days chart](./5.png)\\n\\n![Monthly rainy days samples chart](./6.png)\\n\\nAfter trying to find the number of days that are rainy, we can see that November hit its max value for rainy days in 2015. However, that value is 6, as compared to a previous maximum of 5. While it is a new record, the value isn\'t actually all that different. And for other months, the values are mostly in-line with the averages.\\n\\n# Summary and Conclusions\\n\\nAfter having looked at forecast data for Cary, it appears that the months of July - November this year in terms of weather were at worst on par with prior years, if not slightly more sunny. This seems to be a case of confirmation bias: someone complains about a string of cloudy or rainy days, and suddenly you start noticing them more.\\n\\nWhile this analysis doesn\'t take into account other areas of North Carolina, my initial guess would be to assume that other areas also will show similar results: nothing interesting is happening. Maybe that will be for another blog post later!\\n\\nComing soon: I\'ll compare rain/cloud conditions in North Carolina to some other places in the U.S.!\\n\\n# Generating the Forecast file\\n\\nThe following code was generates the file that was used throughout the blog post. Please note that I\'m retrieving data for other cities to use in a future blog post, only Cary data was used for this post.\\n\\n```python\\nimport pandas as pd\\nfrom functools import reduce\\nimport requests\\nfrom datetime import datetime\\n\\n# Coordinate data from http://itouchmap.com/latlong.html\\ncary_loc = (35.79154,-78.781117)\\nnyc_loc = (40.78306,-73.971249)\\nseattle_loc = (47.60621,-122.332071)\\nbinghamton_loc = (42.098687,-75.917974)\\ncities = {\\n \'cary\': cary_loc,\\n \'nyc\': nyc_loc,\\n \'seattle\': seattle_loc,\\n \'binghamton\': binghamton_loc\\n}\\n\\napikey = \'\' # My super-secret API Key\\n\\ndef get_forecast(lat, long, date=None):\\n forecast_base = \\"https://api.forecast.io/forecast/\\"\\n if date is None:\\n url = forecast_base + apikey + \'/{},{}\'.format(lat, long)\\n else:\\n epoch = int(date.timestamp())\\n url = forecast_base + apikey + \'/{},{},{}\'.format(lat, long, epoch)\\n \\n return requests.get(url).json()\\n \\nyears = range(1990,2016)\\n# For datetimes, the 12 is for getting the weather at noon.\\n# We\'re doing this over midnight because we\'re more concerned\\n# with what people see, and people don\'t typically see the weather\\n# at midnight.\\ndt_indices = [pd.date_range(start=datetime(year, 7, 1, 12),\\n end=datetime(year, 11, 30, 12))\\n for year in years]\\ndt_merge = reduce(lambda x, y: x.union(y), dt_indices)\\n\\n# Because we have to pay a little bit to use the API, we use for loops here\\n# instead of a comprehension - if something breaks, we want to preserve the\\n# data already retrieved\\ncity_forecasts = {}\\nfor city, loc in cities.items():\\n print(\\"Retrieving data for {} starting at {}\\".format(city,\\n datetime.now().strftime(\\"%I:%M:%S %p\\")))\\n for dt in dt_merge:\\n try:\\n city_forecasts[(city, dt)] = get_forecast(*loc, dt)\\n except Exception as e:\\n print(e)\\n city_forecasts[(city, dt)] = None\\nprint(\\"End forecast retrieval: {}\\".format(datetime.now().strftime(\\"%I:%M:%S %p\\")))\\n\\nimport pickle\\npickle.dump(city_forecasts, open(\'city_forecasts.p\', \'wb\'))\\n\\n### Output:\\n# Retrieving data for binghamton starting at 05:13:42 PM\\n# Retrieving data for seattle starting at 05:30:51 PM\\n# Retrieving data for nyc starting at 05:48:30 PM\\n# Retrieving data for cary starting at 06:08:32 PM\\n# End forecast retrieval: 06:25:21 PM\\n```"},{"id":"2015/12/testing-cramer","metadata":{"permalink":"/2015/12/testing-cramer","source":"@site/blog/2015-12-26-testing-cramer/index.mdx","title":"Testing Cramer","description":"Pursuant to attending a graduate school studying Financial Engineering, I\'ve been a fan of the Mad Money TV show featuring the bombastic Jim Cramer. One of the things that he\'s said is that you shouldn\'t use the futures to predict where the stock market is going to go. But he says it often enough, I\'ve begun to wonder - who is he trying to convince?","date":"2015-12-26T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/12/testing-cramer","title":"Testing Cramer","date":"2015-12-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"},"nextItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}},"content":"Pursuant to attending a graduate school studying Financial Engineering, I\'ve been a fan of the [Mad Money][1] TV show featuring the bombastic Jim Cramer. One of the things that he\'s said is that you shouldn\'t use the futures to predict where the stock market is going to go. But he says it often enough, I\'ve begun to wonder - who is he trying to convince?\\n\\n\x3c!-- truncate --\x3e\\n\\nIt makes sense that because futures on things like the S&P 500 are traded continuously, they would price in market information before the stock market opens. So is Cramer right to be convinced that strategies based on the futures are a poor idea? I wanted to test it out.\\n\\nThe first question is where to get the future\'s data. I\'ve been part of [Seeking Alpha][2] for a bit, and they publish the [Wall Street Breakfast][3] newsletter which contains daily future\'s returns as of 6:20 AM EST. I\'d be interested in using that data to see if we can actually make some money.\\n\\nFirst though, let\'s get the data:\\n\\n## Downloading Futures data from Seeking Alpha\\n\\nWe\'re going to define two HTML parsing classes - one to get the article URL\'s from a page, and one to get the actual data from each article.\\n\\n[1]: http://www.cnbc.com/mad-money/\\n[2]: http://seekingalpha.com/\\n[3]: http://seekingalpha.com/author/wall-street-breakfast?s=wall-street-breakfast\\n\\n\\n```python\\nclass ArticleListParser(HTMLParser):\\n \\"\\"\\"Given a web page with articles on it, parse out the article links\\"\\"\\"\\n \\n articles = []\\n \\n def handle_starttag(self, tag, attrs):\\n #if tag == \'div\' and (\\"id\\", \\"author_articles_wrapper\\") in attrs:\\n # self.fetch_links = True\\n if tag == \'a\' and (\'class\', \'dashboard_article_link\') in attrs:\\n href = list(filter(lambda x: x[0] == \'href\', attrs))[0][1]\\n self.articles.append(href)\\n \\nbase_url = \\"http://seekingalpha.com/author/wall-street-breakfast/articles\\"\\narticle_page_urls = [base_url] + [base_url + \'/{}\'.format(i) for i in range(2, 20)]\\n\\nglobal_articles = []\\nfor page in article_page_urls:\\n # We need to switch the user agent, as SA blocks the standard requests agent\\n articles_html = requests.get(page,\\n headers={\\"User-Agent\\": \\"Wget/1.13.4\\"})\\n parser = ArticleListParser()\\n parser.feed(articles_html.text)\\n global_articles += (parser.articles)\\n```\\n\\n\\n```python\\nclass ArticleReturnParser(HTMLParser):\\n \\"Given an article, parse out the futures returns in it\\"\\n \\n record_font_tags = False\\n in_font_tag = False\\n counter = 0\\n # data = {} # See __init__\\n \\n def __init__(self, *args, **kwargs):\\n super().__init__(*args, **kwargs)\\n self.data = {}\\n \\n def handle_starttag(self, tag, attrs):\\n if tag == \'span\' and (\'itemprop\', \'datePublished\') in attrs:\\n date_string = list(filter(lambda x: x[0] == \'content\', attrs))[0][1]\\n date = dtparser.parse(date_string)\\n self.data[\'date\'] = date\\n \\n self.in_font_tag = tag == \'font\'\\n \\n def safe_float(self, string):\\n try:\\n return float(string[:-1]) / 100\\n except ValueError:\\n return np.NaN\\n \\n def handle_data(self, content):\\n if not self.record_font_tags and \\"Futures at 6\\" in content:\\n self.record_font_tags = True\\n \\n if self.record_font_tags and self.in_font_tag:\\n if self.counter == 0:\\n self.data[\'DOW\'] = self.safe_float(content)\\n elif self.counter == 1:\\n self.data[\'S&P\'] = self.safe_float(content)\\n elif self.counter == 2:\\n self.data[\'NASDAQ\'] = self.safe_float(content)\\n elif self.counter == 3:\\n self.data[\'Crude\'] = self.safe_float(content)\\n elif self.counter == 4:\\n self.data[\'Gold\'] = self.safe_float(content)\\n \\n self.counter += 1\\n \\n def handle_endtag(self, tag):\\n self.in_font_tag = False\\n\\ndef retrieve_data(url):\\n sa = \\"http://seekingalpha.com\\"\\n article_html = requests.get(sa + url,\\n headers={\\"User-Agent\\": \\"Wget/1.13.4\\"})\\n parser = ArticleReturnParser()\\n parser.feed(article_html.text)\\n parser.data.update({\\"url\\": url})\\n parser.data.update({\\"text\\": article_html.text})\\n return parser.data\\n\\n# This copy **MUST** be in place. I\'m not sure why,\\n# as you\'d think that the data being returned would already\\n# represent a different memory location. Even so, it blows up\\n# if you don\'t do this.\\narticle_list = list(set(global_articles))\\narticle_data = [copy(retrieve_data(url)) for url in article_list]\\n# If there\'s an issue downloading the article, drop it.\\narticle_df = pd.DataFrame.from_dict(article_data).dropna()\\n```\\n\\n## Fetching the Returns data\\n\\nNow that we have the futures data, we\'re going to compare across 4 different indices - the S&P 500 index, Dow Jones Industrial, Russell 2000, and NASDAQ 100. Let\'s get the data off of Quandl to make things easier!\\n\\n\\n```python\\n# article_df is sorted by date, so we get the first row.\\nstart_date = article_df.sort_values(by=\'date\').iloc[0][\'date\'] - relativedelta(days=1)\\nSPY = Quandl.get(\\"GOOG/NYSE_SPY\\", trim_start=start_date)\\nDJIA = Quandl.get(\\"GOOG/AMS_DIA\\", trim_start=start_date)\\nRUSS = Quandl.get(\\"GOOG/AMEX_IWM\\", trim_start=start_date)\\nNASDAQ = Quandl.get(\\"GOOG/EPA_QQQ\\", trim_start=start_date)\\n```\\n\\n## Running the Comparison\\n\\nThere are two types of tests I want to determine: How accurate each futures category is at predicting the index\'s opening change over the close before, and predicting the index\'s daily return.\\n\\nLet\'s first calculate how good each future is at predicting the opening return over the previous day. I expect that the futures will be more than 50% accurate, since the information is recorded 3 hours before the markets open.\\n\\n\\n```python\\ndef calculate_opening_ret(frame):\\n # I\'m not a huge fan of the appending for loop,\\n # but it\'s a bit verbose for a comprehension\\n data = {}\\n for i in range(1, len(frame)):\\n date = frame.iloc[i].name\\n prior_close = frame.iloc[i-1][\'Close\']\\n open_val = frame.iloc[i][\'Open\']\\n data[date] = (open_val - prior_close) / prior_close\\n \\n return data\\n\\nSPY_open_ret = calculate_opening_ret(SPY)\\nDJIA_open_ret = calculate_opening_ret(DJIA)\\nRUSS_open_ret = calculate_opening_ret(RUSS)\\nNASDAQ_open_ret = calculate_opening_ret(NASDAQ)\\n\\ndef signs_match(list_1, list_2):\\n # This is a surprisingly difficult task - we have to match\\n # up the dates in order to check if opening returns actually match\\n index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}\\n \\n matches = []\\n for row in list_1.iterrows():\\n row_dt = row[1][1]\\n row_value = row[1][0]\\n index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)\\n if index_dt in list_2:\\n index_value = list_2[index_dt]\\n if (row_value > 0 and index_value > 0) or \\\\\\n (row_value < 0 and index_value < 0) or \\\\\\n (row_value == 0 and index_value == 0):\\n matches += [1]\\n else:\\n matches += [0]\\n #print(\\"{}\\".format(list_2[index_dt]))\\n return matches\\n \\n \\nprediction_dict = {}\\nmatches_dict = {}\\ncount_dict = {}\\nindex_dict = {\\"SPY\\": SPY_open_ret, \\"DJIA\\": DJIA_open_ret, \\"RUSS\\": RUSS_open_ret, \\"NASDAQ\\": NASDAQ_open_ret}\\nindices = [\\"SPY\\", \\"DJIA\\", \\"RUSS\\", \\"NASDAQ\\"]\\nfutures = [\\"Crude\\", \\"Gold\\", \\"DOW\\", \\"NASDAQ\\", \\"S&P\\"]\\nfor index in indices:\\n matches_dict[index] = {future: signs_match(article_df[[future, \'date\']],\\n index_dict[index]) for future in futures}\\n count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}\\n prediction_dict[index] = {future: np.mean(matches_dict[index][future])\\n for future in futures}\\nprint(\\"Articles Checked: \\")\\nprint(pd.DataFrame.from_dict(count_dict))\\nprint()\\nprint(\\"Prediction Accuracy:\\")\\nprint(pd.DataFrame.from_dict(prediction_dict))\\n```\\n\\n```\\n Articles Checked: \\n DJIA NASDAQ RUSS SPY\\n Crude 268 268 271 271\\n DOW 268 268 271 271\\n Gold 268 268 271 271\\n NASDAQ 268 268 271 271\\n S&P 268 268 271 271\\n \\n Prediction Accuracy:\\n DJIA NASDAQ RUSS SPY\\n Crude 0.544776 0.522388 0.601476 0.590406\\n DOW 0.611940 0.604478 0.804428 0.841328\\n Gold 0.462687 0.455224 0.464945 0.476015\\n NASDAQ 0.615672 0.608209 0.797048 0.830258\\n S&P 0.604478 0.597015 0.811808 0.848708\\n```\\n\\nThis data is very interesting. Some insights:\\n\\n- Both DOW and NASDAQ futures are pretty bad at predicting their actual market openings\\n- NASDAQ and Dow are fairly unpredictable; Russell 2000 and S&P are very predictable\\n- Gold is a poor predictor in general - intuitively Gold should move inverse to the market, but it appears to be about as accurate as a coin flip.\\n\\nAll said though it appears that futures data is important for determining market direction for both the S&P 500 and Russell 2000. Cramer is half-right: futures data isn\'t very helpful for the Dow and NASDAQ indices, but is great for the S&P and Russell indices.\\n\\n## The next step - Predicting the close\\n\\nGiven the code we currently have, I\'d like to predict the close of the market as well. We can re-use most of the code, so let\'s see what happens:\\n\\n\\n```python\\ndef calculate_closing_ret(frame):\\n # I\'m not a huge fan of the appending for loop,\\n # but it\'s a bit verbose for a comprehension\\n data = {}\\n for i in range(0, len(frame)):\\n date = frame.iloc[i].name\\n open_val = frame.iloc[i][\'Open\']\\n close_val = frame.iloc[i][\'Close\']\\n data[date] = (close_val - open_val) / open_val\\n \\n return data\\n\\nSPY_close_ret = calculate_closing_ret(SPY)\\nDJIA_close_ret = calculate_closing_ret(DJIA)\\nRUSS_close_ret = calculate_closing_ret(RUSS)\\nNASDAQ_close_ret = calculate_closing_ret(NASDAQ)\\n\\ndef signs_match(list_1, list_2):\\n # This is a surprisingly difficult task - we have to match\\n # up the dates in order to check if opening returns actually match\\n index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}\\n \\n matches = []\\n for row in list_1.iterrows():\\n row_dt = row[1][1]\\n row_value = row[1][0]\\n index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)\\n if index_dt in list_2:\\n index_value = list_2[index_dt]\\n if (row_value > 0 and index_value > 0) or \\\\\\n (row_value < 0 and index_value < 0) or \\\\\\n (row_value == 0 and index_value == 0):\\n matches += [1]\\n else:\\n matches += [0]\\n #print(\\"{}\\".format(list_2[index_dt]))\\n return matches\\n \\n \\nmatches_dict = {}\\ncount_dict = {}\\nprediction_dict = {}\\nindex_dict = {\\"SPY\\": SPY_close_ret, \\"DJIA\\": DJIA_close_ret,\\n \\"RUSS\\": RUSS_close_ret, \\"NASDAQ\\": NASDAQ_close_ret}\\nindices = [\\"SPY\\", \\"DJIA\\", \\"RUSS\\", \\"NASDAQ\\"]\\nfutures = [\\"Crude\\", \\"Gold\\", \\"DOW\\", \\"NASDAQ\\", \\"S&P\\"]\\nfor index in indices:\\n matches_dict[index] = {future: signs_match(article_df[[future, \'date\']],\\n index_dict[index]) for future in futures}\\n count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}\\n prediction_dict[index] = {future: np.mean(matches_dict[index][future])\\n for future in futures}\\n \\nprint(\\"Articles Checked:\\")\\nprint(pd.DataFrame.from_dict(count_dict))\\nprint()\\nprint(\\"Prediction Accuracy:\\")\\nprint(pd.DataFrame.from_dict(prediction_dict))\\n```\\n\\n```\\n Articles Checked:\\n DJIA NASDAQ RUSS SPY\\n Crude 268 268 271 271\\n DOW 268 268 271 271\\n Gold 268 268 271 271\\n NASDAQ 268 268 271 271\\n S&P 268 268 271 271\\n \\n Prediction Accuracy:\\n DJIA NASDAQ RUSS SPY\\n Crude 0.533582 0.529851 0.501845 0.542435\\n DOW 0.589552 0.608209 0.535055 0.535055\\n Gold 0.455224 0.451493 0.483395 0.512915\\n NASDAQ 0.582090 0.626866 0.531365 0.538745\\n S&P 0.585821 0.608209 0.535055 0.535055\\n```\\n\\nWell, it appears that the futures data is terrible at predicting market close. NASDAQ predicting NASDAQ is the most interesting data point, but 63% accuracy isn\'t accurate enough to make money consistently.\\n\\n## Final sentiments\\n\\nThe data bears out very close to what I expected would happen:\\n\\n- Futures data is more accurate than a coin flip for predicting openings, which makes sense since it is recorded only 3 hours before the actual opening\\n- Futures data is about as acccurate as a coin flip for predicting closings, which means there is no money to be made in trying to predict the market direction for the day given the futures data.\\n\\nIn summary:\\n\\n- Cramer is half right: Futures data is not good for predicting the market open of the Dow and NASDAQ indices. Contrary to Cramer though, it is very good for predicting the S&P and Russell indices - we can achieve an accuracy slightly over 80% for each. \\n- Making money in the market is hard. We can\'t just go to the futures and treat them as an oracle for where the market will close.\\n\\nI hope you\'ve enjoyed this, I quite enjoyed taking a deep dive in the analytics this way. I\'ll be posting more soon!"},{"id":"2015/11/autocallable","metadata":{"permalink":"/2015/11/autocallable","source":"@site/blog/2015-11-27-autocallable/index.mdx","title":"Autocallable Bonds","description":"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.","date":"2015-11-27T12:00:00.000Z","tags":[],"readingTime":11.085,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/autocallable","title":"Autocallable Bonds","date":"2015-11-27T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"},"nextItem":{"title":"Welcome, and an algorithm","permalink":"/2015/11/welcome"}},"content":"For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.\\n\\n\x3c!-- truncate --\x3e\\n\\nMy only non-core class this semester has been in Structure Products. We\'ve been surveying a wide variety of products, and the final project was to pick one to report on.\\nBecause these are all very similar, we decided to demonstrate all 3 products at once.\\n\\nWhat follows below is a notebook demonstrating the usage of [Julia](http://julialang.com) for Monte-Carlo simulation of some exotic products.\\n\\n---\\n\\n```julia\\nusing Gadfly\\n```\\n\\n# Athena/Phoenix Simulation\\n\\n## Underlying simulation\\n\\nIn order to price the autocallable bonds, we need to simulate the underlying assets. Let\'s go ahead and set up the simulation first, as this lays the foundation for what we\'re trying to do. We\'re going to use [JNJ](http://finance.yahoo.com/q?s=jnj) as the basis for our simulation. This implies the following parameters:\\n\\n- $S_0$ = \\\\$102.2 (as of time of writing)\\n- $q$ = 2.84%\\n- $r$ = [.49, .9, 1.21, 1.45, 1.69] (term structure as of time of writing, linear interpolation)\\n- $\\\\mu$ = $r - q$ (note that this implies a negative drift because of current low rates)\\n- $\\\\sigma$ = $\\\\sigma_{imp}$ = 15.62% (from VIX implied volatility)\\n\\nWe additionally define some parameters for simulation:\\n\\n- `T`: The number of years to simulate\\n- `m`: The number of paths to simulate\\n- `n`: The number of steps to simulate in a year\\n\\n\\n```julia\\nS0 = 102.2\\nnominal = 100\\nq = 2.84 / 100\\n\u03C3 = 15.37 / 100\\nterm = [0, .49, .9, 1.21, 1.45, 1.69] / 100 + 1\\n\\n###\\n# Potential: Based on PEP\\n# S0 = 100.6\\n# \u03C3 = 14.86\\n# q = 2.7\\n###\\n\\n# Simulation parameters\\nT = 5 # Using years as the unit of time\\nn = 250 # simulations per year\\nm = 100000 # paths\\nnum_simulations = 5; # simulation rounds per price\\n```\\n\\n### Defining the simulation\\nTo make things simpler, we simulate a single year at a time. This allows us to easily add in a dividend policy without too much difficulty, and update the simulation every year to match the term structure. The underlying uses GBM for simulation between years.\\n\\n\\n```julia\\nsimulate_gbm = function(S0, \u03BC, \u03C3, T, n)\\n # Set the initial state\\n m = length(S0)\\n t = T / n\\n motion = zeros(m, n)\\n motion[:,1] = S0\\n \\n # Build out all states\\n for i=1:(n-1)\\n motion[:,i+1] = motion[:,i] .* exp((\u03BC - \u03C3^2/2)*t) .* exp(sqrt(t) * \u03C3 .* randn(m))\\n end\\n \\n return motion\\nend\\n\\nfunction display_motion(motion, T)\\n # Given a matrix of paths, display the motion\\n n = length(motion[1,:])\\n m = length(motion[:,1])\\n x = repmat(1:n, m)\\n \\n # Calculate the ticks we\'re going to use. We\'d like to\\n # have an xtick every month, so calculate where those\\n # ticks will actually be at.\\n if (T > 3)\\n num_ticks = T\\n xlabel = \\"Years\\"\\n else\\n num_ticks = T * 12\\n xlabel = \\"Months\\"\\n end\\n tick_width = n / num_ticks\\n x_ticks = []\\n for i=1:round(num_ticks)\\n x_ticks = vcat(x_ticks, i*tick_width)\\n end\\n \\n # Use one color for each path. I\'m not sure if there\'s\\n # a better way to do this without going through DataFrames\\n colors = []\\n for i = 1:m\\n colors = vcat(colors, ones(n)*i)\\n end\\n \\n plot(x=x, y=motion\', color=colors, Geom.line,\\n Guide.xticks(ticks=x_ticks, label=false),\\n Guide.xlabel(xlabel),\\n Guide.ylabel(\\"Value\\"))\\nend;\\n```\\n\\n### Example simulation\\n\\nLet\'s go ahead and run a sample simulation to see what the functions got us!\\n\\n\\n```julia\\ninitial = ones(5) * S0\\n# Using \u03BC=0, T=.25 for now, we\'ll use the proper values later\\nmotion = simulate_gbm(initial, 0, \u03C3, .25, 200) \\n\\ndisplay_motion(motion, .25)\\n```\\n\\n![](./_notebook_files/_notebook_6_0.svg)\\n\\n### Computing the term structure\\n\\nNow that we\'ve got the basic motion set up, let\'s start making things a bit more sophisticated for the model. We\'re going to assume that the drift of the stock is the difference between the implied forward rate and the quarterly dividend rate.\\n\\nWe\'re given the yearly term structure, and need to calculate the quarterly forward rate to match this structure. The term structure is assumed to follow:\\n\\n$d(0, t) = d(0,t-1)\\\\cdot f_{i-1, i}$\\n\\nWhere $f_{i-1, i}$ is the quarterly forward rate.\\n\\n```julia\\nforward_term = function(yearly_term)\\n # It is assumed that we have a yearly term structure passed in, and starts at year 0\\n # This implies a nominal rate above 0 for the first year!\\n years = length(term)-1 # because we start at 0\\n structure = [(term[i+1] / term[i]) for i=1:years]\\nend;\\n```\\n\\n### Illustrating the term structure\\n\\nNow that we\'ve got our term structure, let\'s validate that we\'re getting the correct results! If we\'ve done this correctly, then:\\n\\n```\\nterm[2] == term[1] * structure[1]\\n```\\n\\n```julia\\n# Example term structure taken from:\\n# http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield\\n# Linear interpolation used years in-between periods, assuming real-dollar\\n# interest rates\\nforward_yield = forward_term(term)\\ncalculated_term2 = term[1] * forward_yield[1]\\n\\nprintln(\\"Actual term[2]: $(term[2]); Calculated term[2]: $(calculated_term2)\\")\\n```\\n\\n```\\n Actual term[2]: 1.0049; Calculated term[2]: 1.0049\\n```\\n\\n### The full underlying simulation\\n\\nNow that we have the term structure set up, we can actually start doing some real simulation! Let\'s construct some paths through the full 5-year time frame. In order to do this, we will simulate 1 year at a time, and use the forward rates at those times to compute the drift. Thus, there will be 5 total simulations batched together.\\n\\n\\n```julia\\nfull_motion = ones(5) * S0\\nfull_term = vcat(term[1], forward_yield)\\nfor i=1:T\\n \u03BC = (full_term[i] - 1 - q)\\n year_motion = simulate_gbm(full_motion[:,end], \u03BC, \u03C3, 1, n)\\n full_motion = hcat(full_motion, year_motion)\\nend\\n\\ndisplay_motion(full_motion, T)\\n```\\n\\n![](./_notebook_files/_notebook_12_0.svg)\\n\\n### Final simulation\\n\\nWe\'re now going to actually build out the full motion that we\'ll use for computing the pricing of our autocallable products. It will be largely the same, but we will use far more sample paths for the simulation.\\n\\n\\n```julia\\nfull_simulation = function(S0, T, n, m, term)\\n forward = vcat(term[1], forward_term(term))\\n\\n # And an S0 to kick things off.\\n final_motion = ones(m) * S0\\n for i=1:T\\n \u03BC = (forward[i] - 1 - q)\\n year_motion = simulate_gbm(final_motion[:,end], \u03BC, \u03C3, 1, n)\\n final_motion = hcat(final_motion, year_motion)\\n end\\n return final_motion\\nend\\n\\ntic()\\nfull_simulation(S0, T, n, m, term)\\ntime = toq()\\n@printf(\\"Time to run simulation: %.2fs\\", time)\\n```\\n\\n```\\n Time to run simulation: 5.34s\\n```\\n\\n## Athena Simulation\\n\\nNow that we\'ve defined our underlying simulation, let\'s actually try and price an Athena note. Athena has the following characteristics:\\n\\n- Automatically called if the underlying is above the **call barrier** at observation\\n- Accelerated coupon paid if the underlying is above the **call barrier** at observation\\n - The coupon paid is $c \\\\cdot i$ with $i$ as the current year, and $c$ the coupon rate\\n- Principle protection up until a **protection barrier** at observation; All principle at risk if this barrier not met\\n- Observed yearly\\n\\n```julia\\ncall_barrier = S0\\nstrike = S0\\nprotection_barrier = S0 * .6\\ncoupon = nominal * .07\\n\\nprice_athena = function(initial_price, year_prices, call_barrier,\\n protection_barrier, coupon, forward_structure)\\n\\n total_coupons = 0\\n \\n t = length(year_prices)\\n\\n for i=1:t\\n price = year_prices[i]\\n if price \u2265 call_barrier\\n return (nominal + coupon*i) * exp((prod(forward_structure[i:end])-1)*(t-i))\\n end\\n end\\n\\n # We\'ve reached maturity, time to check capital protection\\n if year_prices[end] > protection_barrier\\n return nominal\\n else\\n put = (strike - year_prices[end]) / strike\\n return nominal*(1-put)\\n end\\nend\\n\\nforward_structure = forward_term(term)\\nprice_function = (year_prices) -> price_athena(S0, year_prices,\\n call_barrier, protection_barrier, coupon, forward_structure)\\n\\nathena = function()\\n year_indexes = [n*i for i=1:T]\\n motion = full_simulation(S0, T, n, m, term)\\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\\n return mean(payoffs)\\nend\\n\\nmean_payoffs = zeros(num_simulations)\\nfor i=1:num_simulations\\n tic()\\n mean_payoffs[i] = athena()\\n time = toq()\\n @printf(\\"Mean of simulation %i: \\\\$%.4f; Simulation time: %.2fs\\\\n\\", i, mean_payoffs[i], time)\\nend\\n\\nfinal_mean = mean(mean_payoffs)\\nprintln(\\"Mean over $num_simulations simulations: $(mean(mean_payoffs))\\")\\npv = final_mean * (exp(-(prod(forward_structure)-1)*T))\\n@printf(\\"Present value of Athena note: \\\\$%.2f, notional: \\\\$%.2f\\", pv, nominal)\\n```\\n\\n```\\n Mean of simulation 1: $103.2805; Simulation time: 5.59s\\n Mean of simulation 2: $103.3796; Simulation time: 5.05s\\n Mean of simulation 3: $103.4752; Simulation time: 5.18s\\n Mean of simulation 4: $103.4099; Simulation time: 5.37s\\n Mean of simulation 5: $103.3260; Simulation time: 5.32s\\n Mean over 5 simulations: 103.37421610015554\\n Present value of Athena note: $95.00, notional: $100.00\\n```\\n\\n## Phoenix without Memory Simulation\\n\\nLet\'s move into pricing a Phoenix without memory. It\'s very similar to the Athena production, with the exception that we introduce a coupon barrier so coupons are paid even when the underlying is below the initial price.\\n\\nThe Phoenix product has the following characteristics (example [here](https://www.rbccm.com/usstructurednotes/file-780079.pdf)):\\n\\n- Automatically called if the underlying is above the **call barrier** at observation\\n- Coupon paid if the underlying is above a **coupon barrier** at observation\\n- Principle protection up until a **protection barrier** at observation; All principle at risk if this barrier not met\\n- Observed yearly\\n\\nSome example paths (all assume that a call barrier of the current price, and coupon barrier some level below that):\\n\\n- At the end of year 1, the stock is above the call barrier; the note is called and you receive the value of the stock plus the coupon being paid.\\n- At the end of year 1, the stock is above the coupon barrier, but not the call barrier; you receive the coupon. At the end of year 2, the stock is below the coupon barrier; you receive nothing. At the end of year 3, the stock is above the call barrier; the note is called and you receive the value of the stock plus a coupon for year 3.\\n\\nWe\'re going to re-use the same simulation, with the following parameters:\\n\\n- Call barrier: 100%\\n- Coupon barrier: 70%\\n- Coupon: 6%\\n- Capital protection until 70% (at maturity)\\n\\n\\n```julia\\ncall_barrier = S0\\ncoupon_barrier = S0 * .8\\nprotection_barrier = S0 * .6\\ncoupon = nominal * .06\\n\\nprice_phoenix_no_memory = function(initial_price, year_prices, call_barrier, coupon_barrier,\\n protection_barrier, coupon, forward_structure)\\n\\n total_coupons = 0\\n t = length(year_prices)\\n\\n for i=1:t\\n price = year_prices[i]\\n if price \u2265 call_barrier\\n return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))\\n elseif price \u2265 coupon_barrier\\n total_coupons = total_coupons * exp(forward_structure[i]-1) + coupon\\n else\\n total_coupons *= exp(forward_structure[i]-1)\\n end\\n end\\n\\n # We\'ve reached maturity, time to check capital protection\\n if year_prices[end] > protection_barrier\\n return nominal + total_coupons\\n else\\n put = (strike - year_prices[end]) / strike\\n return nominal*(1-put)\\n end\\nend\\n\\nforward_structure = forward_term(term)\\nprice_function = (year_prices) -> price_phoenix_no_memory(S0, year_prices,\\n call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)\\n\\nphoenix_no_memory = function()\\n year_indexes = [n*i for i=1:T]\\n motion = full_simulation(S0, T, n, m, term)\\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\\n return mean(payoffs)\\nend\\n\\nmean_payoffs = zeros(num_simulations)\\nfor i=1:num_simulations\\n tic()\\n mean_payoffs[i] = phoenix_no_memory()\\n time = toq()\\n @printf(\\"Mean of simulation %i: \\\\$%.4f; Simulation time: %.2fs\\\\n\\", i, mean_payoffs[i], time)\\nend\\n\\nfinal_mean = mean(mean_payoffs)\\nprintln(\\"Mean over $num_simulations simulations: $(mean(mean_payoffs))\\")\\npv = final_mean * exp(-(prod(forward_structure)-1)*(T))\\n@printf(\\"Present value of Phoenix without memory note: \\\\$%.2f\\", pv)\\n```\\n\\n```\\n Mean of simulation 1: $106.0562; Simulation time: 5.72s\\n Mean of simulation 2: $106.0071; Simulation time: 5.85s\\n Mean of simulation 3: $105.9959; Simulation time: 5.87s\\n Mean of simulation 4: $106.0665; Simulation time: 5.93s\\n Mean of simulation 5: $106.0168; Simulation time: 5.81s\\n Mean over 5 simulations: 106.02850857209883\\n Present value of Phoenix without memory note: $97.44\\n```\\n\\n## Phoenix with Memory Simulation\\n\\nThe Phoenix with Memory structure is very similar to the Phoenix, but as the name implies, has a special \\"memory\\" property: **It remembers any coupons that haven\'t been paid at prior observation times, and pays them all if the underlying crosses the coupon barrier**. For example:\\n- Note issued with 100% call barrier, 70% coupon barrier. At year 1, the underlying is at 50%, so no coupons are paid. At year 2, the underlying is at 80%, so coupons for both year 1 and 2 are paid, resulting in a double coupon.\\n\\nYou can also find an example [here](https://www.rbccm.com/usstructurednotes/file-781232.pdf).\\n\\nLet\'s go ahead and set up the simulation! The parameters will be the same, but we can expect that the value will go up because of the memory attribute\\n\\n\\n```julia\\ncall_barrier = S0\\ncoupon_barrier = S0 * .8\\nprotection_barrier = S0 * .6\\ncoupon = nominal * .07\\n\\nprice_phoenix_with_memory = function(initial_price, year_prices, call_barrier,\\n coupon_barrier, protection_barrier, coupon, forward_structure)\\n\\n last_coupon = 0\\n total_coupons = 0\\n \\n t = length(year_prices)\\n\\n for i=1:t\\n price = year_prices[i]\\n if price > call_barrier\\n return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i))\\n elseif price > coupon_barrier\\n ####################################################################\\n # The only difference between with/without memory is the below lines\\n memory_coupons = (i - last_coupon) * coupon\\n last_coupon = i\\n total_coupons = total_coupons * exp(forward_structure[i]-1) + memory_coupons\\n ####################################################################\\n else\\n total_coupons *= exp(forward_structure[i]-1)\\n end\\n end\\n\\n # We\'ve reached maturity, time to check capital protection\\n if year_prices[end] > protection_barrier\\n return nominal + total_coupons\\n else\\n put = (strike - year_prices[end]) / strike\\n return nominal*(1-put)\\n end\\nend\\n\\nforward_structure = forward_term(term)\\nprice_function = (year_prices) -> price_phoenix_with_memory(S0, year_prices,\\n call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure)\\n\\nphoenix_with_memory = function()\\n year_indexes = [n*i for i=1:T]\\n motion = full_simulation(S0, T, n, m, term)\\n payoffs = [price_function(motion[i, year_indexes]) for i=1:m]\\n return mean(payoffs)\\nend\\n\\nmean_payoffs = zeros(num_simulations)\\nfor i=1:num_simulations\\n tic()\\n mean_payoffs[i] = phoenix_with_memory()\\n time = toq()\\n @printf(\\"Mean of simulation %i: \\\\$%.4f; Simulation time: %.2fs\\\\n\\",\\n i, mean_payoffs[i], time)\\nend\\n\\nfinal_mean = mean(mean_payoffs)\\nprintln(\\"Mean over $num_simulations simulations: $(mean(mean_payoffs))\\")\\npv = final_mean * exp(-(prod(forward_structure)-1)*(T))\\n@printf(\\"Present value of Phoenix with memory note: \\\\$%.2f\\", pv)\\n```\\n\\n```\\n Mean of simulation 1: $108.8612; Simulation time: 5.89s\\n Mean of simulation 2: $109.0226; Simulation time: 5.90s\\n Mean of simulation 3: $108.9175; Simulation time: 5.92s\\n Mean of simulation 4: $108.9426; Simulation time: 5.94s\\n Mean of simulation 5: $108.8087; Simulation time: 6.06s\\n Mean over 5 simulations: 108.91052564051816\\n Present value of Phoenix with memory note: $100.09\\n```"},{"id":"2015/11/welcome","metadata":{"permalink":"/2015/11/welcome","source":"@site/blog/2015-11-14-welcome/index.mdx","title":"Welcome, and an algorithm","description":"Hello! Glad to meet you. I\'m currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I\'m working on!","date":"2015-11-19T12:00:00.000Z","tags":[],"readingTime":4.175,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/11/welcome","title":"Welcome, and an algorithm","date":"2015-11-19T12:00:00.000Z","last_update":{"date":"2015-12-05T12:00:00.000Z"},"authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1449316800000,"prevItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}},"content":"Hello! Glad to meet you. I\'m currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I\'m working on!\\n\\n\x3c!-- truncate --\x3e\\n\\nTo start things off, Columbia has been hosting a trading competition that myself and another partner are competing in. I\'m including a notebook of the algorithm that we\'re using, just to give a simple overview of a miniature algorithm.\\n\\nThe competition is scored in 3 areas:\\n\\n- Total return\\n- [Sharpe ratio](https://en.wikipedia.org/wiki/Sharpe_ratio)\\n- Maximum drawdown\\n\\nOur algorithm uses a basic momentum strategy: in the given list of potential portfolios, pick the stocks that have been performing well in the past 30 days. Then, optimize for return subject to the drawdown being below a specific level. We didn\'t include the Sharpe ratio as a constraint, mostly because we were a bit late entering the competition.\\n\\nI\'ll be updating this post with the results of our algorithm as they come along!\\n\\n---\\n\\n**UPDATE 12/5/2015**: Now that the competition has ended, I wanted to update how the algorithm performed. Unfortunately, it didn\'t do very well. I\'m planning to make some tweaks over the coming weeks, and do another forward test in January.\\n\\n- After week 1: Down .1%\\n- After week 2: Down 1.4%\\n- After week 3: Flat\\n\\nAnd some statistics for all teams participating in the competition:\\n\\n| Statistic | Value |\\n|--------------------|--------|\\n| Max Return | 74.1% |\\n| Min Return | -97.4% |\\n| Average Return | -.1% |\\n| Std Dev of Returns | 19.6% |\\n\\n---\\n\\n## Trading Competition Optimization\\n\\n**Goal: Max return given maximum Sharpe and Drawdown**\\n\\n\\n```python\\nfrom IPython.display import display\\nimport Quandl\\nfrom datetime import datetime, timedelta\\n\\ntickers = [\'XOM\', \'CVX\', \'CLB\', \'OXY\', \'SLB\']\\nmarket_ticker = \'GOOG/NYSE_VOO\'\\nlookback = 30\\nd_col = \'Close\'\\n\\ndata = {tick: Quandl.get(\'YAHOO/{}\'.format(tick))[-lookback:] for tick in tickers}\\nmarket = Quandl.get(market_ticker)\\n```\\n\\n## Calculating the Return\\n\\nWe first want to know how much each ticker returned over the prior period.\\n\\n```python\\nreturns = {tick: data[tick][d_col].pct_change() for tick in tickers}\\n\\ndisplay({tick: returns[tick].mean() for tick in tickers})\\n```\\n\\n```\\n {\'CLB\': -0.0016320202164526894,\\n \'CVX\': 0.0010319531629488911,\\n \'OXY\': 0.00093418904454400551,\\n \'SLB\': 0.00098431254720448159,\\n \'XOM\': 0.00044165797556096868}\\n```\\n\\n## Calculating the Sharpe ratio\\n\\nSharpe: ${R - R_M \\\\over \\\\sigma}$\\n\\nWe use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive.\\n\\n\\n```python\\nmarket_returns = market.pct_change()\\n\\nsharpe = lambda ret: (ret.mean() - market_returns[d_col].mean()) / ret.std()\\nsharpes = {tick: sharpe(returns[tick]) for tick in tickers}\\n\\ndisplay(sharpes)\\n```\\n\\n```\\n {\'CLB\': -0.10578734457846127,\\n \'CVX\': 0.027303529817677398,\\n \'OXY\': 0.022622210057414487,\\n \'SLB\': 0.026950946344858676,\\n \'XOM\': -0.0053519259698605499}\\n```\\n\\n## Calculating the drawdown\\n\\nThis one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change?\\n\\n\\n```python\\ndrawdown = lambda ret: ret.abs().max()\\ndrawdowns = {tick: drawdown(returns[tick]) for tick in tickers}\\n\\ndisplay(drawdowns)\\n```\\n\\n```\\n {\'CLB\': 0.043551495607375035,\\n \'CVX\': 0.044894389686214398,\\n \'OXY\': 0.051424517867144637,\\n \'SLB\': 0.034774627850375328,\\n \'XOM\': 0.035851524605672758}\\n```\\n\\n# Performing the optimization\\n\\n$$\\n\\\\begin{align*}\\nmax\\\\ \\\\ & \\\\mu \\\\cdot \\\\omega\\\\\\\\\\ns.t.\\\\ \\\\ & \\\\vec{1} \\\\omega = 1\\\\\\\\\\n& \\\\vec{S} \\\\omega \\\\ge s\\\\\\\\\\n& \\\\vec{D} \\\\cdot | \\\\omega | \\\\le d\\\\\\\\\\n& \\\\left|\\\\omega\\\\right| \\\\le l\\\\\\\\\\n\\\\end{align*}\\n$$\\n\\nWe want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don\'t have huge long/short positions.\\n\\n```python\\nimport numpy as np\\nfrom scipy.optimize import minimize\\n\\n#sharpe_limit = .1\\ndrawdown_limit = .05\\nleverage = 250\\n\\n# Use the map so we can guarantee we maintain the correct order\\n\\n# So we can write as upper-bound\\n# sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1 \\ndd_a = np.array(list(map(lambda tick: drawdowns[tick], tickers)))\\n\\n# Because minimizing\\nreturns_a = np.array(list(map(lambda tick: returns[tick].mean(), tickers))) \\n\\nmeets_sharpe = lambda x: sum(abs(x) * sharpe_a) - sharpe_limit\\ndef meets_dd(x):\\n portfolio = sum(abs(x))\\n if portfolio < .1:\\n # If there are no stocks in the portfolio,\\n # we can accidentally induce division by 0,\\n # or division by something small enough to cause infinity\\n return 0\\n \\n return drawdown_limit - sum(abs(x) * dd_a) / sum(abs(x))\\n\\nis_portfolio = lambda x: sum(x) - 1\\n\\ndef within_leverage(x):\\n return leverage - sum(abs(x))\\n\\nobjective = lambda x: sum(x * returns_a) * -1 # Because we\'re minimizing\\nbounds = ((None, None),) * len(tickers)\\nx = np.zeros(len(tickers))\\n\\nconstraints = [\\n {\\n \'type\': \'eq\',\\n \'fun\': is_portfolio\\n }, {\\n \'type\': \'ineq\',\\n \'fun\': within_leverage\\n #}, {\\n # \'type\': \'ineq\',\\n # \'fun\': meets_sharpe\\n }, {\\n \'type\': \'ineq\',\\n \'fun\': meets_dd\\n }\\n]\\n\\noptimal = minimize(objective, x, bounds=bounds, constraints=constraints,\\n options={\'maxiter\': 500})\\n\\n# Optimization time!\\ndisplay(optimal.message)\\n\\ndisplay(\\"Holdings: {}\\".format(list(zip(tickers, optimal.x))))\\n\\n# multiply by -100 to scale, and compensate for minimizing\\nexpected_return = optimal.fun * -100\\ndisplay(\\"Expected Return: {:.3f}%\\".format(expected_return))\\n\\nexpected_drawdown = sum(abs(optimal.x) * dd_a) / sum(abs(optimal.x)) * 100\\ndisplay(\\"Expected Max Drawdown: {0:.2f}%\\".format(expected_drawdown))\\n\\n# TODO: Calculate expected Sharpe\\n```\\n\\n```\\n \'Optimization terminated successfully.\'\\n \\"Holdings: [(\'XOM\', 5.8337945679814904),\\n (\'CVX\', 42.935064321851307),\\n (\'CLB\', -124.5),\\n (\'OXY\', 36.790387773552119),\\n (\'SLB\', 39.940753336615096)]\\"\\n \'Expected Return: 32.375%\'\\n \'Expected Max Drawdown: 4.34%\'\\n```"}]}}')}}]); \ No newline at end of file diff --git a/assets/js/b537349a.fd272082.js b/assets/js/b537349a.fd272082.js new file mode 100644 index 0000000..85b3d02 --- /dev/null +++ b/assets/js/b537349a.fd272082.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6078"],{7126:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return a},default:function(){return p},frontMatter:function(){return s},metadata:function(){return o},toc:function(){return l}});var o=n(4024),r=n(5893),i=n(65);let s={slug:"2018/05/hello",title:"Hello!",date:new Date("2018-05-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,c={authorsImageUrls:[void 0]},l=[];function u(e){let t={img:"img",p:"p",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.p,{children:"I'll do what I can to keep this short, there's plenty of other things we both should be doing right\nnow."}),"\n",(0,r.jsx)(t.p,{children:"If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you\ncovered:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Saturday Bread",src:n(7115).Z+"",width:"3036",height:"2729"})}),"\n",(0,r.jsx)(t.p,{children:"And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven."}),"\n",(0,r.jsx)(t.p,{children:"Okay, just one:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Bread as rock",src:n(3811).Z+"",width:"3036",height:"2380"})}),"\n",(0,r.jsx)(t.p,{children:"Thanks, and keep it amazing."})]})}function p(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},7115:function(e,t,n){n.d(t,{Z:function(){return o}});let o=n.p+"assets/images/bread-52bb152a7c29148e837d94bdf1755e1c.jpg"},3811:function(e,t,n){n.d(t,{Z:function(){return o}});let o=n.p+"assets/images/rocks-6b9a0c44bf45210d496e2ebe2f896e0c.jpg"},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return s}});var o=n(7294);let r={},i=o.createContext(r);function s(e){let t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},4024:function(e){e.exports=JSON.parse('{"permalink":"/2018/05/hello","source":"@site/blog/2018-05-28-hello/index.mdx","title":"Hello!","description":"I\'ll do what I can to keep this short, there\'s plenty of other things we both should be doing right","date":"2018-05-28T12:00:00.000Z","tags":[],"readingTime":0.375,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/05/hello","title":"Hello!","date":"2018-05-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731187596000,"prevItem":{"title":"What I learned porting dateutil to Rust","permalink":"/2018/06/dateutil-parser-to-rust"},"nextItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"}}')}}]); \ No newline at end of file diff --git a/assets/js/b5b60058.690e82eb.js b/assets/js/b5b60058.690e82eb.js new file mode 100644 index 0000000..b607a78 --- /dev/null +++ b/assets/js/b5b60058.690e82eb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9798"],{6563:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return c},default:function(){return f},frontMatter:function(){return a},metadata:function(){return i},toc:function(){return s}});var i=n(2208),r=n(5893),o=n(65);let a={slug:"2016/04/tick-tock",title:"Tick tock...",date:new Date("2016-04-06T12:00:00.000Z"),authors:["bspeice"],tags:[]},c=void 0,u={authorsImageUrls:[void 0]},s=[];function l(e){let t={p:"p",...(0,o.a)(),...e.components};return(0,r.jsx)(t.p,{children:"If all we have is a finite number of heartbeats left, what about me?"})}function f(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return c},a:function(){return a}});var i=n(7294);let r={},o=i.createContext(r);function a(e){let t=i.useContext(o);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(o.Provider,{value:t},e.children)}},2208:function(e){e.exports=JSON.parse('{"permalink":"/2016/04/tick-tock","source":"@site/blog/2016-04-06-tick-tock/index.mdx","title":"Tick tock...","description":"If all we have is a finite number of heartbeats left, what about me?","date":"2016-04-06T12:00:00.000Z","tags":[],"readingTime":10.125,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/04/tick-tock","title":"Tick tock...","date":"2016-04-06T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"},"nextItem":{"title":"Tweet like me","permalink":"/2016/03/tweet-like-me"}}')}}]); \ No newline at end of file diff --git a/assets/js/b5d84c45.bfcf3ca8.js b/assets/js/b5d84c45.bfcf3ca8.js new file mode 100644 index 0000000..807de8b --- /dev/null +++ b/assets/js/b5d84c45.bfcf3ca8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5523"],{6297:function(e,t,n){n.r(t),n.d(t,{assets:function(){return s},contentTitle:function(){return c},default:function(){return p},frontMatter:function(){return a},metadata:function(){return i},toc:function(){return u}});var i=n(5419),r=n(5893),o=n(65);let a={slug:"2016/03/tweet-like-me",title:"Tweet like me",date:new Date("2016-03-28T12:00:00.000Z"),authors:["bspeice"],tags:[]},c=void 0,s={authorsImageUrls:[void 0]},u=[];function l(e){let t={p:"p",...(0,o.a)(),...e.components};return(0,r.jsx)(t.p,{children:"In which I try to create a robot that will tweet like I tweet."})}function p(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return c},a:function(){return a}});var i=n(7294);let r={},o=i.createContext(r);function a(e){let t=i.useContext(o);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(o.Provider,{value:t},e.children)}},5419:function(e){e.exports=JSON.parse('{"permalink":"/2016/03/tweet-like-me","source":"@site/blog/2016-03-28-tweet-like-me/index.mdx","title":"Tweet like me","description":"In which I try to create a robot that will tweet like I tweet.","date":"2016-03-28T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/03/tweet-like-me","title":"Tweet like me","date":"2016-03-28T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"},"nextItem":{"title":"Predicting Santander customer happiness","permalink":"/2016/03/predicting-santander-customer-happiness"}}')}}]); \ No newline at end of file diff --git a/assets/js/c32740fe.fac8281f.js b/assets/js/c32740fe.fac8281f.js new file mode 100644 index 0000000..a94884e --- /dev/null +++ b/assets/js/c32740fe.fac8281f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6992"],{1712:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return f},frontMatter:function(){return o},metadata:function(){return i},toc:function(){return u}});var i=n(4018),r=n(5893),a=n(65);let o={slug:"2016/05/the-unfair-casino",title:"The unfair casino",date:new Date("2016-05-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){let t={p:"p",...(0,a.a)(),...e.components};return(0,r.jsx)(t.p,{children:"Trying to figure out how exactly two dice are loaded in a cheating casino."})}function f(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return o}});var i=n(7294);let r={},a=i.createContext(r);function o(e){let t=i.useContext(a);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:t},e.children)}},4018:function(e){e.exports=JSON.parse('{"permalink":"/2016/05/the-unfair-casino","source":"@site/blog/2016-05-15-the-unfair-casino/index.mdx","title":"The unfair casino","description":"Trying to figure out how exactly two dice are loaded in a cheating casino.","date":"2016-05-15T12:00:00.000Z","tags":[],"readingTime":14.62,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/05/the-unfair-casino","title":"The unfair casino","date":"2016-05-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730679360000,"prevItem":{"title":"Event studies and earnings releases","permalink":"/2016/06/event-studies-and-earnings-releases"},"nextItem":{"title":"Tick tock...","permalink":"/2016/04/tick-tock"}}')}}]); \ No newline at end of file diff --git a/assets/js/c97f4488.7aeaa095.js b/assets/js/c97f4488.7aeaa095.js new file mode 100644 index 0000000..ac55db0 --- /dev/null +++ b/assets/js/c97f4488.7aeaa095.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9437"],{4217:function(e,n,t){t.r(n),t.d(n,{assets:function(){return l},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return s},metadata:function(){return a},toc:function(){return c}});var a=t(6954),o=t(5893),i=t(65);let s={slug:"2018/12/allocation-safety",title:"QADAPT - debug_assert! for allocations",date:new Date("2018-12-15T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Why an Allocator?",id:"why-an-allocator",level:2},{value:"Example 1",id:"example-1",level:3},{value:"Example 2",id:"example-2",level:3},{value:"Example 3",id:"example-3",level:3},{value:"Blowing Things Up",id:"blowing-things-up",level:2},{value:"Using a procedural macro",id:"using-a-procedural-macro",level:3},{value:"Using a regular macro",id:"using-a-regular-macro",level:3},{value:"Using function calls",id:"using-function-calls",level:3},{value:"Caveats",id:"caveats",level:3},{value:"Conclusion",id:"conclusion",level:2}];function h(e){let n={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"I think it's part of the human condition to ignore perfectly good advice when it comes our way. A\nbit over a month ago, I was dispensing sage wisdom for the ages:"}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["I had a really great idea: build a custom allocator that allows you to track your own allocations.\nI gave it a shot, but learned very quickly: ",(0,o.jsx)(n.strong,{children:"never write your own allocator."})]}),"\n",(0,o.jsxs)(n.p,{children:["-- ",(0,o.jsx)(n.a,{href:"/2018/10/case-study-optimization",children:"me"})]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"I proceeded to ignore it, because we never really learn from our mistakes."}),"\n",(0,o.jsx)(n.p,{children:"There's another part of the human condition that derives joy from seeing things explode."}),"\n",(0,o.jsx)("center",{children:(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"Explosions",src:t(7537).Z+"",width:"400",height:"280"})})}),"\n",(0,o.jsxs)(n.p,{children:["And ",(0,o.jsx)(n.em,{children:"that's"})," the part I'm going to focus on."]}),"\n",(0,o.jsx)(n.h2,{id:"why-an-allocator",children:"Why an Allocator?"}),"\n",(0,o.jsx)(n.p,{children:"So why, after complaining about allocators, would I still want to write one? There are three reasons\nfor that:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"Allocation/dropping is slow"}),"\n",(0,o.jsx)(n.li,{children:"It's difficult to know exactly when Rust will allocate or drop, especially when using code that\nyou did not write"}),"\n",(0,o.jsx)(n.li,{children:"I want automated tools to verify behavior, instead of inspecting by hand"}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["When I say \"slow,\" it's important to define the terms. If you're writing web applications, you'll\nspend orders of magnitude more time waiting for the database than you will the allocator. However,\nthere's still plenty of code where micro- or nano-seconds matter; think\n",(0,o.jsx)(n.a,{href:"https://www.youtube.com/watch?v=NH1Tta7purM",children:"finance"}),",\n",(0,o.jsx)(n.a,{href:"https://www.reddit.com/r/rust/comments/9hg7yj/synthesizer_progress_update/e6c291f",children:"real-time audio"}),",\n",(0,o.jsx)(n.a,{href:"https://polysync.io/blog/session-types-for-hearty-codecs/",children:"self-driving cars"}),", and\n",(0,o.jsx)(n.a,{href:"https://carllerche.github.io/bytes/bytes/index.html",children:"networking"}),". In these situations it's simply\nunacceptable for you to spend time doing things that are not your program, and waiting on the\nallocator is not cool."]}),"\n",(0,o.jsxs)(n.p,{children:["As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen.\nSo, I propose we play a quick trivia game: ",(0,o.jsx)(n.strong,{children:"Does this code invoke the allocator?"})]}),"\n",(0,o.jsx)(n.h3,{id:"example-1",children:"Example 1"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"fn my_function() {\n let v: Vec<u8> = Vec::new();\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"No"}),": Rust ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/mem/fn.size_of.html",children:"knows how big"})," the ",(0,o.jsx)(n.code,{children:"Vec"})," type is,\nand reserves a fixed amount of memory on the stack for the ",(0,o.jsx)(n.code,{children:"v"})," vector. However, if we wanted to\nreserve extra space (using ",(0,o.jsx)(n.code,{children:"Vec::with_capacity"}),") the allocator would get invoked."]}),"\n",(0,o.jsx)(n.h3,{id:"example-2",children:"Example 2"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"fn my_function() {\n let v: Box<Vec<u8>> = Box::new(Vec::new());\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Yes"}),": Because Boxes allow us to work with things that are of unknown size, it has to allocate on\nthe heap. While the ",(0,o.jsx)(n.code,{children:"Box"})," is unnecessary in this snippet (release builds will optimize out the\nallocation), reserving heap space more generally is needed to pass a dynamically sized type to\nanother function."]}),"\n",(0,o.jsx)(n.h3,{id:"example-3",children:"Example 3"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"fn my_function(v: Vec<u8>) {\n v.push(5);\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Maybe"}),": Depending on whether the Vector we were given has space available, we may or may not\nallocate. Especially when dealing with code that you did not author, it's difficult to verify that\nthings behave as you expect them to."]}),"\n",(0,o.jsx)(n.h2,{id:"blowing-things-up",children:"Blowing Things Up"}),"\n",(0,o.jsxs)(n.p,{children:["So, how exactly does QADAPT solve these problems? ",(0,o.jsx)(n.strong,{children:"Whenever an allocation or drop occurs in code\nmarked allocation-safe, QADAPT triggers a thread panic."})," We don't want to let the program continue\nas if nothing strange happened, ",(0,o.jsx)(n.em,{children:"we want things to explode"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["However, you don't want code to panic in production because of circumstances you didn't predict.\nJust like ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/std/macro.debug_assert.html",children:(0,o.jsx)(n.code,{children:"debug_assert!"})}),", ",(0,o.jsx)(n.strong,{children:"QADAPT will\nstrip out its own code when building in release mode to guarantee no panics and no performance\nimpact."})]}),"\n",(0,o.jsx)(n.p,{children:"Finally, there are three ways to have QADAPT check that your code will not invoke the allocator:"}),"\n",(0,o.jsx)(n.h3,{id:"using-a-procedural-macro",children:"Using a procedural macro"}),"\n",(0,o.jsx)(n.p,{children:"The easiest method, watch an entire function for allocator invocation:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"use qadapt::no_alloc;\nuse qadapt::QADAPT;\n\n#[global_allocator]\nstatic Q: QADAPT = QADAPT;\n\n#[no_alloc]\nfn push_vec(v: &mut Vec<u8>) {\n // This triggers a panic if v.len() == v.capacity()\n v.push(5);\n}\n\nfn main() {\n let v = Vec::with_capacity(1);\n\n // This will *not* trigger a panic\n push_vec(&v);\n\n // This *will* trigger a panic\n push_vec(&v);\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"using-a-regular-macro",children:"Using a regular macro"}),"\n",(0,o.jsx)(n.p,{children:"For times when you need more precision:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"use qadapt::assert_no_alloc;\nuse qadapt::QADAPT;\n\n#[global_allocator]\nstatic Q: QADAPT = QADAPT;\n\nfn main() {\n let v = Vec::with_capacity(1);\n\n // No allocations here, we already have space reserved\n assert_no_alloc!(v.push(5));\n\n // Even though we remove an item, it doesn't trigger a drop\n // because it's a scalar. If it were a `Box<_>` type,\n // a drop would trigger.\n assert_no_alloc!({\n v.pop().unwrap();\n });\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"using-function-calls",children:"Using function calls"}),"\n",(0,o.jsx)(n.p,{children:"Both the most precise and most tedious:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"use qadapt::enter_protected;\nuse qadapt::exit_protected;\nuse qadapt::QADAPT;\n\n#[global_allocator]\nstatic Q: QADAPT = QADAPT;\n\nfn main() {\n // This triggers an allocation (on non-release builds)\n let v = Vec::with_capacity(1);\n\n enter_protected();\n // This does not trigger an allocation because we've reserved size\n v.push(0);\n exit_protected();\n\n // This triggers an allocation because we ran out of size,\n // but doesn't panic because we're no longer protected.\n v.push(1);\n}\n"})}),"\n",(0,o.jsx)(n.h3,{id:"caveats",children:"Caveats"}),"\n",(0,o.jsx)(n.p,{children:"It's important to point out that QADAPT code is synchronous, so please be careful when mixing in\nasynchronous functions:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",children:"use futures::future::Future;\nuse futures::future::ok;\n\n#[no_alloc]\nfn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> {\n ok(12).and_then(|e| Ok(Vec::with_capacity(e)))\n}\n\nfn main() {\n // This doesn't trigger a panic because the `and_then` closure\n // wasn't run during the function call.\n async_capacity();\n\n // Still no panic\n assert_no_alloc!(async_capacity());\n\n // This will panic because the allocation happens during `unwrap`\n // in the `assert_no_alloc!` macro\n assert_no_alloc!(async_capacity().poll().unwrap());\n}\n"})}),"\n",(0,o.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,o.jsxs)(n.p,{children:["While there's a lot more to writing high-performance code than managing your usage of the allocator,\nit's critical that you do use the allocator correctly. QADAPT will verify that your code is doing\nwhat you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for\nmost allocators. Version 1.0 was released today, and you can check it out over at\n",(0,o.jsx)(n.a,{href:"https://crates.io/crates/qadapt",children:"crates.io"})," or on ",(0,o.jsx)(n.a,{href:"https://github.com/bspeice/qadapt",children:"github"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will\nhelp guide that. If there are topics you're interested in, let me know in the comments below!"})]})}function d(e={}){let{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},7537:function(e,n,t){t.d(n,{Z:function(){return a}});let a=t.p+"assets/images/watch-the-world-burn-630e740c91d090f5790a3f4e103f1142.webp"},65:function(e,n,t){t.d(n,{Z:function(){return r},a:function(){return s}});var a=t(7294);let o={},i=a.createContext(o);function s(e){let n=a.useContext(i);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),a.createElement(i.Provider,{value:n},e.children)}},6954:function(e){e.exports=JSON.parse('{"permalink":"/2018/12/allocation-safety","source":"@site/blog/2018-12-15-allocation-safety/index.mdx","title":"QADAPT - debug_assert! for allocations","description":"I think it\'s part of the human condition to ignore perfectly good advice when it comes our way. A","date":"2018-12-15T12:00:00.000Z","tags":[],"readingTime":4.775,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/12/allocation-safety","title":"QADAPT - debug_assert! for allocations","date":"2018-12-15T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"},"nextItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"}}')}}]); \ No newline at end of file diff --git a/assets/js/ccc49370.f10e1762.js b/assets/js/ccc49370.f10e1762.js new file mode 100644 index 0000000..0968b88 --- /dev/null +++ b/assets/js/ccc49370.f10e1762.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["2998"],{8127:function(e,t,n){n.d(t,{Z:function(){return s}});var i=n(5893);n(7294);var l=n(6025),r=n(790);function s(e){let{nextItem:t,prevItem:n}=e;return(0,i.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,l.I)({id:"theme.blog.post.paginator.navAriaLabel",message:"Blog post page navigation",description:"The ARIA label for the blog posts pagination"}),children:[t&&(0,i.jsx)(r.Z,{...t,subLabel:(0,i.jsx)(l.Z,{id:"theme.blog.post.paginator.olderPost",description:"The blog post button label to navigate to the older/next post",children:"Older post"})}),n&&(0,i.jsx)(r.Z,{...n,subLabel:(0,i.jsx)(l.Z,{id:"theme.blog.post.paginator.newerPost",description:"The blog post button label to navigate to the newer/previous post",children:"Newer post"}),isNext:!0})]})}},131:function(e,t,n){n.d(t,{Z:function(){return o}});var i=n(5893),l=n(7294),r=n(4403);function s(e){let{title:t,headingType:n,children:l}=e;return(0,i.jsxs)("div",{role:"group",children:[(0,i.jsx)(r.Z,{as:n,children:t}),l]})}let o=(0,l.memo)(function(e){let{items:t,yearGroupHeadingClassName:n,ListComponent:l}=e;return function(e,t){var n=[],l=[];function r(){if(0===l.length)return;let e=new Date(l[0].date).getFullYear(),r=function(e,t){var n=[],l=[];function r(){if(0===l.length)return;let e=l[0].title.split(":")[0];l=(l=l.map(e=>({...e,title:e.title.split(":")[1].trim()}))).reverse(),n.push((0,i.jsx)(i.Fragment,{children:(0,i.jsx)(s,{title:e,headingType:"h4",children:(0,i.jsx)("ul",{children:(0,i.jsx)(t,{items:l})})})})),l=[]}for(let s of e){if(s.title.includes(":")){l.push(s);continue}r(),n.push((0,i.jsx)(t,{items:[s]}))}return r(),n}(l,t);n.push((0,i.jsx)(i.Fragment,{children:(0,i.jsx)(s,{title:String(e),headingType:"h3",children:r})})),l=[]}for(let t of e){if(0===l.length){l.push(t);continue}let e=new Date(t.date).getFullYear();e!==new Date(l[0].date).getFullYear()&&r(),l.push(t)}return r(),n}(t,l)})}}]); \ No newline at end of file diff --git a/assets/js/cd68b6a4.371cb0e3.js b/assets/js/cd68b6a4.371cb0e3.js new file mode 100644 index 0000000..4358abb --- /dev/null +++ b/assets/js/cd68b6a4.371cb0e3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["1408"],{4849:function(e,t,s){s.r(t),s.d(t,{metadata:()=>n,contentTitle:()=>u,default:()=>x,assets:()=>m,toc:()=>g,frontMatter:()=>p});var n=s("9810"),a=s("5893"),i=s("65");let o=s.p+"assets/medias/1-bc356a416dae6236d2e366a42bee2cd3.wav",r=s.p+"assets/medias/2-bc356a416dae6236d2e366a42bee2cd3.wav",l=s.p+"assets/medias/3-e8092f56b531e18a0d335c0f391b46b9.wav",d=s.p+"assets/medias/4-90047e615651067970475dc7f117aceb.wav",c=s.p+"assets/medias/5-896767515da7b5a0fe46e9a205c1130f.wav",h=s.p+"assets/medias/6-756ec27a28b4fa02181f43ed9061f0b3.wav",p={slug:"2016/11/pca-audio-compression",title:"PCA audio compression",date:new Date("2016-11-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,m={authorsImageUrls:[void 0]},g=[{value:"Towards a new (and pretty poor) compression scheme",id:"towards-a-new-and-pretty-poor-compression-scheme",level:2},{value:"A Brief Introduction to Audio Compression",id:"a-brief-introduction-to-audio-compression",level:2},{value:"A PCA-based Compression Scheme",id:"a-pca-based-compression-scheme",level:2},{value:"Running the Algorithm",id:"running-the-algorithm",level:2},{value:"Drop the (Treble)",id:"drop-the-treble",level:2},{value:"A More Realistic Example",id:"a-more-realistic-example",level:2},{value:"Conclusions",id:"conclusions",level:2}];function f(e){let t={a:"a",code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure."}),"\n",(0,a.jsx)(t.h2,{id:"towards-a-new-and-pretty-poor-compression-scheme",children:"Towards a new (and pretty poor) compression scheme"}),"\n",(0,a.jsxs)(t.p,{children:["I'm going to be working with some audio data for a while as I get prepared for a term project this semester. I'll be working (with a partner) to design a system for separating voices from music. Given my total lack of experience with ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Digital_signal_processing",children:"Digital Signal Processing"})," I figured that now was as good a time as ever to work on a couple of fun projects that would get me back up to speed."]}),"\n",(0,a.jsx)(t.p,{children:"The first project I want to work on: Designing a new compression scheme for audio data."}),"\n",(0,a.jsx)(t.h2,{id:"a-brief-introduction-to-audio-compression",children:"A Brief Introduction to Audio Compression"}),"\n",(0,a.jsxs)(t.p,{children:["Audio files when uncompressed (files ending with ",(0,a.jsx)(t.code,{children:".wav"}),") are huge. Like, 10.5 Megabytes per minute huge. Storage is cheap these days, but that's still an incredible amount of data that we don't really need. Instead, we'd like to compress that data so that it's not taking up so much space. There are broadly two ways to accomplish this:"]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsxs)(t.p,{children:["Lossless compression - Formats like ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/FLAC",children:"FLAC"}),", ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Apple_Lossless",children:"ALAC"}),", and ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Monkey%27s_Audio",children:"Monkey's Audio (.ape)"})," all go down this route. The idea is that when you compress and uncompress a file, you get exactly the same as what you started with."]}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsxs)(t.p,{children:["Lossy compression - Formats like ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/MP3",children:"MP3"}),", ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Vorbis",children:"Ogg"}),", and ",(0,a.jsxs)(t.a,{href:"https://en.wikipedia.org/wiki/Advanced_Audio_Coding",children:["AAC (",(0,a.jsx)(t.code,{children:".m4a"}),")"]})," are far more popular, but make a crucial tradeoff: We can reduce the file size even more during compression, but the decompressed file won't be the same."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["There is a fundamental tradeoff at stake: Using lossy compression sacrifices some of the integrity of the resulting file to save on storage space. Most people (I personally believe it's everybody) can't hear the difference, so this is an acceptable tradeoff. You have files that take up a 10",(0,a.jsx)("sup",{children:"th"})," of the space, and nobody can tell there's a difference in audio quality."]}),"\n",(0,a.jsx)(t.h2,{id:"a-pca-based-compression-scheme",children:"A PCA-based Compression Scheme"}),"\n",(0,a.jsxs)(t.p,{children:["What I want to try out is a ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Principal_component_analysis",children:"PCA"})," approach to encoding audio. The PCA technique comes from Machine Learning, where it is used for a process called ",(0,a.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Dimensionality_reduction",children:"Dimensionality Reduction"}),". Put simply, the idea is the same as lossy compression: if we can find a way that represents the data well enough, we can save on space. There are a lot of theoretical concerns that lead me to believe this compression style will not end well, but I'm interested to try it nonetheless."]}),"\n",(0,a.jsx)(t.p,{children:'PCA works as follows: Given a dataset with a number of features, I find a way to approximate those original features using some "new features" that are statistically as close as possible to the original ones. This is comparable to a scheme like MP3: Given an original signal, I want to find a way of representing it that gets approximately close to what the original was. The difference is that PCA is designed for statistical data, and not signal data. But we won\'t let that stop us.'}),"\n",(0,a.jsx)(t.p,{children:"The idea is as follows: Given a signal, reshape it into 1024 columns by however many rows are needed (zero-padded if necessary). Run the PCA algorithm, and do dimensionality reduction with a couple different settings. The number of components I choose determines the quality: If I use 1024 components, I will essentially be using the original signal. If I use a smaller number of components, I start losing some of the data that was in the original file. This will give me an idea of whether it's possible to actually build an encoding scheme off of this, or whether I'm wasting my time."}),"\n",(0,a.jsx)(t.h2,{id:"running-the-algorithm",children:"Running the Algorithm"}),"\n",(0,a.jsxs)(t.p,{children:["The audio I will be using comes from the song ",(0,a.jsx)(t.a,{href:"https://brokeforfree.bandcamp.com/track/tabulasa",children:"Tabulasa"}),", by ",(0,a.jsx)(t.a,{href:"https://brokeforfree.bandcamp.com/album/xxvii",children:"Broke for Free"}),". I'll be loading in the audio signal to Python and using ",(0,a.jsx)(t.a,{href:"http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html#sklearn.decomposition.PCA",children:"Scikit-Learn"})," to actually run the PCA algorithm."]}),"\n",(0,a.jsx)(t.p,{children:"We first need to convert the FLAC file I have to a WAV:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:'!ffmpeg -hide_banner -loglevel panic -i "Broke For Free/XXVII/01 Tabulasa.flac" "Tabulasa.wav" -c wav\n'})}),"\n",(0,a.jsx)(t.p,{children:"Then, let's go ahead and load a small sample so you can hear what is going on."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"from IPython.display import Audio\nfrom scipy.io import wavfile\n\nsamplerate, tabulasa = wavfile.read('Tabulasa.wav')\n\nstart = samplerate * 14 # 10 seconds in\nend = start + samplerate * 10 # 5 second duration\nAudio(data=tabulasa[start:end, 0], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:o}),"\n",(0,a.jsx)(t.p,{children:"Next, we'll define the code we will be using to do PCA. It's very short, as the PCA algorithm is very simple."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"from sklearn.decomposition import PCA\nimport numpy as np\n\ndef pca_reduce(signal, n_components, block_size=1024):\n \n # First, zero-pad the signal so that it is divisible by the block_size\n samples = len(signal)\n hanging = block_size - np.mod(samples, block_size)\n padded = np.lib.pad(signal, (0, hanging), 'constant', constant_values=0)\n \n # Reshape the signal to have 1024 dimensions\n reshaped = padded.reshape((len(padded) // block_size, block_size))\n \n # Second, do the actual PCA process\n pca = PCA(n_components=n_components)\n pca.fit(reshaped)\n \n transformed = pca.transform(reshaped)\n reconstructed = pca.inverse_transform(transformed).reshape((len(padded)))\n return pca, transformed, reconstructed\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Now that we've got our functions set up, let's try actually running something. First, we'll use ",(0,a.jsx)(t.code,{children:"n_components == block_size"}),", which implies that we should end up with the same signal we started with."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"tabulasa_left = tabulasa[:,0]\n\n_, _, reconstructed = pca_reduce(tabulasa_left, 1024, 1024)\n\nAudio(data=reconstructed[start:end], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:r}),"\n",(0,a.jsx)(t.p,{children:"OK, that does indeed sound like what we originally had. Let's drastically cut down the number of components we're doing this with as a sanity check: the audio quality should become incredibly poor."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"_, _, reconstructed = pca_reduce(tabulasa_left, 32, 1024)\n\nAudio(data=reconstructed[start:end], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:l}),"\n",(0,a.jsx)(t.p,{children:"As expected, our reconstructed audio does sound incredibly poor! But there's something else very interesting going on here under the hood. Did you notice that the bassline comes across very well, but that there's no midrange or treble? The drums are almost entirely gone."}),"\n",(0,a.jsx)(t.h2,{id:"drop-the-treble",children:(0,a.jsx)(t.a,{href:"https://youtu.be/Ua0KpfJsxKo?t=1m17s",children:"Drop the (Treble)"})}),"\n",(0,a.jsx)(t.p,{children:'It will help to understand PCA more fully when trying to read this part, but I\'ll do my best to break it down. PCA tries to find a way to best represent the dataset using "components." Think of each "component" as containing some of the information you need in order to reconstruct the full audio. For example, you might have a "low frequency" component that contains all the information you need in order to hear the bassline. There might be other components that explain the high frequency things like singers, or melodies, that you also need.'}),"\n",(0,a.jsx)(t.p,{children:"What makes PCA interesting is that it attempts to find the \"most important\" components in explaining the signal. In a signal processing world, this means that PCA is trying to find the signal amongst the noise in your data. In our case, this means that PCA, when forced to work with small numbers of components, will chuck out the noisy components first. It's doing it's best job to reconstruct the signal, but it has to make sacrifices somewhere."}),"\n",(0,a.jsx)(t.p,{children:"So I've mentioned that PCA identifies the \"noisy\" components in our dataset. This is equivalent to saying that PCA removes the \"high frequency\" components in this case: it's very easy to represent a low-frequency signal like a bassline. It's far more difficult to represent a high-frequency signal because it's changing all the time. When you force PCA to make a tradeoff by using a small number of components, the best it can hope to do is replicate the low-frequency sections and skip the high-frequency things."}),"\n",(0,a.jsx)(t.p,{children:"This is a very interesting insight, and it also has echos (pardon the pun) of how humans understand music in general. Other encoding schemes (like MP3, etc.) typically chop off a lot of the high-frequency range as well. There is typically a lot of high-frequency noise in audio that is nearly impossible to hear, so it's easy to remove it without anyone noticing. PCA ends up doing something similar, and while that certainly wasn't the intention, it is an interesting effect."}),"\n",(0,a.jsx)(t.h2,{id:"a-more-realistic-example",children:"A More Realistic Example"}),"\n",(0,a.jsx)(t.p,{children:"So we've seen the edge cases so far: Using a large number of components results in audio very close to the original, and using a small number of components acts as a low-pass filter. How about we develop something that sounds \"good enough\" in practice, that we can use as a benchmark for size? We'll use ourselves as judges of audio quality, and build another function to help us estimate how much space we need to store everything in."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:'from bz2 import compress\nimport pandas as pd\n\ndef raw_estimate(transformed, pca):\n # We assume that we\'ll be storing things as 16-bit WAV,\n # meaning two bytes per sample\n signal_bytes = transformed.tobytes()\n # PCA stores the components as floating point, we\'ll assume\n # that means 32-bit floats, so 4 bytes per element\n component_bytes = transformed.tobytes()\n \n # Return a result in megabytes\n return (len(signal_bytes) + len(component_bytes)) / (2**20)\n\n# Do an estimate for lossless compression applied on top of our\n# PCA reduction\ndef bz2_estimate(transformed, pca):\n bytestring = transformed.tobytes() + b\';\' + pca.components_.tobytes()\n compressed = compress(bytestring)\n return len(compressed) / (2**20)\n\ncompression_attempts = [\n (1, 1),\n (1, 2),\n (1, 4),\n (4, 32),\n (16, 256),\n (32, 256),\n (64, 256),\n (128, 1024),\n (256, 1024),\n (512, 1024),\n (128, 2048),\n (256, 2048),\n (512, 2048),\n (1024, 2048)\n]\n\ndef build_estimates(signal, n_components, block_size):\n pca, transformed, recon = pca_reduce(tabulasa_left, n_components, block_size)\n raw_pca_estimate = raw_estimate(transformed, pca)\n bz2_pca_estimate = bz2_estimate(transformed, pca)\n raw_size = len(recon.tobytes()) / (2**20)\n return raw_size, raw_pca_estimate, bz2_pca_estimate\n\npca_compression_results = pd.DataFrame([\n build_estimates(tabulasa_left, n, bs)\n for n, bs in compression_attempts\n ])\n\npca_compression_results.columns = ["Raw", "PCA", "PCA w/ BZ2"]\npca_compression_results.index = compression_attempts\npca_compression_results\n'})}),"\n",(0,a.jsx)("div",{children:(0,a.jsxs)("table",{children:[(0,a.jsx)("thead",{children:(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{}),(0,a.jsx)("th",{children:"Raw"}),(0,a.jsx)("th",{children:"PCA"}),(0,a.jsx)("th",{children:"PCA w/ BZ2"})]})}),(0,a.jsxs)("tbody",{children:[(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(1, 1)"}),(0,a.jsx)("td",{children:"69.054298"}),(0,a.jsx)("td",{children:"138.108597"}),(0,a.jsx)("td",{children:"16.431797"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(1, 2)"}),(0,a.jsx)("td",{children:"69.054306"}),(0,a.jsx)("td",{children:"69.054306"}),(0,a.jsx)("td",{children:"32.981380"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(1, 4)"}),(0,a.jsx)("td",{children:"69.054321"}),(0,a.jsx)("td",{children:"34.527161"}),(0,a.jsx)("td",{children:"16.715032"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(4, 32)"}),(0,a.jsx)("td",{children:"69.054443"}),(0,a.jsx)("td",{children:"17.263611"}),(0,a.jsx)("td",{children:"8.481735"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(16, 256)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"8.631836"}),(0,a.jsx)("td",{children:"4.274846"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(32, 256)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"17.263672"}),(0,a.jsx)("td",{children:"8.542909"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(64, 256)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"34.527344"}),(0,a.jsx)("td",{children:"17.097543"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(128, 1024)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"17.263672"}),(0,a.jsx)("td",{children:"9.430644"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(256, 1024)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"34.527344"}),(0,a.jsx)("td",{children:"18.870387"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(512, 1024)"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"69.054688"}),(0,a.jsx)("td",{children:"37.800940"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(128, 2048)"}),(0,a.jsx)("td",{children:"69.062500"}),(0,a.jsx)("td",{children:"8.632812"}),(0,a.jsx)("td",{children:"6.185015"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(256, 2048)"}),(0,a.jsx)("td",{children:"69.062500"}),(0,a.jsx)("td",{children:"17.265625"}),(0,a.jsx)("td",{children:"12.366942"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(512, 2048)"}),(0,a.jsx)("td",{children:"69.062500"}),(0,a.jsx)("td",{children:"34.531250"}),(0,a.jsx)("td",{children:"24.736506"})]}),(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{children:"(1024, 2048)"}),(0,a.jsx)("td",{children:"69.062500"}),(0,a.jsx)("td",{children:"69.062500"}),(0,a.jsx)("td",{children:"49.517493"})]})]})]})}),"\n",(0,a.jsx)(t.p,{children:"As we can see, there are a couple of instances where we do nearly 20 times better on storage space than the uncompressed file. Let's here what that sounds like:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"_, _, reconstructed = pca_reduce(tabulasa_left, 16, 256)\nAudio(data=reconstructed[start:end], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:d}),"\n",(0,a.jsx)(t.p,{children:"It sounds incredibly poor though. Let's try something that's a bit more realistic:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"_, _, reconstructed = pca_reduce(tabulasa_left, 1, 4)\nAudio(data=reconstructed[start:end], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:c}),"\n",(0,a.jsx)(t.p,{children:"And just out of curiosity, we can try something that has the same ratio of components to block size. This should be close to an apples-to-apples comparison."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-python",children:"_, _, reconstructed = pca_reduce(tabulasa_left, 64, 256)\nAudio(data=reconstructed[start:end], rate=samplerate)\n"})}),"\n","\n",(0,a.jsx)("audio",{controls:!0,src:h}),"\n",(0,a.jsx)(t.p,{children:"The smaller block size definitely has better high-end response, but I personally think the larger block size sounds better overall."}),"\n",(0,a.jsx)(t.h2,{id:"conclusions",children:"Conclusions"}),"\n",(0,a.jsx)(t.p,{children:"So, what do I think about audio compression using PCA?"}),"\n",(0,a.jsx)(t.p,{children:"Strangely enough, it actually works pretty well relative to what I expected. That said, it's a terrible idea in general."}),"\n",(0,a.jsx)(t.p,{children:"First off, you don't really save any space. The component matrix needed to actually run the PCA algorithm takes up a lot of space on its own, so it's very difficult to save space without sacrificing a huge amount of audio quality. And even then, codecs like AAC sound very nice even at bitrates that this PCA method could only dream of."}),"\n",(0,a.jsx)(t.p,{children:"Second, there's the issue of audio streaming. PCA relies on two components: the datastream, and a matrix used to reconstruct the original signal. While it is easy to stream the data, you can't stream that matrix. And even if you divided the stream up into small blocks to give you a small matrix, you must guarantee that the matrix arrives; if you don't have that matrix, the data stream will make no sense whatsoever."}),"\n",(0,a.jsx)(t.p,{children:"All said, this was an interesting experiment. It's really cool seeing PCA used for signal analysis where I haven't seen it applied before, but I don't think it will lead to any practical results. Look forward to more signal processing stuff in the future!"})]})}function x(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(f,{...e})}):f(e)}},65:function(e,t,s){s.d(t,{Z:function(){return r},a:function(){return o}});var n=s(7294);let a={},i=n.createContext(a);function o(e){let t=n.useContext(i);return n.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:t},e.children)}},9810:function(e){e.exports=JSON.parse('{"permalink":"/2016/11/pca-audio-compression","source":"@site/blog/2016-11-01-PCA-audio-compression/index.mdx","title":"PCA audio compression","description":"In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.","date":"2016-11-01T12:00:00.000Z","tags":[],"readingTime":10.39,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/11/pca-audio-compression","title":"PCA audio compression","date":"2016-11-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"Captain\'s Cookbook: Project setup","permalink":"/2018/01/captains-cookbook-part-1"},"nextItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"}}')}}]); \ No newline at end of file diff --git a/assets/js/d085497a.41eaf6d0.js b/assets/js/d085497a.41eaf6d0.js new file mode 100644 index 0000000..712e7bf --- /dev/null +++ b/assets/js/d085497a.41eaf6d0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8704"],{2372:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return o},default:function(){return u},frontMatter:function(){return s},metadata:function(){return a},toc:function(){return d}});var a=n(2231),r=n(5893),i=n(65);let s={slug:"2015/12/testing-cramer",title:"Testing Cramer",date:new Date("2015-12-26T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,l={authorsImageUrls:[void 0]},d=[{value:"Downloading Futures data from Seeking Alpha",id:"downloading-futures-data-from-seeking-alpha",level:2},{value:"Fetching the Returns data",id:"fetching-the-returns-data",level:2},{value:"Running the Comparison",id:"running-the-comparison",level:2},{value:"The next step - Predicting the close",id:"the-next-step---predicting-the-close",level:2},{value:"Final sentiments",id:"final-sentiments",level:2}];function c(e){let t={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["Pursuant to attending a graduate school studying Financial Engineering, I've been a fan of the ",(0,r.jsx)(t.a,{href:"http://www.cnbc.com/mad-money/",children:"Mad Money"})," TV show featuring the bombastic Jim Cramer. One of the things that he's said is that you shouldn't use the futures to predict where the stock market is going to go. But he says it often enough, I've begun to wonder - who is he trying to convince?"]}),"\n",(0,r.jsx)(t.p,{children:"It makes sense that because futures on things like the S&P 500 are traded continuously, they would price in market information before the stock market opens. So is Cramer right to be convinced that strategies based on the futures are a poor idea? I wanted to test it out."}),"\n",(0,r.jsxs)(t.p,{children:["The first question is where to get the future's data. I've been part of ",(0,r.jsx)(t.a,{href:"http://seekingalpha.com/",children:"Seeking Alpha"})," for a bit, and they publish the ",(0,r.jsx)(t.a,{href:"http://seekingalpha.com/author/wall-street-breakfast?s=wall-street-breakfast",children:"Wall Street Breakfast"})," newsletter which contains daily future's returns as of 6:20 AM EST. I'd be interested in using that data to see if we can actually make some money."]}),"\n",(0,r.jsx)(t.p,{children:"First though, let's get the data:"}),"\n",(0,r.jsx)(t.h2,{id:"downloading-futures-data-from-seeking-alpha",children:"Downloading Futures data from Seeking Alpha"}),"\n",(0,r.jsx)(t.p,{children:"We're going to define two HTML parsing classes - one to get the article URL's from a page, and one to get the actual data from each article."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:'class ArticleListParser(HTMLParser):\n """Given a web page with articles on it, parse out the article links"""\n \n articles = []\n \n def handle_starttag(self, tag, attrs):\n #if tag == \'div\' and ("id", "author_articles_wrapper") in attrs:\n # self.fetch_links = True\n if tag == \'a\' and (\'class\', \'dashboard_article_link\') in attrs:\n href = list(filter(lambda x: x[0] == \'href\', attrs))[0][1]\n self.articles.append(href)\n \nbase_url = "http://seekingalpha.com/author/wall-street-breakfast/articles"\narticle_page_urls = [base_url] + [base_url + \'/{}\'.format(i) for i in range(2, 20)]\n\nglobal_articles = []\nfor page in article_page_urls:\n # We need to switch the user agent, as SA blocks the standard requests agent\n articles_html = requests.get(page,\n headers={"User-Agent": "Wget/1.13.4"})\n parser = ArticleListParser()\n parser.feed(articles_html.text)\n global_articles += (parser.articles)\n'})}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:"class ArticleReturnParser(HTMLParser):\n \"Given an article, parse out the futures returns in it\"\n \n record_font_tags = False\n in_font_tag = False\n counter = 0\n # data = {} # See __init__\n \n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.data = {}\n \n def handle_starttag(self, tag, attrs):\n if tag == 'span' and ('itemprop', 'datePublished') in attrs:\n date_string = list(filter(lambda x: x[0] == 'content', attrs))[0][1]\n date = dtparser.parse(date_string)\n self.data['date'] = date\n \n self.in_font_tag = tag == 'font'\n \n def safe_float(self, string):\n try:\n return float(string[:-1]) / 100\n except ValueError:\n return np.NaN\n \n def handle_data(self, content):\n if not self.record_font_tags and \"Futures at 6\" in content:\n self.record_font_tags = True\n \n if self.record_font_tags and self.in_font_tag:\n if self.counter == 0:\n self.data['DOW'] = self.safe_float(content)\n elif self.counter == 1:\n self.data['S&P'] = self.safe_float(content)\n elif self.counter == 2:\n self.data['NASDAQ'] = self.safe_float(content)\n elif self.counter == 3:\n self.data['Crude'] = self.safe_float(content)\n elif self.counter == 4:\n self.data['Gold'] = self.safe_float(content)\n \n self.counter += 1\n \n def handle_endtag(self, tag):\n self.in_font_tag = False\n\ndef retrieve_data(url):\n sa = \"http://seekingalpha.com\"\n article_html = requests.get(sa + url,\n headers={\"User-Agent\": \"Wget/1.13.4\"})\n parser = ArticleReturnParser()\n parser.feed(article_html.text)\n parser.data.update({\"url\": url})\n parser.data.update({\"text\": article_html.text})\n return parser.data\n\n# This copy **MUST** be in place. I'm not sure why,\n# as you'd think that the data being returned would already\n# represent a different memory location. Even so, it blows up\n# if you don't do this.\narticle_list = list(set(global_articles))\narticle_data = [copy(retrieve_data(url)) for url in article_list]\n# If there's an issue downloading the article, drop it.\narticle_df = pd.DataFrame.from_dict(article_data).dropna()\n"})}),"\n",(0,r.jsx)(t.h2,{id:"fetching-the-returns-data",children:"Fetching the Returns data"}),"\n",(0,r.jsx)(t.p,{children:"Now that we have the futures data, we're going to compare across 4 different indices - the S&P 500 index, Dow Jones Industrial, Russell 2000, and NASDAQ 100. Let's get the data off of Quandl to make things easier!"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:'# article_df is sorted by date, so we get the first row.\nstart_date = article_df.sort_values(by=\'date\').iloc[0][\'date\'] - relativedelta(days=1)\nSPY = Quandl.get("GOOG/NYSE_SPY", trim_start=start_date)\nDJIA = Quandl.get("GOOG/AMS_DIA", trim_start=start_date)\nRUSS = Quandl.get("GOOG/AMEX_IWM", trim_start=start_date)\nNASDAQ = Quandl.get("GOOG/EPA_QQQ", trim_start=start_date)\n'})}),"\n",(0,r.jsx)(t.h2,{id:"running-the-comparison",children:"Running the Comparison"}),"\n",(0,r.jsx)(t.p,{children:"There are two types of tests I want to determine: How accurate each futures category is at predicting the index's opening change over the close before, and predicting the index's daily return."}),"\n",(0,r.jsx)(t.p,{children:"Let's first calculate how good each future is at predicting the opening return over the previous day. I expect that the futures will be more than 50% accurate, since the information is recorded 3 hours before the markets open."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:'def calculate_opening_ret(frame):\n # I\'m not a huge fan of the appending for loop,\n # but it\'s a bit verbose for a comprehension\n data = {}\n for i in range(1, len(frame)):\n date = frame.iloc[i].name\n prior_close = frame.iloc[i-1][\'Close\']\n open_val = frame.iloc[i][\'Open\']\n data[date] = (open_val - prior_close) / prior_close\n \n return data\n\nSPY_open_ret = calculate_opening_ret(SPY)\nDJIA_open_ret = calculate_opening_ret(DJIA)\nRUSS_open_ret = calculate_opening_ret(RUSS)\nNASDAQ_open_ret = calculate_opening_ret(NASDAQ)\n\ndef signs_match(list_1, list_2):\n # This is a surprisingly difficult task - we have to match\n # up the dates in order to check if opening returns actually match\n index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}\n \n matches = []\n for row in list_1.iterrows():\n row_dt = row[1][1]\n row_value = row[1][0]\n index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)\n if index_dt in list_2:\n index_value = list_2[index_dt]\n if (row_value > 0 and index_value > 0) or \\\n (row_value < 0 and index_value < 0) or \\\n (row_value == 0 and index_value == 0):\n matches += [1]\n else:\n matches += [0]\n #print("{}".format(list_2[index_dt]))\n return matches\n \n \nprediction_dict = {}\nmatches_dict = {}\ncount_dict = {}\nindex_dict = {"SPY": SPY_open_ret, "DJIA": DJIA_open_ret, "RUSS": RUSS_open_ret, "NASDAQ": NASDAQ_open_ret}\nindices = ["SPY", "DJIA", "RUSS", "NASDAQ"]\nfutures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"]\nfor index in indices:\n matches_dict[index] = {future: signs_match(article_df[[future, \'date\']],\n index_dict[index]) for future in futures}\n count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}\n prediction_dict[index] = {future: np.mean(matches_dict[index][future])\n for future in futures}\nprint("Articles Checked: ")\nprint(pd.DataFrame.from_dict(count_dict))\nprint()\nprint("Prediction Accuracy:")\nprint(pd.DataFrame.from_dict(prediction_dict))\n'})}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:" Articles Checked: \n DJIA NASDAQ RUSS SPY\n Crude 268 268 271 271\n DOW 268 268 271 271\n Gold 268 268 271 271\n NASDAQ 268 268 271 271\n S&P 268 268 271 271\n \n Prediction Accuracy:\n DJIA NASDAQ RUSS SPY\n Crude 0.544776 0.522388 0.601476 0.590406\n DOW 0.611940 0.604478 0.804428 0.841328\n Gold 0.462687 0.455224 0.464945 0.476015\n NASDAQ 0.615672 0.608209 0.797048 0.830258\n S&P 0.604478 0.597015 0.811808 0.848708\n"})}),"\n",(0,r.jsx)(t.p,{children:"This data is very interesting. Some insights:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Both DOW and NASDAQ futures are pretty bad at predicting their actual market openings"}),"\n",(0,r.jsx)(t.li,{children:"NASDAQ and Dow are fairly unpredictable; Russell 2000 and S&P are very predictable"}),"\n",(0,r.jsx)(t.li,{children:"Gold is a poor predictor in general - intuitively Gold should move inverse to the market, but it appears to be about as accurate as a coin flip."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"All said though it appears that futures data is important for determining market direction for both the S&P 500 and Russell 2000. Cramer is half-right: futures data isn't very helpful for the Dow and NASDAQ indices, but is great for the S&P and Russell indices."}),"\n",(0,r.jsx)(t.h2,{id:"the-next-step---predicting-the-close",children:"The next step - Predicting the close"}),"\n",(0,r.jsx)(t.p,{children:"Given the code we currently have, I'd like to predict the close of the market as well. We can re-use most of the code, so let's see what happens:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-python",children:'def calculate_closing_ret(frame):\n # I\'m not a huge fan of the appending for loop,\n # but it\'s a bit verbose for a comprehension\n data = {}\n for i in range(0, len(frame)):\n date = frame.iloc[i].name\n open_val = frame.iloc[i][\'Open\']\n close_val = frame.iloc[i][\'Close\']\n data[date] = (close_val - open_val) / open_val\n \n return data\n\nSPY_close_ret = calculate_closing_ret(SPY)\nDJIA_close_ret = calculate_closing_ret(DJIA)\nRUSS_close_ret = calculate_closing_ret(RUSS)\nNASDAQ_close_ret = calculate_closing_ret(NASDAQ)\n\ndef signs_match(list_1, list_2):\n # This is a surprisingly difficult task - we have to match\n # up the dates in order to check if opening returns actually match\n index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()}\n \n matches = []\n for row in list_1.iterrows():\n row_dt = row[1][1]\n row_value = row[1][0]\n index_dt = datetime(row_dt.year, row_dt.month, row_dt.day)\n if index_dt in list_2:\n index_value = list_2[index_dt]\n if (row_value > 0 and index_value > 0) or \\\n (row_value < 0 and index_value < 0) or \\\n (row_value == 0 and index_value == 0):\n matches += [1]\n else:\n matches += [0]\n #print("{}".format(list_2[index_dt]))\n return matches\n \n \nmatches_dict = {}\ncount_dict = {}\nprediction_dict = {}\nindex_dict = {"SPY": SPY_close_ret, "DJIA": DJIA_close_ret,\n "RUSS": RUSS_close_ret, "NASDAQ": NASDAQ_close_ret}\nindices = ["SPY", "DJIA", "RUSS", "NASDAQ"]\nfutures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"]\nfor index in indices:\n matches_dict[index] = {future: signs_match(article_df[[future, \'date\']],\n index_dict[index]) for future in futures}\n count_dict[index] = {future: len(matches_dict[index][future]) for future in futures}\n prediction_dict[index] = {future: np.mean(matches_dict[index][future])\n for future in futures}\n \nprint("Articles Checked:")\nprint(pd.DataFrame.from_dict(count_dict))\nprint()\nprint("Prediction Accuracy:")\nprint(pd.DataFrame.from_dict(prediction_dict))\n'})}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:" Articles Checked:\n DJIA NASDAQ RUSS SPY\n Crude 268 268 271 271\n DOW 268 268 271 271\n Gold 268 268 271 271\n NASDAQ 268 268 271 271\n S&P 268 268 271 271\n \n Prediction Accuracy:\n DJIA NASDAQ RUSS SPY\n Crude 0.533582 0.529851 0.501845 0.542435\n DOW 0.589552 0.608209 0.535055 0.535055\n Gold 0.455224 0.451493 0.483395 0.512915\n NASDAQ 0.582090 0.626866 0.531365 0.538745\n S&P 0.585821 0.608209 0.535055 0.535055\n"})}),"\n",(0,r.jsx)(t.p,{children:"Well, it appears that the futures data is terrible at predicting market close. NASDAQ predicting NASDAQ is the most interesting data point, but 63% accuracy isn't accurate enough to make money consistently."}),"\n",(0,r.jsx)(t.h2,{id:"final-sentiments",children:"Final sentiments"}),"\n",(0,r.jsx)(t.p,{children:"The data bears out very close to what I expected would happen:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Futures data is more accurate than a coin flip for predicting openings, which makes sense since it is recorded only 3 hours before the actual opening"}),"\n",(0,r.jsx)(t.li,{children:"Futures data is about as acccurate as a coin flip for predicting closings, which means there is no money to be made in trying to predict the market direction for the day given the futures data."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"In summary:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Cramer is half right: Futures data is not good for predicting the market open of the Dow and NASDAQ indices. Contrary to Cramer though, it is very good for predicting the S&P and Russell indices - we can achieve an accuracy slightly over 80% for each."}),"\n",(0,r.jsx)(t.li,{children:"Making money in the market is hard. We can't just go to the futures and treat them as an oracle for where the market will close."}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"I hope you've enjoyed this, I quite enjoyed taking a deep dive in the analytics this way. I'll be posting more soon!"})]})}function u(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return s}});var a=n(7294);let r={},i=a.createContext(r);function s(e){let t=a.useContext(i);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(i.Provider,{value:t},e.children)}},2231:function(e){e.exports=JSON.parse('{"permalink":"/2015/12/testing-cramer","source":"@site/blog/2015-12-26-testing-cramer/index.mdx","title":"Testing Cramer","description":"Pursuant to attending a graduate school studying Financial Engineering, I\'ve been a fan of the Mad Money TV show featuring the bombastic Jim Cramer. One of the things that he\'s said is that you shouldn\'t use the futures to predict where the stock market is going to go. But he says it often enough, I\'ve begun to wonder - who is he trying to convince?","date":"2015-12-26T12:00:00.000Z","tags":[],"readingTime":8.23,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2015/12/testing-cramer","title":"Testing Cramer","date":"2015-12-26T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Complaining about the weather","permalink":"/2016/01/complaining-about-the-weather"},"nextItem":{"title":"Autocallable Bonds","permalink":"/2015/11/autocallable"}}')}}]); \ No newline at end of file diff --git a/assets/js/d185f613.d18d8259.js b/assets/js/d185f613.d18d8259.js new file mode 100644 index 0000000..9b592e9 --- /dev/null +++ b/assets/js/d185f613.d18d8259.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5407"],{3561:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return s},metadata:function(){return o},toc:function(){return c}});var o=n(9395),a=n(5893),i=n(65);let s={title:"Allocations in Rust: Compiler optimizations",description:"A lot. The answer is a lot.",date:new Date("2019-02-08T12:00:00.000Z"),last_updated:{date:new Date("2019-02-10T12:00:00.000Z")},tags:[]},r=void 0,l={authorsImageUrls:[]},c=[{value:"The Case of the Disappearing Box",id:"the-case-of-the-disappearing-box",level:2},{value:"Dr. Array or: how I learned to love the optimizer",id:"dr-array-or-how-i-learned-to-love-the-optimizer",level:2}];function h(e){let t={a:"a",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Up to this point, we've been discussing memory usage in the Rust language by focusing on simple\nrules that are mostly right for small chunks of code. We've spent time showing how those rules work\nthemselves out in practice, and become familiar with reading the assembly code needed to see each\nmemory type (global, stack, heap) in action."}),"\n",(0,a.jsx)(t.p,{children:"Throughout the series so far, we've put a handicap on the code. In the name of consistent and\nunderstandable results, we've asked the compiler to pretty please leave the training wheels on. Now\nis the time where we throw out all the rules and take off the kid gloves. As it turns out, both the\nRust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them\ndo their job."}),"\n",(0,a.jsxs)(t.p,{children:["Similar to\n",(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=bSkpMdDe4g4",children:'"What Has My Compiler Done For Me Lately?"'}),", we're\nfocusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll\nstill be looking at assembly code to understand what's going on, but it's important to mention\nagain: ",(0,a.jsxs)(t.strong,{children:["please use automated tools like ",(0,a.jsx)(t.a,{href:"https://crates.io/crates/alloc_counter",children:"alloc-counter"})," to\ndouble-check memory behavior if it's something you care about"]}),". It's far too easy to mis-read\nassembly in large code sections, you should always verify behavior if you care about memory usage."]}),"\n",(0,a.jsxs)(t.p,{children:["The guiding principal as we move forward is this: ",(0,a.jsx)(t.em,{children:"optimizing compilers won't produce worse programs\nthan we started with."})," There won't be any situations where stack allocations get moved to heap\nallocations. There will, however, be an opera of optimization."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"Update 2019-02-10"}),": When debugging a\n",(0,a.jsx)(t.a,{href:"https://gitlab.com/sio4/code/alloc-counter/issues/1",children:"related issue"}),", it was discovered that the\noriginal code worked because LLVM optimized out the entire function, rather than just the allocation\nsegments. The code has been updated with proper use of\n",(0,a.jsx)(t.a,{href:"https://doc.rust-lang.org/std/ptr/fn.read_volatile.html",children:(0,a.jsx)(t.code,{children:"read_volatile"})}),", and a previous section\non vector capacity has been removed."]}),"\n",(0,a.jsx)(t.h2,{id:"the-case-of-the-disappearing-box",children:"The Case of the Disappearing Box"}),"\n",(0,a.jsxs)(t.p,{children:["Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently\nshort that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the\nstack instead! The way this interacts with ",(0,a.jsx)(t.code,{children:"#[inline]"})," attributes is a bit opaque, but the important\npart is that LLVM can sometimes do better than the baseline Rust language:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-rust",children:'use std::alloc::{GlobalAlloc, Layout, System};\nuse std::sync::atomic::{AtomicBool, Ordering};\n\npub fn cmp(x: u32) {\n // Turn on panicking if we allocate on the heap\n DO_PANIC.store(true, Ordering::SeqCst);\n\n // The compiler is able to see through the constant `Box`\n // and directly compare `x` to 24 - assembly line 73\n let y = Box::new(24);\n let equals = x == *y;\n\n // This call to drop is eliminated\n drop(y);\n\n // Need to mark the comparison result as volatile so that\n // LLVM doesn\'t strip out all the code. If `y` is marked\n // volatile instead, allocation will be forced.\n unsafe { std::ptr::read_volatile(&equals) };\n\n // Turn off panicking, as there are some deallocations\n // when we exit main.\n DO_PANIC.store(false, Ordering::SeqCst);\n}\n\nfn main() {\n cmp(12)\n}\n\n#[global_allocator]\nstatic A: PanicAllocator = PanicAllocator;\nstatic DO_PANIC: AtomicBool = AtomicBool::new(false);\nstruct PanicAllocator;\n\nunsafe impl GlobalAlloc for PanicAllocator {\n unsafe fn alloc(&self, layout: Layout) -> *mut u8 {\n if DO_PANIC.load(Ordering::SeqCst) {\n panic!("Unexpected allocation.");\n }\n System.alloc(layout)\n }\n\n unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {\n if DO_PANIC.load(Ordering::SeqCst) {\n panic!("Unexpected deallocation.");\n }\n System.dealloc(ptr, layout);\n }\n}\n'})}),"\n",(0,a.jsxs)(t.p,{children:["-- ",(0,a.jsx)(t.a,{href:"https://godbolt.org/z/BZ_Yp3",children:"Compiler Explorer"})]}),"\n",(0,a.jsxs)(t.p,{children:["-- ",(0,a.jsx)(t.a,{href:"https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4a765f753183d5b919f62c71d2109d5d",children:"Rust Playground"})]}),"\n",(0,a.jsx)(t.h2,{id:"dr-array-or-how-i-learned-to-love-the-optimizer",children:"Dr. Array or: how I learned to love the optimizer"}),"\n",(0,a.jsxs)(t.p,{children:["Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping\nout code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if\nyou're not careful, they can make your benchmarks look\n",(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=nXaxk27zwlk&feature=youtu.be&t=1199",children:"impossibly good"}),". In Rust, the\n",(0,a.jsx)(t.code,{children:"black_box"})," function (implemented in both\n",(0,a.jsx)(t.a,{href:"https://doc.rust-lang.org/1.1.0/test/fn.black_box.html",children:(0,a.jsx)(t.code,{children:"libtest"})})," and\n",(0,a.jsx)(t.a,{href:"https://docs.rs/criterion/0.2.10/criterion/fn.black_box.html",children:(0,a.jsx)(t.code,{children:"criterion"})}),") will tell the compiler\nto disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up\nrunning programs that previously caused errors:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-rust",children:"#[derive(Default)]\nstruct TwoFiftySix {\n _a: [u64; 32]\n}\n\n#[derive(Default)]\nstruct EightK {\n _a: [TwoFiftySix; 32]\n}\n\n#[derive(Default)]\nstruct TwoFiftySixK {\n _a: [EightK; 32]\n}\n\n#[derive(Default)]\nstruct EightM {\n _a: [TwoFiftySixK; 32]\n}\n\npub fn main() {\n // Normally this blows up because we can't reserve size on stack\n // for the `EightM` struct. But because the compiler notices we\n // never do anything with `_x`, it optimizes out the stack storage\n // and the program completes successfully.\n let _x = EightM::default();\n}\n"})}),"\n",(0,a.jsxs)(t.p,{children:["-- ",(0,a.jsx)(t.a,{href:"https://godbolt.org/z/daHn7P",children:"Compiler Explorer"})]}),"\n",(0,a.jsxs)(t.p,{children:["-- ",(0,a.jsx)(t.a,{href:"https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4c253bf26072119896ab93c6ef064dc0",children:"Rust Playground"})]})]})}function d(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return s}});var o=n(7294);let a={},i=o.createContext(a);function s(e){let t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},9395:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/08/compiler-optimizations","source":"@site/blog/2019-02-08-compiler-optimizations/index.mdx","title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","tags":[],"readingTime":3.695,"hasTruncateMarker":true,"authors":[],"frontMatter":{"title":"Allocations in Rust: Compiler optimizations","description":"A lot. The answer is a lot.","date":"2019-02-08T12:00:00.000Z","last_updated":{"date":"2019-02-10T12:00:00.000Z"},"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Summary","permalink":"/2019/02/summary"},"nextItem":{"title":"Allocations in Rust: Dynamic memory","permalink":"/2019/02/a-heaping-helping"}}')}}]); \ No newline at end of file diff --git a/assets/js/d280b035.762e2b8a.js b/assets/js/d280b035.762e2b8a.js new file mode 100644 index 0000000..e9310d5 --- /dev/null +++ b/assets/js/d280b035.762e2b8a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7120"],{4260:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return a},default:function(){return d},frontMatter:function(){return r},metadata:function(){return o},toc:function(){return c}});var o=n(6583),i=n(5893),s=n(65);let r={slug:"2019/02/understanding-allocations-in-rust",title:"Allocations in Rust: Foreword",date:new Date("2019-02-04T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,l={authorsImageUrls:[void 0]},c=[];function u(e){let t={a:"a",code:"code",p:"p",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["There's an alchemy of distilling complex technical topics into articles and videos that change the\nway programmers see the tools they interact with on a regular basis. I knew what a linker was, but\nthere's a staggering amount of complexity in between\n",(0,i.jsxs)(t.a,{href:"https://www.youtube.com/watch?v=dOfucXtyEsU",children:["the OS and ",(0,i.jsx)(t.code,{children:"main()"})]}),". Rust programmers use the\n",(0,i.jsx)(t.a,{href:"https://doc.rust-lang.org/stable/std/boxed/struct.Box.html",children:(0,i.jsx)(t.code,{children:"Box"})})," type all the time, but there's a\nrich history of the Rust language itself wrapped up in\n",(0,i.jsx)(t.a,{href:"https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/",children:"how special it is"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"In a similar vein, this series attempts to look at code and understand how memory is used; the\ncomplex choreography of operating system, compiler, and program that frees you to focus on\nfunctionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the\ncognitive burden associated with memory management, but we're going to step into its world for a\nwhile."}),"\n",(0,i.jsx)(t.p,{children:"Let's learn a bit about memory in Rust."})]})}function d(e={}){let{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return r}});var o=n(7294);let i={},s=o.createContext(i);function r(e){let t=o.useContext(s);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(s.Provider,{value:t},e.children)}},6583:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/understanding-allocations-in-rust","source":"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx","title":"Allocations in Rust: Foreword","description":"There\'s an alchemy of distilling complex technical topics into articles and videos that change the","date":"2019-02-04T12:00:00.000Z","tags":[],"readingTime":3.785,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/understanding-allocations-in-rust","title":"Allocations in Rust: Foreword","date":"2019-02-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"},"nextItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"}}')}}]); \ No newline at end of file diff --git a/assets/js/d7ab2b33.2a9efd2a.js b/assets/js/d7ab2b33.2a9efd2a.js new file mode 100644 index 0000000..8cfcc09 --- /dev/null +++ b/assets/js/d7ab2b33.2a9efd2a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9127"],{4487:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return r},default:function(){return m},frontMatter:function(){return a},metadata:function(){return s},toc:function(){return u}});var s=n(5238),i=n(5893),o=n(65);let a={slug:"2019/02/a-heaping-helping",title:"Allocations in Rust: Dynamic memory",date:new Date("2019-02-07T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,l={authorsImageUrls:[void 0]},u=[];function c(e){let t={a:"a",em:"em",p:"p",strong:"strong",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and\nsome languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how\nthe language uses dynamic memory (also referred to as the ",(0,i.jsx)(t.strong,{children:"heap"}),") is a system called ",(0,i.jsx)(t.em,{children:"ownership"}),".\nAnd as the docs mention, ownership\n",(0,i.jsx)(t.a,{href:"https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html",children:"is Rust's most unique feature"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["The heap is used in two situations; when the compiler is unable to predict either the ",(0,i.jsx)(t.em,{children:"total size of\nmemory needed"}),", or ",(0,i.jsx)(t.em,{children:"how long the memory is needed for"}),", it allocates space in the heap."]})]})}function m(e={}){let{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return a}});var s=n(7294);let i={},o=s.createContext(i);function a(e){let t=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:t},e.children)}},5238:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/a-heaping-helping","source":"@site/blog/2019-02-07-a-heaping-helping/index.mdx","title":"Allocations in Rust: Dynamic memory","description":"Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and","date":"2019-02-07T12:00:00.000Z","tags":[],"readingTime":5.86,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/a-heaping-helping","title":"Allocations in Rust: Dynamic memory","date":"2019-02-07T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"},"nextItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"}}')}}]); \ No newline at end of file diff --git a/assets/js/db76ea4b.9758d9ce.js b/assets/js/db76ea4b.9758d9ce.js new file mode 100644 index 0000000..1eb1c4d --- /dev/null +++ b/assets/js/db76ea4b.9758d9ce.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6138"],{9994:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return s},default:function(){return p},frontMatter:function(){return i},metadata:function(){return o},toc:function(){return u}});var o=n(4111),a=n(5893),r=n(65);let i={slug:"2018/10/case-study-optimization",title:"A case study in heaptrack",date:new Date("2018-10-08T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function l(e){let t={a:"a",blockquote:"blockquote",p:"p",...(0,r.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I remember early in my career someone joking that:"}),"\n",(0,a.jsxs)(t.blockquote,{children:["\n",(0,a.jsx)(t.p,{children:"Programmers have it too easy these days. They should learn to develop in low memory environments\nand be more efficient."}),"\n"]}),"\n",(0,a.jsxs)(t.p,{children:["...though it's not like the first code I wrote was for a\n",(0,a.jsx)(t.a,{href:"https://web.archive.org/web/20180924060530/https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-se",children:"graphing calculator"}),"\npacking a whole 24KB of RAM."]}),"\n",(0,a.jsxs)(t.p,{children:["But the principle remains: be efficient with the resources you have, because\n",(0,a.jsx)(t.a,{href:"http://exo-blog.blogspot.com/2007/09/what-intel-giveth-microsoft-taketh-away.html",children:"what Intel giveth, Microsoft taketh away"}),"."]})]})}function p(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return i}});var o=n(7294);let a={},r=o.createContext(a);function i(e){let t=o.useContext(r);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(r.Provider,{value:t},e.children)}},4111:function(e){e.exports=JSON.parse('{"permalink":"/2018/10/case-study-optimization","source":"@site/blog/2018-10-08-case-study-optimization/index.mdx","title":"A case study in heaptrack","description":"I remember early in my career someone joking that:","date":"2018-10-08T12:00:00.000Z","tags":[],"readingTime":4.26,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/10/case-study-optimization","title":"A case study in heaptrack","date":"2018-10-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731189722000,"prevItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"},"nextItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"}}')}}]); \ No newline at end of file diff --git a/assets/js/dca2e11d.209b089a.js b/assets/js/dca2e11d.209b089a.js new file mode 100644 index 0000000..604334f --- /dev/null +++ b/assets/js/dca2e11d.209b089a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6424"],{5347:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return s},default:function(){return h},frontMatter:function(){return o},metadata:function(){return r},toc:function(){return c}});var r=n(6160),i=n(5893),a=n(65);let o={slug:"2019/12/release-the-gil",title:"Release the GIL",date:new Date("2019-12-14T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,l={authorsImageUrls:[void 0]},c=[];function u(e){let t={a:"a",em:"em",p:"p",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Complaining about the ",(0,i.jsx)(t.a,{href:"https://wiki.python.org/moin/GlobalInterpreterLock",children:"Global Interpreter Lock"}),"\n(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision\nmade before multi-core CPU's were widely available, but the fact that it's still around indicates\nthat it generally works ",(0,i.jsx)(t.a,{href:"https://wiki.c2.com/?PrematureOptimization",children:"Good"}),"\n",(0,i.jsx)(t.a,{href:"https://wiki.c2.com/?YouArentGonnaNeedIt",children:"Enough"}),". Besides, there are simple and effective\nworkarounds; it's not hard to start a\n",(0,i.jsx)(t.a,{href:"https://docs.python.org/3/library/multiprocessing.html",children:"new process"})," and use message passing to\nsynchronize code running in parallel."]}),"\n",(0,i.jsxs)(t.p,{children:["Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of\nasynchronicity and ",(0,i.jsx)(t.em,{children:"M:N"})," threading, Python seems lacking. The ideal scenario is to take advantage of\nboth Python's productivity and the modern CPU's parallel capabilities."]})]})}function h(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return o}});var r=n(7294);let i={},a=r.createContext(i);function o(e){let t=r.useContext(a);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),r.createElement(a.Provider,{value:t},e.children)}},6160:function(e){e.exports=JSON.parse('{"permalink":"/2019/12/release-the-gil","source":"@site/blog/2019-12-14-release-the-gil/index.mdx","title":"Release the GIL","description":"Complaining about the Global Interpreter Lock","date":"2019-12-14T12:00:00.000Z","tags":[],"readingTime":8.58,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/12/release-the-gil","title":"Release the GIL","date":"2019-12-14T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731207983000,"prevItem":{"title":"The webpack industrial complex","permalink":"/2011/11/webpack-industrial-complex"},"nextItem":{"title":"Binary format shootout","permalink":"/2019/09/binary-format-shootout"}}')}}]); \ No newline at end of file diff --git a/assets/js/de854ad9.70027cd9.js b/assets/js/de854ad9.70027cd9.js new file mode 100644 index 0000000..5a5c6ab --- /dev/null +++ b/assets/js/de854ad9.70027cd9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["9994"],{1244:function(e){e.exports=JSON.parse('{"metadata":{"permalink":"/page/4","page":4,"postsPerPage":10,"totalPages":4,"totalCount":34,"previousPage":"/page/3","blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/de863535.9c2d8ada.js b/assets/js/de863535.9c2d8ada.js new file mode 100644 index 0000000..aeef286 --- /dev/null +++ b/assets/js/de863535.9c2d8ada.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8276"],{2128:function(e,t,n){n.r(t),n.d(t,{assets:function(){return u},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return r},metadata:function(){return o},toc:function(){return c}});var o=n(4729),a=n(5893),i=n(65);let r={slug:"2011/11/webpack-industrial-complex",title:"The webpack industrial complex",date:new Date("2022-11-20T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,u={authorsImageUrls:[void 0]},c=[];function l(e){let t={p:"p",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:'This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).'}),"\n",(0,a.jsx)(t.p,{children:"The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process."})]})}function d(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return r}});var o=n(7294);let a={},i=o.createContext(a);function r(e){let t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},4729:function(e){e.exports=JSON.parse('{"permalink":"/2011/11/webpack-industrial-complex","source":"@site/blog/2022-11-20-webpack-industrial-complex/index.mdx","title":"The webpack industrial complex","description":"This started because I wanted to build a synthesizer. Setting a goal of \\"digital DX7\\" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).","date":"2022-11-20T12:00:00.000Z","tags":[],"readingTime":4.51,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2011/11/webpack-industrial-complex","title":"The webpack industrial complex","date":"2022-11-20T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731274898000,"nextItem":{"title":"Release the GIL","permalink":"/2019/12/release-the-gil"}}')}}]); \ No newline at end of file diff --git a/assets/js/e0aaf982.98e12c9e.js b/assets/js/e0aaf982.98e12c9e.js new file mode 100644 index 0000000..de5e2bb --- /dev/null +++ b/assets/js/e0aaf982.98e12c9e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8998"],{7508:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return s},default:function(){return d},frontMatter:function(){return r},metadata:function(){return o},toc:function(){return c}});var o=n(1495),i=n(5893),a=n(65);let r={slug:"2019/02/the-whole-world",title:"Allocations in Rust: Global memory",date:new Date("2019-02-05T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,l={authorsImageUrls:[void 0]},c=[];function u(e){let t={a:"a",code:"code",em:"em",p:"p",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["The first memory type we'll look at is pretty special: when Rust can prove that a ",(0,i.jsx)(t.em,{children:"value"})," is fixed\nfor the life of a program (",(0,i.jsx)(t.code,{children:"const"}),"), and when a ",(0,i.jsx)(t.em,{children:"reference"})," is unique for the life of a program\n(",(0,i.jsx)(t.code,{children:"static"})," as a declaration, not\n",(0,i.jsx)(t.a,{href:"https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#the-static-lifetime",children:(0,i.jsx)(t.code,{children:"'static"})})," as a\nlifetime), we can make use of global memory. This special section of data is embedded directly in\nthe program binary so that variables are ready to go once the program loads; no additional\ncomputation is necessary."]}),"\n",(0,i.jsxs)(t.p,{children:["Understanding the value/reference distinction is important for reasons we'll go into below, and\nwhile the\n",(0,i.jsx)(t.a,{href:"https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md",children:"full specification"})," for\nthese two keywords is available, we'll take a hands-on approach to the topic."]})]})}function d(e={}){let{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},65:function(e,t,n){n.d(t,{Z:function(){return s},a:function(){return r}});var o=n(7294);let i={},a=o.createContext(i);function r(e){let t=o.useContext(a);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(a.Provider,{value:t},e.children)}},1495:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/the-whole-world","source":"@site/blog/2019-02-05-the-whole-world/index.mdx","title":"Allocations in Rust: Global memory","description":"The first memory type we\'ll look at is pretty special: when Rust can prove that a value is fixed","date":"2019-02-05T12:00:00.000Z","tags":[],"readingTime":7.485,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/the-whole-world","title":"Allocations in Rust: Global memory","date":"2019-02-05T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Fixed memory","permalink":"/2019/02/stacking-up"},"nextItem":{"title":"Allocations in Rust: Foreword","permalink":"/2019/02/understanding-allocations-in-rust"}}')}}]); \ No newline at end of file diff --git a/assets/js/e37dfb5c.04d97c35.js b/assets/js/e37dfb5c.04d97c35.js new file mode 100644 index 0000000..8d97828 --- /dev/null +++ b/assets/js/e37dfb5c.04d97c35.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["3956"],{4297:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return a},default:function(){return u},frontMatter:function(){return o},metadata:function(){return i},toc:function(){return c}});var i=n(610),s=n(5893),r=n(65);let o={slug:"2019/02/summary",title:"Allocations in Rust: Summary",date:new Date("2019-02-09T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,l={authorsImageUrls:[void 0]},c=[];function d(e){let t={a:"a",code:"code",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["While there's a lot of interesting detail captured in this series, it's often helpful to have a\ndocument that answers some \"yes/no\" questions. You may not care about what an ",(0,s.jsx)(t.code,{children:"Iterator"})," looks like\nin assembly, you just need to know whether it allocates an object on the heap or not. And while Rust\nwill prioritize the fastest behavior it can, here are the rules for each memory type:"]}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Global Allocation"}),":"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"const"})," is a fixed value; the compiler is allowed to copy it wherever useful."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"static"})," is a fixed reference; the compiler will guarantee it is unique."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Stack Allocation"}),":"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Everything not using a smart pointer will be allocated on the stack."}),"\n",(0,s.jsx)(t.li,{children:"Structs, enums, iterators, arrays, and closures are all stack allocated."}),"\n",(0,s.jsxs)(t.li,{children:["Cell types (",(0,s.jsx)(t.code,{children:"RefCell"}),") behave like smart pointers, but are stack-allocated."]}),"\n",(0,s.jsxs)(t.li,{children:["Inlining (",(0,s.jsx)(t.code,{children:"#[inline]"}),") will not affect allocation behavior for better or worse."]}),"\n",(0,s.jsxs)(t.li,{children:["Types that are marked ",(0,s.jsx)(t.code,{children:"Copy"})," are guaranteed to have their contents stack-allocated."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Heap Allocation"}),":"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Smart pointers (",(0,s.jsx)(t.code,{children:"Box"}),", ",(0,s.jsx)(t.code,{children:"Rc"}),", ",(0,s.jsx)(t.code,{children:"Mutex"}),", etc.) allocate their contents in heap memory."]}),"\n",(0,s.jsxs)(t.li,{children:["Collections (",(0,s.jsx)(t.code,{children:"HashMap"}),", ",(0,s.jsx)(t.code,{children:"Vec"}),", ",(0,s.jsx)(t.code,{children:"String"}),", etc.) allocate their contents in heap memory."]}),"\n",(0,s.jsx)(t.li,{children:"Some smart pointers in the standard library have counterparts in other crates that don't need heap\nmemory. If possible, use those."}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Container Sizes in Rust",src:n(9209).Z+"",width:"960",height:"540"})}),"\n",(0,s.jsxs)(t.p,{children:["-- ",(0,s.jsx)(t.a,{href:"https://docs.google.com/presentation/d/1q-c7UAyrUlM-eZyTo1pd8SZ0qwA_wYxmPZVOQkoDmH4/edit?usp=sharing",children:"Raph Levien"})]})]})}function u(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},9209:function(e,t,n){n.d(t,{Z:function(){return i}});let i=n.p+"assets/images/container-size-7fd54cbb2391e3e7310b0424c5f92cc1.svg"},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return o}});var i=n(7294);let s={},r=i.createContext(s);function o(e){let t=i.useContext(r);return i.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:t},e.children)}},610:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/summary","source":"@site/blog/2019-02-09-summary/index.mdx","title":"Allocations in Rust: Summary","description":"While there\'s a lot of interesting detail captured in this series, it\'s often helpful to have a","date":"2019-02-09T12:00:00.000Z","tags":[],"readingTime":1.095,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/summary","title":"Allocations in Rust: Summary","date":"2019-02-09T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Making bread","permalink":"/2019/05/making-bread"},"nextItem":{"title":"Allocations in Rust: Compiler optimizations","permalink":"/2019/02/08/compiler-optimizations"}}')}}]); \ No newline at end of file diff --git a/assets/js/e62372be.2024c2a5.js b/assets/js/e62372be.2024c2a5.js new file mode 100644 index 0000000..0cd76f3 --- /dev/null +++ b/assets/js/e62372be.2024c2a5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6781"],{1490:function(e,t,n){n.r(t),n.d(t,{assets:function(){return o},contentTitle:function(){return u},default:function(){return d},frontMatter:function(){return a},metadata:function(){return s},toc:function(){return c}});var s=n(173),r=n(5893),i=n(65);let a={slug:"2016/06/event-studies-and-earnings-releases",title:"Event studies and earnings releases",date:new Date("2016-06-08T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,o={authorsImageUrls:[void 0]},c=[];function l(e){let t={p:"p",...(0,i.a)(),...e.components};return(0,r.jsx)(t.p,{children:"Or, being suspicious of market insiders."})}function d(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return a}});var s=n(7294);let r={},i=s.createContext(r);function a(e){let t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(i.Provider,{value:t},e.children)}},173:function(e){e.exports=JSON.parse('{"permalink":"/2016/06/event-studies-and-earnings-releases","source":"@site/blog/2016-06-08-event-studies-and-earnings-releases/index.mdx","title":"Event studies and earnings releases","description":"Or, being suspicious of market insiders.","date":"2016-06-08T12:00:00.000Z","tags":[],"readingTime":16.01,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/06/event-studies-and-earnings-releases","title":"Event studies and earnings releases","date":"2016-06-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730863976000,"prevItem":{"title":"A Rustic re-podcasting server","permalink":"/2016/10/rustic-repodcasting"},"nextItem":{"title":"The unfair casino","permalink":"/2016/05/the-unfair-casino"}}')}}]); \ No newline at end of file diff --git a/assets/js/ed9b7162.911627e7.js b/assets/js/ed9b7162.911627e7.js new file mode 100644 index 0000000..f2a9528 --- /dev/null +++ b/assets/js/ed9b7162.911627e7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["3533"],{1867:function(t,e,o){o.r(e),o.d(e,{assets:function(){return c},contentTitle:function(){return s},default:function(){return l},frontMatter:function(){return i},metadata:function(){return n},toc:function(){return u}});var n=o(457),a=o(5893),r=o(65);let i={slug:"2018/01/captains-cookbook-part-1",title:"Captain's Cookbook: Project setup",date:new Date("2018-01-16T12:00:00.000Z"),authors:["bspeice"],tags:[]},s=void 0,c={authorsImageUrls:[void 0]},u=[];function p(t){let e={p:"p",...(0,r.a)(),...t.components};return(0,a.jsx)(e.p,{children:"A basic introduction to getting started with Cap'N Proto."})}function l(t={}){let{wrapper:e}={...(0,r.a)(),...t.components};return e?(0,a.jsx)(e,{...t,children:(0,a.jsx)(p,{...t})}):p(t)}},65:function(t,e,o){o.d(e,{Z:function(){return s},a:function(){return i}});var n=o(7294);let a={},r=n.createContext(a);function i(t){let e=n.useContext(r);return n.useMemo(function(){return"function"==typeof t?t(e):{...e,...t}},[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(a):t.components||a:i(t.components),n.createElement(r.Provider,{value:e},t.children)}},457:function(t){t.exports=JSON.parse('{"permalink":"/2018/01/captains-cookbook-part-1","source":"@site/blog/2018-01-16-captains-cookbok-part-1/index.mdx","title":"Captain\'s Cookbook: Project setup","description":"A basic introduction to getting started with Cap\'N Proto.","date":"2018-01-16T12:00:00.000Z","tags":[],"readingTime":7.555,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-1","title":"Captain\'s Cookbook: Project setup","date":"2018-01-16T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"},"nextItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"}}')}}]); \ No newline at end of file diff --git a/assets/js/ef7aa1ca.f98a4c92.js b/assets/js/ef7aa1ca.f98a4c92.js new file mode 100644 index 0000000..c0f6c72 --- /dev/null +++ b/assets/js/ef7aa1ca.f98a4c92.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["832"],{8603:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return s},metadata:function(){return o},toc:function(){return l}});var o=n(457),a=n(5893),i=n(65);let s={slug:"2018/01/captains-cookbook-part-1",title:"Captain's Cookbook: Project setup",date:new Date("2018-01-16T12:00:00.000Z"),authors:["bspeice"],tags:[]},r=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Step 1: Installing <code>capnp</code>",id:"step-1-installing-capnp",level:2},{value:"Step 2: Starting a Cap'N Proto Rust project",id:"step-2-starting-a-capn-proto-rust-project",level:2},{value:"Step 3: Writing a basic schema",id:"step-3-writing-a-basic-schema",level:2},{value:"Step 4: Setting up the build process",id:"step-4-setting-up-the-build-process",level:2},{value:"Step 5: Running the build",id:"step-5-running-the-build",level:2},{value:"Step 6: Making a point",id:"step-6-making-a-point",level:2}];function p(e){let t={a:"a",code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"A basic introduction to getting started with Cap'N Proto."}),"\n",(0,a.jsxs)(t.p,{children:["I've been working a lot with ",(0,a.jsx)(t.a,{href:"https://capnproto.org/",children:"Cap'N Proto"})," recently with Rust, but there's a real dearth of information\non how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's\nfantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going."]}),"\n",(0,a.jsxs)(t.p,{children:["So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with ",(0,a.jsx)(t.a,{href:"https://developers.google.com/protocol-buffers/",children:"Protobuf"}),"\nand ",(0,a.jsx)(t.a,{href:"https://google.github.io/flatbuffers/",children:"FlatBuffers"}),", but is better compared with FlatBuffers. The whole point behind it\nis to define a schema language and serialization format such that:"]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"Applications that do not share the same base programming language can communicate"}),"\n",(0,a.jsx)(t.li,{children:"The data and schema you use can naturally evolve over time as your needs change"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"Accompanying this are typically code generators that take the schemas you define for your application and give you back\ncode for different languages to get data to and from that schema."}),"\n",(0,a.jsx)(t.p,{children:"Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way\nas is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there."}),"\n",(0,a.jsxs)(t.p,{children:["We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some\nexamples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects.\nIf you want to follow along, feel free. If not, I've posted ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1",children:"the final result"}),"\nfor reference."]}),"\n",(0,a.jsxs)(t.h2,{id:"step-1-installing-capnp",children:["Step 1: Installing ",(0,a.jsx)(t.code,{children:"capnp"})]}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.code,{children:"capnp"})," binary itself is needed for taking the schema files you write and turning them into a format that can be used by the\ncode generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed."]}),"\n",(0,a.jsxs)(t.p,{children:["I'll refer you to ",(0,a.jsx)(t.a,{href:"https://capnproto.org/install.html",children:"Cap'N Proto's installation instructions"})," here. As a quick TLDR though:"]}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Linux users will likely have a binary shipped by their package manager - On Ubuntu, ",(0,a.jsx)(t.code,{children:"apt install capnproto"})," is enough"]}),"\n",(0,a.jsxs)(t.li,{children:["OS X users can use ",(0,a.jsx)(t.a,{href:"https://brew.sh/",children:"Homebrew"})," as an easy install path. Just ",(0,a.jsx)(t.code,{children:"brew install capnp"})]}),"\n",(0,a.jsxs)(t.li,{children:["Windows users are a bit more complicated. If you're using ",(0,a.jsx)(t.a,{href:"https://chocolatey.org/",children:"Chocolatey"}),", there's ",(0,a.jsx)(t.a,{href:"https://chocolatey.org/packages/capnproto/",children:"a package"})," available. If that doesn't work however, you need to download ",(0,a.jsx)(t.a,{href:"https://capnproto.org/capnproto-c++-win32-0.6.1.zip",children:"a release zip"})," and make sure that the ",(0,a.jsx)(t.code,{children:"capnp.exe"})," binary is in your ",(0,a.jsx)(t.code,{children:"%PATH%"})," environment variable"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"The way you know you're done with this step is if the following command works in your shell:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"capnp id\n"})}),"\n",(0,a.jsx)(t.h2,{id:"step-2-starting-a-capn-proto-rust-project",children:"Step 2: Starting a Cap'N Proto Rust project"}),"\n",(0,a.jsxs)(t.p,{children:["After the ",(0,a.jsx)(t.code,{children:"capnp"})," binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"mkdir capnp_cookbook_1\ncd capnp_cookbook_1\ncargo init --bin\n"})}),"\n",(0,a.jsxs)(t.p,{children:["We'll put the following content into ",(0,a.jsx)(t.code,{children:"Cargo.toml"}),":"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:'[package]\nname = "capnp_cookbook_1"\nversion = "0.1.0"\nauthors = ["Bradlee Speice <bspeice@kcg.com>"]\n\n[build-dependencies]\ncapnpc = "0.8" # 1\n\n[dependencies]\ncapnp = "0.8" # 2\n'})}),"\n",(0,a.jsx)(t.p,{children:"This sets up:"}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsx)(t.li,{children:"The Rust code generator (CAPNProto Compiler)"}),"\n",(0,a.jsx)(t.li,{children:"The Cap'N Proto runtime library (CAPNProto runtime)"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"We've now got everything prepared that we need for writing a Cap'N Proto project."}),"\n",(0,a.jsx)(t.h2,{id:"step-3-writing-a-basic-schema",children:"Step 3: Writing a basic schema"}),"\n",(0,a.jsx)(t.p,{children:"We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure\nyou get familiar with how to start from a basic project."}),"\n",(0,a.jsx)(t.p,{children:"First, we're going to create a top-level directory for storing the schema files in:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"# Assuming we're starting from the `capnp_cookbook_1` directory created earlier\n\nmkdir schema\ncd schema\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Now, we're going to put the following content in ",(0,a.jsx)(t.code,{children:"point.capnp"}),":"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"@0xab555145c708dad2;\n\nstruct Point {\n x @0 :Int32;\n y @1 :Int32;\n}\n"})}),"\n",(0,a.jsx)(t.p,{children:"Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format."}),"\n",(0,a.jsx)(t.h2,{id:"step-4-setting-up-the-build-process",children:"Step 4: Setting up the build process"}),"\n",(0,a.jsxs)(t.p,{children:["Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using.\nThis is typically done through a ",(0,a.jsx)(t.code,{children:"build.rs"})," file to invoke the schema compiler."]}),"\n",(0,a.jsxs)(t.p,{children:["In the same folder as your ",(0,a.jsx)(t.code,{children:"Cargo.toml"})," file, please put the following content in ",(0,a.jsx)(t.code,{children:"build.rs"}),":"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-rust",children:'extern crate capnpc;\n\nfn main() {\n ::capnpc::CompilerCommand::new()\n .src_prefix("schema") // 1\n .file("schema/point.capnp") // 2\n .run().expect("compiling schema");\n}\n'})}),"\n",(0,a.jsxs)(t.p,{children:["This sets up the protocol compiler (",(0,a.jsx)(t.code,{children:"capnpc"})," from earlier) to compile the schema we've built so far."]}),"\n",(0,a.jsxs)(t.ol,{children:["\n",(0,a.jsxs)(t.li,{children:["Because Cap'N Proto schema files can re-use types specified in other files, the ",(0,a.jsx)(t.code,{children:"src_prefix()"})," tells the compiler\nwhere to look for those extra files at."]}),"\n",(0,a.jsxs)(t.li,{children:["We specify the schema file we're including by hand. In a much larger project, you could presumably build the ",(0,a.jsx)(t.code,{children:"CompilerCommand"}),"\ndynamically, but we won't worry too much about that one for now."]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"step-5-running-the-build",children:"Step 5: Running the build"}),"\n",(0,a.jsxs)(t.p,{children:["If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code.\nRun a ",(0,a.jsx)(t.code,{children:"cargo build"})," command, and if you don't see ",(0,a.jsx)(t.code,{children:"cargo"})," complaining, you're doing just fine!"]}),"\n",(0,a.jsxs)(t.p,{children:["So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated\ncode looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives\nsomewhere in the ",(0,a.jsx)(t.code,{children:"target/"})," directory."]}),"\n",(0,a.jsxs)(t.p,{children:["The long answer is that you're best off running a ",(0,a.jsx)(t.code,{children:"find"})," command to get the actual file path:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"# Assuming we're running from the capnp_cookbook_1 project folder\nfind . -name point_capnp.rs\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Alternately, if the ",(0,a.jsx)(t.code,{children:"find"})," command isn't available, the path will look something like:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs\n"})}),"\n",(0,a.jsx)(t.p,{children:"See if there are any paths in your target directory that look similar."}),"\n",(0,a.jsxs)(t.p,{children:["Now, the file content looks pretty nasty. I've included an example ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs",children:"here"}),"\nif you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how\nthe schema we wrote for the \"Point\" message is tied to the generated code."]}),"\n",(0,a.jsxs)(t.p,{children:["First, the Cap'N Proto library splits things up into ",(0,a.jsx)(t.code,{children:"Builder"})," and ",(0,a.jsx)(t.code,{children:"Reader"})," structs. These are best thought of the same way\nRust separates ",(0,a.jsx)(t.code,{children:"mut"})," from non-",(0,a.jsx)(t.code,{children:"mut"})," code. ",(0,a.jsx)(t.code,{children:"Builder"}),"s are ",(0,a.jsx)(t.code,{children:"mut"})," versions of your message, and ",(0,a.jsx)(t.code,{children:"Reader"}),"s are immutable versions."]}),"\n",(0,a.jsxs)(t.p,{children:["For example, the ",(0,a.jsxs)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L90",children:[(0,a.jsx)(t.code,{children:"Builder"})," impl"]})," for ",(0,a.jsx)(t.code,{children:"point"})," defines ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L105",children:(0,a.jsx)(t.code,{children:"get_x()"})}),", ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L109",children:(0,a.jsx)(t.code,{children:"set_x()"})}),", ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L113",children:(0,a.jsx)(t.code,{children:"get_y()"})}),", and ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L117",children:(0,a.jsx)(t.code,{children:"set_y()"})})," methods.\nIn comparison, the ",(0,a.jsxs)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L38",children:[(0,a.jsx)(t.code,{children:"Reader"})," impl"]})," only defines ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L47",children:(0,a.jsx)(t.code,{children:"get_x()"})})," and ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L51",children:(0,a.jsx)(t.code,{children:"get_y()"})})," methods."]}),"\n",(0,a.jsxs)(t.p,{children:["So now we know that there are some ",(0,a.jsx)(t.code,{children:"get"})," and ",(0,a.jsx)(t.code,{children:"set"})," methods available for our ",(0,a.jsx)(t.code,{children:"x"})," and ",(0,a.jsx)(t.code,{children:"y"})," coordinates;\nbut what do we actually do with those?"]}),"\n",(0,a.jsx)(t.h2,{id:"step-6-making-a-point",children:"Step 6: Making a point"}),"\n",(0,a.jsxs)(t.p,{children:["So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building\nCap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code\nshould go in ",(0,a.jsx)(t.a,{href:"https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs",children:(0,a.jsx)(t.code,{children:"src/main.rs"})}),":"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-rust",children:"// Note that we use `capnp` here, NOT `capnpc`\nextern crate capnp;\n\n// We create a module here to define how we are to access the code\n// being included.\npub mod point_capnp {\n // The environment variable OUT_DIR is set by Cargo, and\n // is the location of all the code that was built as part\n // of the codegen step.\n // point_capnp.rs is the actual file to include\n include!(concat!(env!(\"OUT_DIR\"), \"/point_capnp.rs\"));\n}\n\nfn main() {\n\n // The process of building a Cap'N Proto message is a bit tedious.\n // We start by creating a generic Builder; it acts as the message\n // container that we'll later be filling with content of our `Point`\n let mut builder = capnp::message::Builder::new_default();\n\n // Because we need a mutable reference to the `builder` later,\n // we fence off this part of the code to allow sequential mutable\n // borrows. As I understand it, non-lexical lifetimes:\n // https://github.com/rust-lang/rust-roadmap/issues/16\n // will make this no longer necessary\n {\n // And now we can set up the actual message we're trying to create\n let mut point_msg = builder.init_root::<point_capnp::point::Builder>();\n\n // Stuff our message with some content\n point_msg.set_x(12);\n\n point_msg.set_y(14);\n }\n\n // It's now time to serialize our message to binary. Let's set up a buffer for that:\n let mut buffer = Vec::new();\n\n // And actually fill that buffer with our data\n capnp::serialize::write_message(&mut buffer, &builder).unwrap();\n\n // Finally, let's deserialize the data\n let deserialized = capnp::serialize::read_message(\n &mut buffer.as_slice(),\n capnp::message::ReaderOptions::new()\n ).unwrap();\n\n // `deserialized` is currently a generic reader; it understands\n // the content of the message we gave it (i.e. that there are two\n // int32 values) but doesn't really know what they represent (the Point).\n // This is where we map the generic data back into our schema.\n let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();\n\n // We can now get our x and y values back, and make sure they match\n assert_eq!(point_reader.get_x(), 12);\n assert_eq!(point_reader.get_y(), 14);\n}\n"})}),"\n",(0,a.jsx)(t.p,{children:"And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up\nsome practical examples of Cap'N Proto in action:"})]})}function d(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},65:function(e,t,n){n.d(t,{Z:function(){return r},a:function(){return s}});var o=n(7294);let a={},i=o.createContext(a);function s(e){let t=o.useContext(i);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(i.Provider,{value:t},e.children)}},457:function(e){e.exports=JSON.parse('{"permalink":"/2018/01/captains-cookbook-part-1","source":"@site/blog/2018-01-16-captains-cookbok-part-1/index.mdx","title":"Captain\'s Cookbook: Project setup","description":"A basic introduction to getting started with Cap\'N Proto.","date":"2018-01-16T12:00:00.000Z","tags":[],"readingTime":7.555,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/01/captains-cookbook-part-1","title":"Captain\'s Cookbook: Project setup","date":"2018-01-16T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731201811000,"prevItem":{"title":"Captain\'s Cookbook: Practical usage","permalink":"/2018/01/captains-cookbook-part-2"},"nextItem":{"title":"PCA audio compression","permalink":"/2016/11/pca-audio-compression"}}')}}]); \ No newline at end of file diff --git a/assets/js/f2eb9457.6fac4cda.js b/assets/js/f2eb9457.6fac4cda.js new file mode 100644 index 0000000..743341a --- /dev/null +++ b/assets/js/f2eb9457.6fac4cda.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8863"],{4174:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return u},default:function(){return p},frontMatter:function(){return a},metadata:function(){return r},toc:function(){return l}});var r=n(7133),o=n(5893),i=n(65);let a={slug:"2016/01/complaining-about-the-weather",title:"Complaining about the weather",date:new Date("2016-01-01T12:00:00.000Z"),authors:["bspeice"],tags:[]},u=void 0,c={authorsImageUrls:[void 0]},l=[];function s(e){let t={p:"p",...(0,i.a)(),...e.components};return(0,o.jsx)(t.p,{children:"Figuring out whether people should be complaining about the recent weather in North Carolina."})}function p(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(s,{...e})}):s(e)}},65:function(e,t,n){n.d(t,{Z:function(){return u},a:function(){return a}});var r=n(7294);let o={},i=r.createContext(o);function a(e){let t=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function u(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(i.Provider,{value:t},e.children)}},7133:function(e){e.exports=JSON.parse('{"permalink":"/2016/01/complaining-about-the-weather","source":"@site/blog/2016-01-01-complaining-about-the-weather/index.mdx","title":"Complaining about the weather","description":"Figuring out whether people should be complaining about the recent weather in North Carolina.","date":"2016-01-01T12:00:00.000Z","tags":[],"readingTime":7.475,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/01/complaining-about-the-weather","title":"Complaining about the weather","date":"2016-01-01T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"},"nextItem":{"title":"Testing Cramer","permalink":"/2015/12/testing-cramer"}}')}}]); \ No newline at end of file diff --git a/assets/js/f8fee0f7.90b05631.js b/assets/js/f8fee0f7.90b05631.js new file mode 100644 index 0000000..76ddb66 --- /dev/null +++ b/assets/js/f8fee0f7.90b05631.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["4760"],{3643:function(e,t,n){n.r(t),n.d(t,{assets:function(){return c},contentTitle:function(){return o},default:function(){return d},frontMatter:function(){return r},metadata:function(){return a},toc:function(){return l}});var a=n(4111),s=n(5893),i=n(65);let r={slug:"2018/10/case-study-optimization",title:"A case study in heaptrack",date:new Date("2018-10-08T12:00:00.000Z"),authors:["bspeice"],tags:[]},o=void 0,c={authorsImageUrls:[void 0]},l=[{value:"Curiosity",id:"curiosity",level:2},{value:"Turning on the System Allocator",id:"turning-on-the-system-allocator",level:2},{value:"Running heaptrack",id:"running-heaptrack",level:2},{value:"Reading Flamegraphs",id:"reading-flamegraphs",level:2},{value:"Optimizing dtparse",id:"optimizing-dtparse",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",h2:"h2",hr:"hr",img:"img",p:"p",pre:"pre",strong:"strong",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"I remember early in my career someone joking that:"}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsx)(t.p,{children:"Programmers have it too easy these days. They should learn to develop in low memory environments\nand be more efficient."}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["...though it's not like the first code I wrote was for a\n",(0,s.jsx)(t.a,{href:"https://web.archive.org/web/20180924060530/https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-se",children:"graphing calculator"}),"\npacking a whole 24KB of RAM."]}),"\n",(0,s.jsxs)(t.p,{children:["But the principle remains: be efficient with the resources you have, because\n",(0,s.jsx)(t.a,{href:"http://exo-blog.blogspot.com/2007/09/what-intel-giveth-microsoft-taketh-away.html",children:"what Intel giveth, Microsoft taketh away"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["My professional work is focused on this kind of efficiency; low-latency financial markets demand\nthat you understand at a deep level ",(0,s.jsx)(t.em,{children:"exactly"})," what your code is doing. As I continue experimenting\nwith Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's\nflexibility for the times I pretend to have a garbage collector, and flexibility for the times that\nI really care about how memory is used."]}),"\n",(0,s.jsx)(t.p,{children:"This post is a (small) case study in how I went from the former to the latter. And ultimately, it's\nintended to be a starting toolkit to empower analysis of your own code."}),"\n",(0,s.jsx)(t.h2,{id:"curiosity",children:"Curiosity"}),"\n",(0,s.jsxs)(t.p,{children:["When I first started building the ",(0,s.jsx)(t.a,{href:"https://crates.io/crates/dtparse",children:"dtparse"})," crate, my intention was to mirror as closely as possible\nthe equivalent ",(0,s.jsx)(t.a,{href:"https://github.com/dateutil/dateutil",children:"Python library"}),". Python, as you may know, is garbage collected. Very\nrarely is memory usage considered in Python, and I likewise wasn't paying too much attention when\n",(0,s.jsx)(t.code,{children:"dtparse"})," was first being built."]}),"\n",(0,s.jsxs)(t.p,{children:["This lackadaisical approach to memory works well enough, and I'm not planning on making ",(0,s.jsx)(t.code,{children:"dtparse"}),'\nhyper-efficient. But every so often, I\'ve wondered: "what exactly is going on in memory?" With the\nadvent of Rust 1.28 and the\n',(0,s.jsx)(t.a,{href:"https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html",children:"Global Allocator trait"}),", I had a really\ngreat idea: ",(0,s.jsx)(t.em,{children:"build a custom allocator that allows you to track your own allocations."})," That way, you\ncan do things like writing tests for both correct results and correct memory usage. I gave it a\n",(0,s.jsx)(t.a,{href:"https://crates.io/crates/qadapt",children:"shot"}),", but learned very quickly: ",(0,s.jsx)(t.strong,{children:"never write your own allocator"}),'. It went from "fun\nweekend project" to "I have literally no idea what my computer is doing" at breakneck speed.']}),"\n",(0,s.jsxs)(t.p,{children:["Instead, I'll highlight a separate path I took to make sense of my memory usage: ",(0,s.jsx)(t.a,{href:"https://github.com/KDE/heaptrack",children:"heaptrack"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"turning-on-the-system-allocator",children:"Turning on the System Allocator"}),"\n",(0,s.jsxs)(t.p,{children:["This is the hardest part of the post. Because Rust uses\n",(0,s.jsx)(t.a,{href:"https://github.com/rust-lang/rust/pull/27400#issue-41256384",children:"its own allocator"})," by default,\n",(0,s.jsx)(t.code,{children:"heaptrack"})," is unable to properly record unmodified Rust code. To remedy this, we'll make use of the\n",(0,s.jsx)(t.code,{children:"#[global_allocator]"})," attribute."]}),"\n",(0,s.jsxs)(t.p,{children:["Specifically, in ",(0,s.jsx)(t.code,{children:"lib.rs"})," or ",(0,s.jsx)(t.code,{children:"main.rs"}),", add this:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-rust",children:"use std::alloc::System;\n\n#[global_allocator]\nstatic GLOBAL: System = System;\n"})}),"\n",(0,s.jsx)(t.p,{children:"...and that's it. Everything else comes essentially for free."}),"\n",(0,s.jsx)(t.h2,{id:"running-heaptrack",children:"Running heaptrack"}),"\n",(0,s.jsxs)(t.p,{children:["Assuming you've installed heaptrack ",(0,s.jsx)("small",{children:"(Homebrew in Mac, package manager\nin Linux, ??? in Windows)"}),", all that's left is to fire up your application:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"heaptrack my_application\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It's that easy. After the program finishes, you'll see a file in your local directory with a name\nlike ",(0,s.jsx)(t.code,{children:"heaptrack.my_appplication.XXXX.gz"}),". If you load that up in ",(0,s.jsx)(t.code,{children:"heaptrack_gui"}),", you'll see\nsomething like this:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"heaptrack",src:n(7029).Z+"",width:"1312",height:"320"})}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsx)(t.p,{children:"And even these pretty colors:"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"pretty colors",src:n(4078).Z+"",width:"1284",height:"715"})}),"\n",(0,s.jsx)(t.h2,{id:"reading-flamegraphs",children:"Reading Flamegraphs"}),"\n",(0,s.jsxs)(t.p,{children:["To make sense of our memory usage, we're going to focus on that last picture - it's called a\n",(0,s.jsx)(t.a,{href:"http://www.brendangregg.com/flamegraphs.html",children:'"flamegraph"'}),". These charts are typically used to\nshow how much time your program spends executing each function, but they're used here to show how\nmuch memory was allocated during those functions instead."]}),"\n",(0,s.jsxs)(t.p,{children:["For example, we can see that all executions happened during the ",(0,s.jsx)(t.code,{children:"main"})," function:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"allocations in main",src:n(9206).Z+"",width:"654",height:"343"})}),"\n",(0,s.jsxs)(t.p,{children:["...and within that, all allocations happened during ",(0,s.jsx)(t.code,{children:"dtparse::parse"}),":"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"allocations in dtparse",src:n(8644).Z+"",width:"654",height:"315"})}),"\n",(0,s.jsxs)(t.p,{children:["...and within ",(0,s.jsx)(t.em,{children:"that"}),", allocations happened in two different places:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"allocations in parseinfo",src:n(6746).Z+"",width:"654",height:"372"})}),"\n",(0,s.jsxs)(t.p,{children:["Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue:\n",(0,s.jsxs)(t.strong,{children:["what the heck is the ",(0,s.jsx)(t.code,{children:"Default"})," thing doing?"]})]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"pretty colors",src:n(8308).Z+"",width:"1284",height:"715"})}),"\n",(0,s.jsx)(t.h2,{id:"optimizing-dtparse",children:"Optimizing dtparse"}),"\n",(0,s.jsxs)(t.p,{children:["See, I knew that there were some allocations during calls to ",(0,s.jsx)(t.code,{children:"dtparse::parse"}),", but I was totally\nwrong about where the bulk of allocations occurred in my program. Let me post the code and see if\nyou can spot the mistake:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-rust",children:"/// Main entry point for using `dtparse`.\npub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> {\n let res = Parser::default().parse(\n timestr, None, None, false, false,\n None, false,\n &HashMap::new(),\n )?;\n\n Ok((res.0, res.1))\n}\n"})}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/blob/4d7c5dd99572823fa4a390b483c38ab020a2172f/src/lib.rs#L1286",children:"dtparse"})}),"\n"]}),"\n",(0,s.jsx)(t.hr,{}),"\n",(0,s.jsxs)(t.p,{children:["Because ",(0,s.jsx)(t.code,{children:"Parser::parse"})," requires a mutable reference to itself, I have to create a new\n",(0,s.jsx)(t.code,{children:"Parser::default"})," every time it receives a string. This is excessive! We'd rather have an immutable\nparser that can be re-used, and avoid allocating memory in the first place."]}),"\n",(0,s.jsxs)(t.p,{children:["Armed with that information, I put some time in to\n",(0,s.jsx)(t.a,{href:"https://github.com/bspeice/dtparse/commit/741afa34517d6bc1155713bbc5d66905fea13fad#diff-b4aea3e418ccdb71239b96952d9cddb6",children:"make the parser immutable"}),".\nNow that I can re-use the same parser over and over, the allocations disappear:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"allocations cleaned up",src:n(809).Z+"",width:"1272",height:"712"})}),"\n",(0,s.jsxs)(t.p,{children:["In total, we went from requiring 2 MB of memory in\n",(0,s.jsx)(t.a,{href:"https://crates.io/crates/dtparse/1.0.2",children:"version 1.0.2"}),":"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"memory before",src:n(3346).Z+"",width:"717",height:"116"})}),"\n",(0,s.jsxs)(t.p,{children:["All the way down to 300KB in ",(0,s.jsx)(t.a,{href:"https://crates.io/crates/dtparse/1.0.3",children:"version 1.0.3"}),":"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"memory after",src:n(9838).Z+"",width:"739",height:"123"})}),"\n",(0,s.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(t.p,{children:"In the end, you don't need to write a custom allocator to be efficient with memory, great tools\nalready exist to help you understand what your program is doing."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Use them."})}),"\n",(0,s.jsxs)(t.p,{children:["Given that ",(0,s.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Moore%27s_law",children:"Moore's Law"})," is\n",(0,s.jsx)(t.a,{href:"https://www.technologyreview.com/s/601441/moores-law-is-dead-now-what/",children:"dead"}),", we've all got to do\nour part to take back what Microsoft stole."]})]})}function d(e={}){let{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},7029:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-before-11fba190f97831448cc539ebb32fa579.png"},9838:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-closeup-after-967bc4596c480bcc9e8410b0a7a64a00.png"},3346:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-closeup-12ae3897c033ccb3684a88dd45592e14.png"},8644:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-dtparse-colorized-e6caf224f50df2dd56981f5b02970325.png"},809:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-flamegraph-after-cedc4c3519313f5af538364165e92c34.png"},8308:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-flamegraph-default-26cc411d387f58f50cb548f8e81df1a1.png"},4078:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-flamegraph-5094664fa79faaf2664b38505c15ac1f.png"},9206:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-main-colorized-cfe5d7d345d32cfc1a0f297580619718.png"},6746:function(e,t,n){n.d(t,{Z:function(){return a}});let a=n.p+"assets/images/heaptrack-parseinfo-colorized-a1898beaf28a3997ac86810f872539b7.png"},65:function(e,t,n){n.d(t,{Z:function(){return o},a:function(){return r}});var a=n(7294);let s={},i=a.createContext(s);function r(e){let t=a.useContext(i);return a.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:t},e.children)}},4111:function(e){e.exports=JSON.parse('{"permalink":"/2018/10/case-study-optimization","source":"@site/blog/2018-10-08-case-study-optimization/index.mdx","title":"A case study in heaptrack","description":"I remember early in my career someone joking that:","date":"2018-10-08T12:00:00.000Z","tags":[],"readingTime":4.26,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2018/10/case-study-optimization","title":"A case study in heaptrack","date":"2018-10-08T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731189722000,"prevItem":{"title":"More \\"what companies really mean\\"","permalink":"/2018/12/what-small-business-really-means"},"nextItem":{"title":"Isomorphic desktop apps with Rust","permalink":"/2018/09/isomorphic-apps"}}')}}]); \ No newline at end of file diff --git a/assets/js/fd7e7e63.09b6c6e9.js b/assets/js/fd7e7e63.09b6c6e9.js new file mode 100644 index 0000000..a8aa480 --- /dev/null +++ b/assets/js/fd7e7e63.09b6c6e9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["8868"],{1450:function(s,e,a){a.r(e),a.d(e,{assets:function(){return r},contentTitle:function(){return m},default:function(){return d},frontMatter:function(){return t},metadata:function(){return n},toc:function(){return c}});var n=a(4892),l=a(5893),i=a(65);let t={slug:"2016/02/guaranteed-money-maker",title:"Guaranteed money maker",date:new Date("2016-02-03T12:00:00.000Z"),authors:["bspeice"],tags:[]},m=void 0,r={authorsImageUrls:[void 0]},c=[{value:"Applying the Martingale Strategy",id:"applying-the-martingale-strategy",level:2},{value:"Interesting Implications",id:"interesting-implications",level:2},{value:"Running the simulation",id:"running-the-simulation",level:2},{value:"Summary",id:"summary",level:2},{value:"Side note and disclaimer",id:"side-note-and-disclaimer",level:3}];function h(s){let e={a:"a",annotation:"annotation",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",mstyle:"mstyle",msub:"msub",msubsup:"msubsup",mtable:"mtable",mtd:"mtd",mtr:"mtr",munderover:"munderover",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,i.a)(),...s.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(e.p,{children:"Developing an investment strategy based on the Martingale betting strategy"}),"\n",(0,l.jsx)(e.p,{children:"If you can see into the future, that is."}),"\n",(0,l.jsxs)(e.p,{children:["My previous class in Stochastic Calculus covered a lot of interesting topics, and the important one for today is the ",(0,l.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Gambler's_ruin",children:"Gambler's Ruin"})," problem. If you're interested in some of the theory behind it, also make sure to check out ",(0,l.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Random_walk",children:"random walks"}),". The important bit is that we studied the ",(0,l.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Martingale_%28betting_system%29",children:"Martingale Betting Strategy"}),", which describes for us a ",(0,l.jsx)(e.strong,{children:"guaranteed way"})," to ",(0,l.jsx)("small",{children:"eventually"})," make money."]}),"\n",(0,l.jsx)(e.p,{children:"The strategy goes like this: You are going to toss a fair coin with a friend. If you guess heads or tails correctly, you get back double the money you bet. If you guess incorrectly, you lose money. How should you bet?"}),"\n",(0,l.jsx)(e.p,{children:"The correct answer is that you should double your bet each time you lose. Then when you finally win, you'll be guaranteed to make back everything you lost and then $1 extra! Consider the scenario:"}),"\n",(0,l.jsxs)(e.ol,{children:["\n",(0,l.jsx)(e.li,{children:"You bet $1, and guess incorrectly. You're 1 dollar in the hole."}),"\n",(0,l.jsx)(e.li,{children:"You bet $2, and guess incorrectly. You're 3 dollars in the hole now."}),"\n",(0,l.jsx)(e.li,{children:"You bet $4, and guess incorrectly. You're 7 dollars in the hole."}),"\n",(0,l.jsxs)(e.li,{children:["You bet $8, and guess correctly! You now get back those 8 dollars you bet, plus 8 extra for winning, for a ",(0,l.jsx)(e.strong,{children:"total profit of one dollar"}),"!"]}),"\n"]}),"\n",(0,l.jsx)(e.p,{children:"Mathematically, we can prove that as long as you have unlimited money to bet, you are guaranteed to make money."}),"\n",(0,l.jsx)(e.h2,{id:"applying-the-martingale-strategy",children:"Applying the Martingale Strategy"}),"\n",(0,l.jsx)(e.p,{children:"But we're all realistic people, and once you start talking about \"unlimited money\" eyebrows should be raised. Even still, this is an interesting strategy to investigate, and I want to apply it to the stock market. As long as we can guarantee there's a single day in which the stock goes up, we should be able to make money right? The question is just how much we have to invest to guarantee this."}),"\n",(0,l.jsx)(e.p,{children:"Now it's time for the math. We'll use the following definitions:"}),"\n",(0,l.jsxs)(e.ul,{children:["\n",(0,l.jsxs)(e.li,{children:[(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"o_i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.5806em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]})," = the share price at the opening of day ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsx)(e.mi,{children:"i"})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.6595em"}}),(0,l.jsx)(e.span,{className:"mord mathnormal",children:"i"})]})})]})]}),"\n",(0,l.jsxs)(e.li,{children:[(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"i"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"c_i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.5806em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]})," = the share price at the close of day ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsx)(e.mi,{children:"i"})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.6595em"}}),(0,l.jsx)(e.span,{className:"mord mathnormal",children:"i"})]})})]})]}),"\n",(0,l.jsxs)(e.li,{children:[(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"d_i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]})," = the amount of money we want to invest at the beginning of day ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsx)(e.mi,{children:"i"})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"i"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.6595em"}}),(0,l.jsx)(e.span,{className:"mord mathnormal",children:"i"})]})})]})]}),"\n"]}),"\n",(0,l.jsxs)(e.p,{children:["With those definitions in place, I'd like to present the formula that is ",(0,l.jsx)(e.strong,{children:"guaranteed to make you money"}),". I call it ",(0,l.jsx)(e.em,{children:"Bradlee's Investment Formula"}),":"]}),"\n",(0,l.jsx)(e.p,{children:(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msubsup,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.mo,{children:">"}),(0,l.jsxs)(e.msubsup,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"c_n \\sum_{i=1}^n \\frac{d_i}{o_i} > \\sum_{i=1}^{n} d_i"})]})})}),(0,l.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"1.3413em",verticalAlign:"-0.4451em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mop",children:[(0,l.jsx)(e.span,{className:"mop op-symbol small-op",style:{position:"relative",top:"0em"},children:"\u2211"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"0.8043em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.4003em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.2029em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.2997em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"0.8962em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3281em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"0em",marginRight:"0.0714em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,l.jsx)(e.span,{})})})]})})]})})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.4101em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3281em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"0em",marginRight:"0.0714em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,l.jsx)(e.span,{})})})]})})]})})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.4451em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mrel",children:">"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"1.104em",verticalAlign:"-0.2997em"}}),(0,l.jsxs)(e.span,{className:"mop",children:[(0,l.jsx)(e.span,{className:"mop op-symbol small-op",style:{position:"relative",top:"0em"},children:"\u2211"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"0.8043em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.4003em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.2029em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.2997em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]})]})}),"\n",(0,l.jsx)(e.p,{children:"It might not look like much, but if you can manage to make it so that this formula holds true, you will be guaranteed to make money. The intuition behind the formula is this: The closing share price times the number of shares you have purchased ends up greater than the amount of money you invested."}),"\n",(0,l.jsxs)(e.p,{children:["That is, on day ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsx)(e.mi,{children:"n"})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"n"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,l.jsx)(e.span,{className:"mord mathnormal",children:"n"})]})})]}),", ",(0,l.jsx)("small",{children:"if you know what the closing price will be"})," you can set up the amount of money you invest that day to ",(0,l.jsx)(e.strong,{children:"guarantee you make money"}),". I'll even teach you to figure out how much money that is! Take a look:"]}),"\n",(0,l.jsx)(e.span,{className:"katex-display",children:(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",display:"block",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsxs)(e.mtable,{rowspacing:"0.25em",columnalign:"right left",columnspacing:"0em",children:[(0,l.jsxs)(e.mtr,{children:[(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.munderover,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"n"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsx)(e.mn,{children:"1"})]})]}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.mo,{children:"+"}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]})]})]})})}),(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mrow,{}),(0,l.jsx)(e.mo,{children:">"}),(0,l.jsxs)(e.munderover,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"n"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsx)(e.mn,{children:"1"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsx)(e.mo,{children:"+"}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})]})})})]}),(0,l.jsxs)(e.mtr,{children:[(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]})]}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})]})})}),(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mrow,{}),(0,l.jsx)(e.mo,{children:">"}),(0,l.jsxs)(e.munderover,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"n"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsx)(e.mn,{children:"1"})]})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:"("}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:")"})]})})})]}),(0,l.jsxs)(e.mtr,{children:[(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:"("}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:")"})]})})}),(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mrow,{}),(0,l.jsx)(e.mo,{children:">"}),(0,l.jsxs)(e.munderover,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"n"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsx)(e.mn,{children:"1"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:"("}),(0,l.jsx)(e.mn,{children:"1"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:")"})]})})})]}),(0,l.jsxs)(e.mtr,{children:[(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})})}),(0,l.jsx)(e.mtd,{children:(0,l.jsx)(e.mstyle,{scriptlevel:"0",displaystyle:"true",children:(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mrow,{}),(0,l.jsx)(e.mo,{children:">"}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"c"}),(0,l.jsx)(e.mi,{children:"n"})]}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"n"})]})]})]}),(0,l.jsxs)(e.munderover,{children:[(0,l.jsx)(e.mo,{children:"\u2211"}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"i"}),(0,l.jsx)(e.mo,{children:"="}),(0,l.jsx)(e.mn,{children:"1"})]}),(0,l.jsxs)(e.mrow,{children:[(0,l.jsx)(e.mi,{children:"n"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsx)(e.mn,{children:"1"})]})]}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"i"})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:"("}),(0,l.jsx)(e.mn,{children:"1"}),(0,l.jsx)(e.mo,{children:"\u2212"}),(0,l.jsxs)(e.mfrac,{children:[(0,l.jsx)(e.mn,{children:"1"}),(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"o"}),(0,l.jsx)(e.mi,{children:"i"})]})]}),(0,l.jsx)(e.mo,{stretchy:"false",children:")"})]})})})]})]}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\begin{align*}\nc_n \\sum_{i=1}^{n-1} \\frac{d_i}{o_i} + \\frac{c_nd_n}{o_n} &> \\sum_{i=1}^{n-1}d_i + d_n\\\\\n\\frac{c_nd_n}{o_n} - d_n &> \\sum_{i=1}^{n-1}(d_i - \\frac{c_nd_i}{o_i})\\\\\nd_n (\\frac{c_n - o_n}{o_n}) &> \\sum_{i=1}^{n-1} d_i(1 - \\frac{c_n}{o_i})\\\\\nd_n &> \\frac{o_n}{c_n - o_n} \\sum_{i=1}^{n-1} d_i(1 - \\frac{1}{o_i})\n\\end{align*}"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"13.5151em",verticalAlign:"-6.5076em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mtable",children:[(0,l.jsx)(e.span,{className:"col-align-r",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"7.0076em"},children:[(0,l.jsxs)(e.span,{style:{top:"-9.0076em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsx)(e.span,{className:"mop op-limits",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.8011em"},children:[(0,l.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{children:(0,l.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,l.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,l.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.3714em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"+"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.3714em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]}),(0,l.jsxs)(e.span,{style:{top:"-5.6288em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.3714em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]}),(0,l.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mopen",children:"("}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.2603em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mclose",children:")"})]})]}),(0,l.jsxs)(e.span,{style:{top:"1.1288em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"6.5076em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"col-align-l",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"7.0076em"},children:[(0,l.jsxs)(e.span,{style:{top:"-9.0076em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mrel",children:">"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mop op-limits",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.8011em"},children:[(0,l.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{children:(0,l.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,l.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,l.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"+"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]}),(0,l.jsxs)(e.span,{style:{top:"-5.6288em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mrel",children:">"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mop op-limits",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.8011em"},children:[(0,l.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{children:(0,l.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,l.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,l.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mopen",children:"("}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.3714em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mclose",children:")"})]})]}),(0,l.jsxs)(e.span,{style:{top:"-2.25em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mrel",children:">"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mop op-limits",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.8011em"},children:[(0,l.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{children:(0,l.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,l.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,l.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mopen",children:"("}),(0,l.jsx)(e.span,{className:"mord",children:"1"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.1076em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mclose",children:")"})]})]}),(0,l.jsxs)(e.span,{style:{top:"1.1288em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.8011em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsx)(e.span,{className:"mrel",children:">"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.1076em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"c"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsx)(e.span,{className:"mop op-limits",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.8011em"},children:[(0,l.jsxs)(e.span,{style:{top:"-1.8723em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"}),(0,l.jsx)(e.span,{className:"mrel mtight",children:"="}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{children:(0,l.jsx)(e.span,{className:"mop op-symbol large-op",children:"\u2211"})})]}),(0,l.jsxs)(e.span,{style:{top:"-4.3em",marginLeft:"0em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3.05em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsxs)(e.span,{className:"mord mtight",children:[(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"}),(0,l.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mord mtight",children:"1"})]})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"1.2777em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.1667em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]}),(0,l.jsx)(e.span,{className:"mopen",children:"("}),(0,l.jsx)(e.span,{className:"mord",children:"1"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,l.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,l.jsx)(e.span,{className:"mfrac",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsxs)(e.span,{className:"vlist",style:{height:"1.3214em"},children:[(0,l.jsxs)(e.span,{style:{top:"-2.314em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"o"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.3117em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"i"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]}),(0,l.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,l.jsxs)(e.span,{style:{top:"-3.677em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,l.jsx)(e.span,{className:"mord",children:(0,l.jsx)(e.span,{className:"mord",children:"1"})})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.836em"},children:(0,l.jsx)(e.span,{})})})]})}),(0,l.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,l.jsx)(e.span,{className:"mclose",children:")"})]})]})]}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"6.5076em"},children:(0,l.jsx)(e.span,{})})})]})})]})})]})})]})}),"\n",(0,l.jsxs)(e.p,{children:["If you invest exactly ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"d_n"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]})," that day, you'll break even. But if you can make sure the money you invest is greater than that quantity on the right ",(0,l.jsx)("small",{children:"(which requires that you have a crystal ball tell you the stock's closing price)"})," you are ",(0,l.jsx)(e.strong,{children:"guaranteed to make money!"})]}),"\n",(0,l.jsx)(e.h2,{id:"interesting-implications",children:"Interesting Implications"}),"\n",(0,l.jsx)(e.p,{children:"On a more serious note though, the formula above tells us a couple of interesting things:"}),"\n",(0,l.jsxs)(e.ol,{children:["\n",(0,l.jsx)(e.li,{children:"It's impossible to make money without the closing price at some point being greater than the opening price (or vice-versa if you are short selling) - there is no amount of money you can invest that will turn things in your favor."}),"\n",(0,l.jsx)(e.li,{children:"Close prices of the past aren't important if you're concerned about the bottom line. While chart technicians use price history to make judgment calls, in the end, the closing price on anything other than the last day is irrelevant."}),"\n",(0,l.jsx)(e.li,{children:"It's possible to make money as long as there is a single day where the closing price is greater than the opening price! You might have to invest a lot to do so, but it's possible."}),"\n",(0,l.jsx)(e.li,{children:"You must make a prediction about where the stock will close at if you want to know how much to invest. That is, we can set up our investment for the day to make money if the stock goes up 1%, but if it only goes up .5% we'll still lose money."}),"\n",(0,l.jsxs)(e.li,{children:["It's possible the winning move is to scale back your position. Consider the scenario:","\n",(0,l.jsxs)(e.ul,{children:["\n",(0,l.jsx)(e.li,{children:"You invest money and the stock closes down the day .5%"}),"\n",(0,l.jsx)(e.li,{children:"You invest tomorrow expecting the stock to go up 1%"}),"\n",(0,l.jsx)(e.li,{children:"The winning investment to break even (assuming a 1% increase) is to scale back the position, since the shares you purchased at the beginning would then be profitable"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,l.jsx)(e.h2,{id:"running-the-simulation",children:"Running the simulation"}),"\n",(0,l.jsx)(e.p,{children:"So now that we've defined our investment formula,we need to tweak a couple things in order to make an investment strategy we can actually work with. There are two issues we need to address:"}),"\n",(0,l.jsxs)(e.ol,{children:["\n",(0,l.jsxs)(e.li,{children:["The formula only tells us how much to invest if we want to break even (",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"d_n"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]}),"). If we actually want to turn a profit, we need to invest more than that, which we will refer to as the ",(0,l.jsx)(e.strong,{children:"bias"}),"."]}),"\n",(0,l.jsxs)(e.li,{children:["The formula assumes we know what the closing price will be on any given day. If we don't know this, we can still invest assuming the stock price will close at a level we choose. If the price doesn't meet this objective, we try again tomorrow! This predetermined closing price will be referred to as the ",(0,l.jsx)(e.strong,{children:"expectation"}),"."]}),"\n"]}),"\n",(0,l.jsxs)(e.p,{children:["Now that we've defined our ",(0,l.jsx)(e.em,{children:"bias"})," and ",(0,l.jsx)(e.em,{children:"expectation"}),", we can actually build a strategy we can simulate. Much like the martingale strategy told you to bet twice your previous bet in order to make money, we've designed a system that tells us how much to bet in order to make money as well."]}),"\n",(0,l.jsx)(e.p,{children:"Now, let's get to the code!"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-julia",children:"using Quandl\napi_key = \"\"\ndaily_investment = function(current_open, current_close, purchase_history, open_history)\n # We're not going to safeguard against divide by 0 - that's the user's responsibility\n t1 = current_close / current_open - 1\n t2 = sum(purchase_history - purchase_history*current_close ./ open_history)\n return t2 / t1\nend;\n"})}),"\n",(0,l.jsx)(e.p,{children:"And let's code a way to run simulations quickly:"}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-julia",children:'is_profitable = function(current_price, purchase_history, open_history)\n shares = sum(purchase_history ./ open_history)\n return current_price*shares > sum(purchase_history)\nend\n\nsimulate = function(name, start, init, expected, bias)\n ticker_info = quandlget(name, from=start, api_key=api_key)\n open_vals = ticker_info["Open"].values\n close_vals = ticker_info["Close"].values\n invested = [init]\n \n # The simulation stops once we\'ve made a profit\n day = 1\n profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||\n is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])\n while !profitable\n expected_close = open_vals[day+1] * expected\n todays_purchase = daily_investment(open_vals[day+1], expected_close, invested, open_vals[1:day])\n invested = [invested; todays_purchase + bias]\n # expected_profit = expected_close * sum(invested ./ open_vals[1:length(invested)]) - sum(invested)\n day += 1\n profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) ||\n is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)])\n end\n \n shares = sum(invested ./ open_vals[1:length(invested)])\n max_profit = max(close_vals[day], open_vals[day+1])\n profit = shares * max_profit - sum(invested)\n return (invested, profit)\nend\n\nsim_summary = function(investments, profit)\n leverages = [sum(investments[1:i]) for i=1:length(investments)]\n max_leverage = maximum(leverages) / investments[1]\n println("Max leverage: $(max_leverage)")\n println("Days invested: $(length(investments))")\n println("Profit: $profit")\nend;\n'})}),"\n",(0,l.jsx)(e.p,{children:"Now, let's get some data and run a simulation! Our first test:"}),"\n",(0,l.jsxs)(e.ul,{children:["\n",(0,l.jsxs)(e.li,{children:["We'll invest 100 dollars in LMT, and expect that the stock will close up 1% every day. We'll invest ",(0,l.jsxs)(e.span,{className:"katex",children:[(0,l.jsx)(e.span,{className:"katex-mathml",children:(0,l.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,l.jsxs)(e.semantics,{children:[(0,l.jsx)(e.mrow,{children:(0,l.jsxs)(e.msub,{children:[(0,l.jsx)(e.mi,{children:"d"}),(0,l.jsx)(e.mi,{children:"n"})]})}),(0,l.jsx)(e.annotation,{encoding:"application/x-tex",children:"d_n"})]})})}),(0,l.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,l.jsxs)(e.span,{className:"base",children:[(0,l.jsx)(e.span,{className:"strut",style:{height:"0.8444em",verticalAlign:"-0.15em"}}),(0,l.jsxs)(e.span,{className:"mord",children:[(0,l.jsx)(e.span,{className:"mord mathnormal",children:"d"}),(0,l.jsx)(e.span,{className:"msupsub",children:(0,l.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,l.jsxs)(e.span,{className:"vlist-r",children:[(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,l.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"0em",marginRight:"0.05em"},children:[(0,l.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,l.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,l.jsx)(e.span,{className:"mord mathnormal mtight",children:"n"})})]})}),(0,l.jsx)(e.span,{className:"vlist-s",children:"\u200B"})]}),(0,l.jsx)(e.span,{className:"vlist-r",children:(0,l.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,l.jsx)(e.span,{})})})]})})]})]})})]})," + 10 dollars every day that we haven't turned a profit, and end the simulation once we've made a profit."]}),"\n"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-julia",children:'investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.01, 10)\nsim_summary(investments, profit)\n'})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{children:" Max leverage: 5.590373200042106\n Days invested: 5\n Profit: 0.6894803101560001\n"})}),"\n",(0,l.jsx)(e.p,{children:"The result: We need to invest 5.6x our initial position over a period of 5 days to make approximately .69\xa2"}),"\n",(0,l.jsxs)(e.ul,{children:["\n",(0,l.jsx)(e.li,{children:"Now let's try the same thing, but we'll assume the stock closes up 2% instead."}),"\n"]}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{className:"language-julia",children:'investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.02, 10)\nsim_summary(investments, profit)\n'})}),"\n",(0,l.jsx)(e.pre,{children:(0,l.jsx)(e.code,{children:" Max leverage: 1.854949900247809\n Days invested: 25\n Profit: 0.08304813163696423\n"})}),"\n",(0,l.jsx)(e.p,{children:"In this example, we only get up to a 1.85x leveraged position, but it takes 25 days to turn a profit of 8\xa2"}),"\n",(0,l.jsx)(e.h2,{id:"summary",children:"Summary"}),"\n",(0,l.jsx)(e.p,{children:"We've defined an investment strategy that can tell us how much to invest when we know what the closing position of a stock will be. We can tweak the strategy to actually make money, but plenty of work needs to be done so that we can optimize the money invested."}),"\n",(0,l.jsx)(e.p,{children:"In the next post I'm going to post more information about some backtests and strategy tests on this strategy (unless of course this experiment actually produces a significant profit potential, and then I'm keeping it for myself)."}),"\n",(0,l.jsx)(e.h3,{id:"side-note-and-disclaimer",children:"Side note and disclaimer"}),"\n",(0,l.jsx)(e.p,{children:"The claims made in this presentation about being able to guarantee making money are intended as a joke and do not constitute investment advice of any sort."})]})}function d(s={}){let{wrapper:e}={...(0,i.a)(),...s.components};return e?(0,l.jsx)(e,{...s,children:(0,l.jsx)(h,{...s})}):h(s)}},65:function(s,e,a){a.d(e,{Z:function(){return m},a:function(){return t}});var n=a(7294);let l={},i=n.createContext(l);function t(s){let e=n.useContext(i);return n.useMemo(function(){return"function"==typeof s?s(e):{...e,...s}},[e,s])}function m(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(l):s.components||l:t(s.components),n.createElement(i.Provider,{value:e},s.children)}},4892:function(s){s.exports=JSON.parse('{"permalink":"/2016/02/guaranteed-money-maker","source":"@site/blog/2016-02-03-guaranteed-money-maker/index.mdx","title":"Guaranteed money maker","description":"Developing an investment strategy based on the Martingale betting strategy","date":"2016-02-03T12:00:00.000Z","tags":[],"readingTime":7.695,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2016/02/guaranteed-money-maker","title":"Guaranteed money maker","date":"2016-02-03T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1730678252000,"prevItem":{"title":"Profitability using the investment formula","permalink":"/2016/02/profitability-using-the-investment-formula"},"nextItem":{"title":"Cloudy in Seattle","permalink":"/2016/01/cloudy-in-seattle"}}')}}]); \ No newline at end of file diff --git a/assets/js/main.62ce6156.js b/assets/js/main.62ce6156.js new file mode 100644 index 0000000..8307623 --- /dev/null +++ b/assets/js/main.62ce6156.js @@ -0,0 +1,36 @@ +(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["6909"],{3601:function(e,t,n){"use strict";n.r(t)},7686:function(e,t,n){"use strict";n.r(t)},1381:function(e,t,n){"use strict";n.d(t,{PP:()=>N,Ep:()=>f,lX:()=>x,q_:()=>C,ob:()=>p});var r=n("6019");function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r<a;n+=1,r+=1)e[n]=e[r];e.pop()}let i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],l=e&&a(e),s=t&&a(t),u=l||s;if(e&&a(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var c=i[i.length-1];n="."===c||".."===c||""===c}else n=!1;for(var d=0,f=i.length;f>=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!u)for(;d--;d)i.unshift("..");u&&""!==i[0]&&(!i[0]||!a(i[0]))&&i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};var l=n("1835");function s(e){return"/"===e.charAt(0)?e:"/"+e}function u(e){return"/"===e.charAt(0)?e.substr(1):e}function c(e,t){var n,r;return(n=e,r=t,0===n.toLowerCase().indexOf(r.toLowerCase())&&-1!=="/?#".indexOf(n.charAt(r.length)))?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function p(e,t,n,a){var o,l,s,u,c,d;if("string"==typeof e){;s="",u="",-1!==(c=(l=e||"/").indexOf("#"))&&(u=l.substr(c),l=l.substr(0,c)),-1!==(d=l.indexOf("?"))&&(s=l.substr(d),l=l.substr(0,d)),(o={pathname:l,search:"?"===s?"":s,hash:"#"===u?"":u}).state=t}else void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t);try{o.pathname=decodeURI(o.pathname)}catch(e){if(e instanceof URIError)throw URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.');throw e}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:!o.pathname&&(o.pathname="/"),o}function h(){var e=null,t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter(function(e){return e!==r})}},notifyListeners:function(){for(var e=arguments.length,n=Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach(function(e){return e.apply(void 0,n)})}}}var g=!!("undefined"!=typeof window&&window.document&&window.document.createElement);function m(e,t){t(window.confirm(e))}var y="popstate",b="hashchange";function v(){try{return window.history.state||{}}catch(e){return{}}}function x(e){void 0===e&&(e={}),g||(0,l.Z)(!1);var t,n=window.history;var a=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=-1!==window.navigator.userAgent.indexOf("Trident"),i=e,u=i.forceRefresh,x=void 0!==u&&u,w=i.getUserConfirmation,k=void 0===w?m:w,S=i.keyLength,E=void 0===S?6:S,_=e.basename?d(s(e.basename)):"";function C(e){var t=e||{},n=t.key,r=t.state,a=window.location,o=a.pathname+a.search+a.hash;return _&&(o=c(o,_)),p(o,r,n)}function T(){return Math.random().toString(36).substr(2,E)}var N=h();function A(e){(0,r.Z)(B,e),B.length=n.length,N.notifyListeners(B.location,B.action)}function O(e){if(!(void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")))L(C(e.state))}function P(){L(C(v()))}var j=!1;function L(e){j?(j=!1,A()):N.confirmTransitionTo(e,"POP",k,function(t){t?A({action:"POP",location:e}):function(e){var t=B.location,n=I.indexOf(t.key);-1===n&&(n=0);var r=I.indexOf(e.key);-1===r&&(r=0);var a=n-r;a&&(j=!0,F(a))}(e)})}var R=C(v()),I=[R.key];function M(e){return _+f(e)}function F(e){n.go(e)}var D=0;function z(e){1===(D+=e)&&1===e?(window.addEventListener(y,O),o&&window.addEventListener(b,P)):0===D&&(window.removeEventListener(y,O),o&&window.removeEventListener(b,P))}var $=!1,B={length:n.length,action:"POP",location:R,createHref:M,push:function(e,t){var r="PUSH",o=p(e,t,T(),B.location);N.confirmTransitionTo(o,r,k,function(e){if(e){var t=M(o),i=o.key,l=o.state;if(a){if(n.pushState({key:i,state:l},null,t),x)window.location.href=t;else{var s=I.indexOf(B.location.key),u=I.slice(0,s+1);u.push(o.key),I=u,A({action:r,location:o})}}else window.location.href=t}})},replace:function(e,t){var r="REPLACE",o=p(e,t,T(),B.location);N.confirmTransitionTo(o,r,k,function(e){if(e){var t=M(o),i=o.key,l=o.state;if(a){if(n.replaceState({key:i,state:l},null,t),x)window.location.replace(t);else{var s=I.indexOf(B.location.key);-1!==s&&(I[s]=o.key),A({action:r,location:o})}}else window.location.replace(t)}})},go:F,goBack:function(){F(-1)},goForward:function(){F(1)},block:function(e){void 0===e&&(e=!1);var t=N.setPrompt(e);return!$&&(z(1),$=!0),function(){return $&&($=!1,z(-1)),t()}},listen:function(e){var t=N.appendListener(e);return z(1),function(){z(-1),t()}}};return B}var w="hashchange",k={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+u(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:u,decodePath:s},slash:{encodePath:s,decodePath:s}};function S(e){var t=e.indexOf("#");return -1===t?e:e.slice(0,t)}function E(){var e=window.location.href,t=e.indexOf("#");return -1===t?"":e.substring(t+1)}function _(e){window.location.replace(S(window.location.href)+"#"+e)}function C(e){void 0===e&&(e={}),g||(0,l.Z)(!1);var t=window.history;window.navigator.userAgent.indexOf("Firefox");var n=e,a=n.getUserConfirmation,o=void 0===a?m:a,i=n.hashType,u=e.basename?d(s(e.basename)):"",y=k[void 0===i?"slash":i],b=y.encodePath,v=y.decodePath;function x(){var e=v(E());return u&&(e=c(e,u)),p(e)}var C=h();function T(e){(0,r.Z)(z,e),z.length=t.length,C.notifyListeners(z.location,z.action)}var N=!1,A=null;function O(){var e=E(),t=b(e);if(e!==t)_(t);else{var n,r,a=x(),i=z.location;if(!N&&(n=i,r=a,n.pathname===r.pathname&&n.search===r.search&&n.hash===r.hash)||A===f(a))return;A=null,function(e){N?(N=!1,T()):C.confirmTransitionTo(e,"POP",o,function(t){t?T({action:"POP",location:e}):function(e){var t=z.location,n=R.lastIndexOf(f(t));-1===n&&(n=0);var r=R.lastIndexOf(f(e));-1===r&&(r=0);var a=n-r;a&&(N=!0,I(a))}(e)})}(a)}}var P=E(),j=b(P);P!==j&&_(j);var L=x(),R=[f(L)];function I(e){t.go(e)}var M=0;function F(e){1===(M+=e)&&1===e?window.addEventListener(w,O):0===M&&window.removeEventListener(w,O)}var D=!1,z={length:t.length,action:"POP",location:L,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=S(window.location.href)),n+"#"+b(u+f(e))},push:function(e,t){var n="PUSH",r=p(e,void 0,void 0,z.location);C.confirmTransitionTo(r,n,o,function(e){if(e){var t=f(r),a=b(u+t);if(E()!==a){A=t,o=a,window.location.hash=o;var o,i=R.lastIndexOf(f(z.location)),l=R.slice(0,i+1);l.push(t),R=l,T({action:n,location:r})}else T()}})},replace:function(e,t){var n="REPLACE",r=p(e,void 0,void 0,z.location);C.confirmTransitionTo(r,n,o,function(e){if(e){var t=f(r),a=b(u+t);E()!==a&&(A=t,_(a));var o=R.indexOf(f(z.location));-1!==o&&(R[o]=t),T({action:n,location:r})}})},go:I,goBack:function(){I(-1)},goForward:function(){I(1)},block:function(e){void 0===e&&(e=!1);var t=C.setPrompt(e);return!D&&(F(1),D=!0),function(){return D&&(D=!1,F(-1)),t()}},listen:function(e){var t=C.appendListener(e);return F(1),function(){F(-1),t()}}};return z}function T(e,t,n){return Math.min(Math.max(e,t),n)}function N(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,a=t.initialEntries,o=void 0===a?["/"]:a,i=t.initialIndex,l=t.keyLength,s=void 0===l?6:l,u=h();function c(e){(0,r.Z)(b,e),b.length=b.entries.length,u.notifyListeners(b.location,b.action)}function d(){return Math.random().toString(36).substr(2,s)}var g=T(void 0===i?0:i,0,o.length-1),m=o.map(function(e){return"string"==typeof e?p(e,void 0,d()):p(e,void 0,e.key||d())});function y(e){var t=T(b.index+e,0,b.entries.length-1),r=b.entries[t];u.confirmTransitionTo(r,"POP",n,function(e){e?c({action:"POP",location:r,index:t}):c()})}var b={length:m.length,action:"POP",location:m[g],index:g,entries:m,createHref:f,push:function(e,t){var r="PUSH",a=p(e,t,d(),b.location);u.confirmTransitionTo(a,r,n,function(e){if(e){var t=b.index+1,n=b.entries.slice(0);n.length>t?n.splice(t,n.length-t,a):n.push(a),c({action:r,location:a,index:t,entries:n})}})},replace:function(e,t){var r="REPLACE",a=p(e,t,d(),b.location);u.confirmTransitionTo(a,r,n,function(e){e&&(b.entries[b.index]=a,c({action:r,location:a}))})},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=b.index+e;return t>=0&&t<b.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return b}},8679:function(e,t,n){"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function s(e){return r.isMemo(e)?i:l[e.$$typeof]||a}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var u=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var a=p(n);a&&a!==h&&e(t,a,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=s(t),g=s(n),m=0;m<i.length;++m){var y=i[m];if(!o[y]&&!(r&&r[y])&&!(g&&g[y])&&!(l&&l[y])){var b=f(n,y);try{u(t,y,b)}catch(e){}}}}return t}},1143:function(e){"use strict";e.exports=function(e,t,n,r,a,o,i,l){if(!e){var s;if(void 0===t)s=Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,a,o,i,l],c=0;(s=Error(t.replace(/%s/g,function(){return u[c++]}))).name="Invariant Violation"}throw s.framesToPop=1,s}}},5826:function(e){e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},813:function(e){var t,n;t=0,n=function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")},n=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},a=function(){function e(n){var r=!(arguments.length>1)||void 0===arguments[1]||arguments[1],a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=a,this.iframesTimeout=o}return n(e,[{key:"getContexts",value:function(){var e=void 0,t=[];return void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):e=Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:e=[],e.forEach(function(e){var n=t.filter(function(t){return t.contains(e)}).length>0;-1===t.indexOf(e)&&!n&&t.push(e)}),t}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var a=e.contentWindow;if(r=a.document,!a||!r)throw Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,a=!1,o=null,i=function i(){if(!a){a=!0,clearTimeout(o);try{!r.isIframeBlank(e)&&(e.removeEventListener("load",i),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",i),o=setTimeout(i,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector("html"),function(){!--r&&t()})},function(e){!e&&t()})}},{key:"forEachIframe",value:function(t,n,r){var a=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},i=t.querySelectorAll("iframe"),l=i.length,s=0;i=Array.prototype.slice.call(i);var u=function(){--l<=0&&o(s)};!l&&u(),i.forEach(function(t){e.matches(t,a.exclude)?u():a.onIframeReady(t,function(e){n(t)&&(s++,r(e)),u()},u)})}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode(),n=void 0;return n=null===t?e.nextNode():e.nextNode()&&e.nextNode(),{prevNode:t,node:n}}},{key:"checkIframeFilter",value:function(e,t,n,r){var a=!1,o=!1;return(r.forEach(function(e,t){e.val===n&&(a=t,o=e.handled)}),this.compareNodeIframe(e,t,n))?(!1!==a||o?!1!==a&&!o&&(r[a].handled=!0):r.push({val:n,handled:!0}),!0):(!1===a&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var a=this;e.forEach(function(e){!e.handled&&a.getIframeContents(e.val,function(e){a.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:"iterateThroughNodes",value:function(e,t,n,r,a){var o,i=this,l=this.createIterator(t,e,r),s=[],u=[],c=void 0,d=void 0;for(;d=(o=i.getIteratorNode(l)).prevNode,c=o.node;)this.iframes&&this.forEachIframe(t,function(e){return i.checkIframeFilter(c,d,e,s)},function(t){i.createInstanceOnIframe(t).forEachNode(e,function(e){return u.push(e)},r)}),u.push(c);u.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(s,e,n,r),a()}},{key:"forEachNode",value:function(e,t,n){var r=this,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},o=this.getContexts(),i=o.length;!i&&a(),o.forEach(function(o){var l=function(){r.iterateThroughNodes(e,o,t,n,function(){--i<=0&&a()})};r.iframes?r.waitForIframes(o,l):l()})}}],[{key:"matches",value:function(e,t){var n=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(!n)return!1;var r=!1;return("string"==typeof t?[t]:t).every(function(t){return!n.call(e,t)||(r=!0,!1)}),r}}]),e}(),o=function(){function o(e){t(this,o),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(o,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;if(!!this.opt.debug)(void 0===r?"undefined":e(r))==="object"&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e)}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var a in t)if(t.hasOwnProperty(a)){var o=t[a],i="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(a):this.escapeStr(a),l="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o);""!==i&&""!==l&&(e=e.replace(RegExp("("+this.escapeStr(i)+"|"+this.escapeStr(l)+")","gm"+n),r+("("+this.processSynomyms(i))+"|"+this.processSynomyms(l)+")"+r))}return e}},{key:"processSynomyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,function(e){return"\\"===e.charAt(0)?"?":"\x01"})).replace(/(?:\\)*\*/g,function(e){return"\\"===e.charAt(0)?"*":"\x02"})}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"})}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["a\xe0\xe1\u1EA3\xe3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xe2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xe4\xe5\u0101\u0105","A\xc0\xc1\u1EA2\xc3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xc2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xc4\xc5\u0100\u0104","c\xe7\u0107\u010D","C\xc7\u0106\u010C","d\u0111\u010F","D\u0110\u010E","e\xe8\xe9\u1EBB\u1EBD\u1EB9\xea\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xeb\u011B\u0113\u0119","E\xc8\xc9\u1EBA\u1EBC\u1EB8\xca\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xcb\u011A\u0112\u0118","i\xec\xed\u1EC9\u0129\u1ECB\xee\xef\u012B","I\xcc\xcd\u1EC8\u0128\u1ECA\xce\xcf\u012A","l\u0142","L\u0141","n\xf1\u0148\u0144","N\xd1\u0147\u0143","o\xf2\xf3\u1ECF\xf5\u1ECD\xf4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xf6\xf8\u014D","O\xd2\xd3\u1ECE\xd5\u1ECC\xd4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xd6\xd8\u014C","r\u0159","R\u0158","s\u0161\u015B\u0219\u015F","S\u0160\u015A\u0218\u015E","t\u0165\u021B\u0163","T\u0164\u021A\u0162","u\xf9\xfa\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xfb\xfc\u016F\u016B","U\xd9\xda\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xdb\xdc\u016E\u016A","y\xfd\u1EF3\u1EF7\u1EF9\u1EF5\xff","Y\xdd\u1EF2\u1EF6\u1EF8\u1EF4\u0178","z\u017E\u017C\u017A","Z\u017D\u017B\u0179"]:["a\xe0\xe1\u1EA3\xe3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xe2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xe4\xe5\u0101\u0105A\xc0\xc1\u1EA2\xc3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xc2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xc4\xc5\u0100\u0104","c\xe7\u0107\u010DC\xc7\u0106\u010C","d\u0111\u010FD\u0110\u010E","e\xe8\xe9\u1EBB\u1EBD\u1EB9\xea\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xeb\u011B\u0113\u0119E\xc8\xc9\u1EBA\u1EBC\u1EB8\xca\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xcb\u011A\u0112\u0118","i\xec\xed\u1EC9\u0129\u1ECB\xee\xef\u012BI\xcc\xcd\u1EC8\u0128\u1ECA\xce\xcf\u012A","l\u0142L\u0141","n\xf1\u0148\u0144N\xd1\u0147\u0143","o\xf2\xf3\u1ECF\xf5\u1ECD\xf4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xf6\xf8\u014DO\xd2\xd3\u1ECE\xd5\u1ECC\xd4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xd6\xd8\u014C","r\u0159R\u0158","s\u0161\u015B\u0219\u015FS\u0160\u015A\u0218\u015E","t\u0165\u021B\u0163T\u0164\u021A\u0162","u\xf9\xfa\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xfb\xfc\u016F\u016BU\xd9\xda\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xdb\xdc\u016E\u016A","y\xfd\u1EF3\u1EF7\u1EF9\u1EF5\xffY\xdd\u1EF2\u1EF6\u1EF8\u1EF4\u0178","z\u017E\u017C\u017AZ\u017D\u017B\u0179"],r=[];return e.split("").forEach(function(a){n.every(function(n){if(-1!==n.indexOf(a)){if(r.indexOf(n)>-1)return!1;e=e.replace(RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0})}),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gmi,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n=this.opt.accuracy,r="string"==typeof n?n:n.value,a="string"==typeof n?[]:n.limiters,o="";switch(a.forEach(function(e){o+="|"+t.escapeStr(e)}),r){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(o="\\s"+(o||this.escapeStr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xa1\xbf")))+"]*"+e+"[^"+o+"]*)";case"exactly":return"(^|\\s"+o+")("+e+")(?=$|\\s"+o+")"}}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(" ").forEach(function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)}):e.trim()&&-1===n.indexOf(e)&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort(function(e,t){return e.start-t.start}).forEach(function(e){var a=t.callNoMatchOnInvalidRanges(e,r),o=a.start,i=a.end;a.valid&&(e.start=o,e.length=i-o,n.push(e),r=i)}),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,a=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?a=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:a}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,a=!0,o=n.length,i=t-o,l=parseInt(e.start,10)-i;return(r=(l=l>o?o:l)+parseInt(e.length,10))>o&&(r=o,this.log("End range automatically set to the max value of "+o)),l<0||r-l<0||l>o||r>o?(a=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(l,r).replace(/\s+/g,"")&&(a=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:l,end:r,valid:a}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:"matchesExclude",value:function(e){return a.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",a=e.splitText(t),o=a.splitText(n-t),i=document.createElement(r);return i.setAttribute("data-markjs","true"),this.opt.className&&i.setAttribute("class",this.opt.className),i.textContent=a.textContent,a.parentNode.replaceChild(i,a),o}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,a){var o=this;e.nodes.every(function(i,l){var s=e.nodes[l+1];if(void 0===s||s.start>t){if(!r(i.node))return!1;var u=t-i.start,c=(n>i.end?i.end:n)-i.start,d=e.value.substr(0,i.start),f=e.value.substr(c+i.start);if(i.node=o.wrapRangeInTextNode(i.node,u,c),e.value=d+f,e.nodes.forEach(function(t,n){n>=l&&(e.nodes[n].start>0&&n!==l&&(e.nodes[n].start-=c),e.nodes[n].end-=c)}),n-=c,a(i.node.previousSibling,i.start),!(n>i.end))return!1;t=i.end}return!0})}},{key:"wrapMatches",value:function(e,t,n,r,a){var o=this,i=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var a=void 0;null!==(a=e.exec(t.textContent))&&""!==a[i];){if(!!n(a[i],t)){var l=a.index;if(0!==i)for(var s=1;s<i;s++)l+=a[s].length;r((t=o.wrapRangeInTextNode(t,l,l+a[i].length)).previousSibling),e.lastIndex=0}}}),a()})}},{key:"wrapMatchesAcrossElements",value:function(e,t,n,r,a){var o=this,i=0===t?0:t+1;this.getTextNodes(function(t){for(var l=void 0;null!==(l=e.exec(t.value))&&""!==l[i];){var s=l.index;if(0!==i)for(var u=1;u<i;u++)s+=l[u].length;var c=s+l[i].length;o.wrapRangeInMappedTextNode(t,s,c,function(e){return n(l[i],e)},function(t,n){e.lastIndex=n,r(t)})}a()})}},{key:"wrapRangeFromIndex",value:function(e,t,n,r){var a=this;this.getTextNodes(function(o){var i=o.value.length;e.forEach(function(e,r){var l=a.checkWhitespaceRanges(e,i,o.value),s=l.start,u=l.end;l.valid&&a.wrapRangeInMappedTextNode(o,s,u,function(n){return t(n,e,o.value.substring(s,u),r)},function(t){n(t,e)})}),r()})}},{key:"unwrapMatches",value:function(e){for(var t=e.parentNode,n=document.createDocumentFragment();e.firstChild;)n.appendChild(e.removeChild(e.firstChild));t.replaceChild(n,e),this.ie?this.normalizeTextNode(t):t.normalize()}},{key:"normalizeTextNode",value:function(e){if(!!e){if(3===e.nodeType)for(;e.nextSibling&&3===e.nextSibling.nodeType;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}},{key:"markRegExp",value:function(e,t){var n=this;this.opt=t,this.log('Searching with expression "'+e+'"');var r=0,a="wrapMatches";this.opt.acrossElements&&(a="wrapMatchesAcrossElements"),this[a](e,this.opt.ignoreGroups,function(e,t){return n.opt.filter(t,e,r)},function(e){r++,n.opt.each(e)},function(){0===r&&n.opt.noMatch(e),n.opt.done(r)})}},{key:"mark",value:function(e,t){var n=this;this.opt=t;var r=0,a="wrapMatches",o=this.getSeparatedKeywords("string"==typeof e?[e]:e),i=o.keywords,l=o.length,s=this.opt.caseSensitive?"":"i";this.opt.acrossElements&&(a="wrapMatchesAcrossElements"),0===l?this.opt.done(r):!function e(t){var o=RegExp(n.createRegExp(t),"gm"+s),u=0;n.log('Searching with expression "'+o+'"'),n[a](o,1,function(e,a){return n.opt.filter(a,t,r,u)},function(e){u++,r++,n.opt.each(e)},function(){0===u&&n.opt.noMatch(t),i[l-1]===t?n.opt.done(r):e(i[i.indexOf(t)+1])})}(i[0])}},{key:"markRanges",value:function(e,t){var n=this;this.opt=t;var r=0,a=this.checkRanges(e);a&&a.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(a)),this.wrapRangeFromIndex(a,function(e,t,r,a){return n.opt.filter(e,t,r,a)},function(e,t){r++,n.opt.each(e,t)},function(){n.opt.done(r)})):this.opt.done(r)}},{key:"unmark",value:function(e){var t=this;this.opt=e;var n=this.opt.element?this.opt.element:"*";n+="[data-markjs]",this.opt.className&&(n+="."+this.opt.className),this.log('Removal selector "'+n+'"'),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,function(e){t.unwrapMatches(e)},function(e){var r=a.matches(e,n),o=t.matchesExclude(e);return!r||o?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}},{key:"opt",set:function(e){this._opt=r({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:function(){},noMatch:function(){},filter:function(){return!0},done:function(){},debug:!1,log:window.console},e)},get:function(){return this._opt}},{key:"iterator",get:function(){return new a(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}}]),o}();return function(e){var t=this,n=new o(e);return this.mark=function(e,r){return n.mark(e,r),t},this.markRegExp=function(e,r){return n.markRegExp(e,r),t},this.markRanges=function(e,r){return n.markRanges(e,r),t},this.unmark=function(e){return n.unmark(e),t},this}},e.exports=n()},4865:function(e){var t,n;t=0,n=function(){var e,t,n,r={};r.version="0.2.0";var a=r.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function o(e,t,n){return e<t?t:e>n?n:e}function i(e){return(-1+e)*100}r.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(a[t]=n);return this},r.status=null,r.set=function(e){var t=r.isStarted();e=o(e,a.minimum,1),r.status=1===e?null:e;var n=r.render(!t),i=n.querySelector(a.barSelector),u=a.speed,c=a.easing;return n.offsetWidth,l(function(t){""===a.positionUsing&&(a.positionUsing=r.getPositioningCSS()),s(i,function(e,t,n){var r;if("translate3d"===a.positionUsing)r={transform:"translate3d("+(-1+e)*100+"%,0,0)"};else if("translate"===a.positionUsing)r={transform:"translate("+(-1+e)*100+"%,0)"};else r={"margin-left":(-1+e)*100+"%"};return r.transition="all "+t+"ms "+n,r}(e,u,c)),1===e?(s(n,{transition:"none",opacity:1}),n.offsetWidth,setTimeout(function(){s(n,{transition:"all "+u+"ms linear",opacity:0}),setTimeout(function(){r.remove(),t()},u)},u)):setTimeout(t,u)}),this},r.isStarted=function(){return"number"==typeof r.status},r.start=function(){!r.status&&r.set(0);var e=function(){setTimeout(function(){r.status&&(r.trickle(),e())},a.trickleSpeed)};return a.trickle&&e(),this},r.done=function(e){return e||r.status?r.inc(.3+.5*Math.random()).set(1):this},r.inc=function(e){var t=r.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),r.set(t)):r.start()},r.trickle=function(){return r.inc(Math.random()*a.trickleRate)},e=0,t=0,r.promise=function(n){return n&&"resolved"!==n.state()?(0===t&&r.start(),e++,t++,n.always(function(){0==--t?(e=0,r.done()):r.set((e-t)/e)}),this):this},r.render=function(e){if(r.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=a.template;var n,o=t.querySelector(a.barSelector),i=e?"-100":function(e){return(-1+e)*100}(r.status||0),l=document.querySelector(a.parent);return s(o,{transition:"all 0 linear",transform:"translate3d("+i+"%,0,0)"}),!a.showSpinner&&(n=t.querySelector(a.spinnerSelector))&&p(n),l!=document.body&&c(l,"nprogress-custom-parent"),l.appendChild(t),t},r.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(a.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},r.isRendered=function(){return!!document.getElementById("nprogress")},r.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective" in e?"translate3d":t+"Transform" in e?"translate":"margin"};var l=(n=[],function(e){n.push(e),1==n.length&&!function e(){var t=n.shift();t&&t(e)}()}),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(n,r,a){r=function(n){return t[n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(e,t){return t.toUpperCase()})]||(t[n]=function(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}(n))}(r),n.style[r]=a}return function(e,t){var r,a,o=arguments;if(2==o.length)for(r in t)void 0!==(a=t[r])&&t.hasOwnProperty(r)&&n(e,r,a);else n(e,o[1],o[2])}}();function u(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=f(e),r=n+t;!u(n,t)&&(e.className=r.substring(1))}function d(e,t){var n,r=f(e);u(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return r},"function"==typeof define&&define.amd?define(n):e.exports=n()},4779:function(e,t,n){var r=n(5826);e.exports=f,e.exports.parse=o,e.exports.compile=function(e,t){return l(o(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=d;var a=RegExp("(\\\\.)|([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))","g");function o(e,t){for(var n,r=[],o=0,i=0,l="",u=t&&t.delimiter||"/";null!=(n=a.exec(e));){var c=n[0],d=n[1],f=n.index;if(l+=e.slice(i,f),i=f+c.length,d){l+=d[1];continue}var p=e[i],h=n[2],g=n[3],m=n[4],y=n[5],b=n[6],v=n[7];l&&(r.push(l),l="");var x=null!=h&&null!=p&&p!==h,w="+"===b||"*"===b,k="?"===b||"*"===b,S=h||u,E=m||y,_=h||("string"==typeof r[r.length-1]?r[r.length-1]:"");r.push({name:g||o++,prefix:h||"",delimiter:S,optional:k,repeat:w,partial:x,asterisk:!!v,pattern:E?function(e){return e.replace(/([=!:$\/()])/g,"\\$1")}(E):v?".*":function(e,t){return!t||t.indexOf(e)>-1?"[^"+s(e)+"]+?":s(t)+"|(?:(?!"+s(t)+")[^"+s(e)+"])+?"}(S,_)})}return i<e.length&&(l+=e.substr(i)),l&&r.push(l),r}function i(e){return encodeURI(e).replace(/[\/?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}function l(e,t){for(var n=Array(e.length),a=0;a<e.length;a++)"object"==typeof e[a]&&(n[a]=RegExp("^(?:"+e[a].pattern+")$",c(t)));return function(t,a){for(var o="",l=t||{},s=(a||{}).pretty?i:encodeURIComponent,u=0;u<e.length;u++){var c,d=e[u];if("string"==typeof d){o+=d;continue}var f=l[d.name];if(null==f){if(d.optional){d.partial&&(o+=d.prefix);continue}throw TypeError('Expected "'+d.name+'" to be defined')}if(r(f)){if(!d.repeat)throw TypeError('Expected "'+d.name+'" to not repeat, but received `'+JSON.stringify(f)+"`");if(0===f.length){if(d.optional)continue;throw TypeError('Expected "'+d.name+'" to not be empty')}for(var p=0;p<f.length;p++){if(c=s(f[p]),!n[u].test(c))throw TypeError('Expected all "'+d.name+'" to match "'+d.pattern+'", but received `'+JSON.stringify(c)+"`");o+=(0===p?d.prefix:d.delimiter)+c}continue}if(c=d.asterisk?encodeURI(f).replace(/[?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}):s(f),!n[u].test(c))throw TypeError('Expected "'+d.name+'" to match "'+d.pattern+'", but received "'+c+'"');o+=d.prefix+c}return o}}function s(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function u(e,t){return e.keys=t,e}function c(e){return e&&e.sensitive?"":"i"}function d(e,t,n){!r(t)&&(n=t||n,t=[]);for(var a,o,i=(n=n||{}).strict,l=!1!==n.end,u="",d=0;d<e.length;d++){var f=e[d];if("string"==typeof f)u+=s(f);else{var p=s(f.prefix),h="(?:"+f.pattern+")";t.push(f),f.repeat&&(h+="(?:"+p+h+")*"),u+=h=f.optional?f.partial?p+"("+h+")?":"(?:"+p+"("+h+"))?":p+"("+h+")"}}var g=s(n.delimiter||"/"),m=u.slice(-g.length)===g;return!i&&(u=(m?u.slice(0,-g.length):u)+"(?:"+g+"(?=$))?"),l?u+="$":u+=i&&m?"":"(?="+g+"|$)",a=RegExp("^"+u,c(n)),o=t,a.keys=o,a}function f(e,t,n){var a,i,l;if(!r(t)&&(n=t||n,t=[]),n=n||{},e instanceof RegExp)return function(e,t){var n,r,a=e.source.match(/\((?!\?)/g);if(a)for(var o=0;o<a.length;o++)t.push({name:o,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return n=e,r=t,n.keys=r,n}(e,t);if(r(e))return function(e,t,n){for(var r,a,o=[],i=0;i<e.length;i++)o.push(f(e[i],t,n).source);return r=RegExp("(?:"+o.join("|")+")",c(n)),a=t,r.keys=a,r}(e,t,n);return a=e,i=t,d(o(a,l=n),i,l)}},7874:function(){!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i<a.length;i++)o[a[i]]=e.languages.bash[a[i]];e.languages.sh=e.languages.bash,e.languages.shell=e.languages.bash}(Prism)},2503:function(){var e,t,n,r;e=Prism,t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,r={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}},e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[r,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:r.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:r.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":r,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:r.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:r.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})},6543:function(){Prism.languages.julia={comment:{pattern:/(^|[^\\])(?:#=(?:[^#=]|=(?!#)|#(?!=)|#=(?:[^#=]|=(?!#)|#(?!=))*=#)*=#|#.*)/,lookbehind:!0},regex:{pattern:/r"(?:\\.|[^"\\\r\n])*"[imsx]{0,4}/,greedy:!0},string:{pattern:/"""[\s\S]+?"""|(?:\b\w+)?"(?:\\.|[^"\\\r\n])*"|`(?:[^\\`\r\n]|\\.)*`/,greedy:!0},char:{pattern:/(^|[^\w'])'(?:\\[^\r\n][^'\r\n]*|[^\\\r\n])'/,lookbehind:!0,greedy:!0},keyword:/\b(?:abstract|baremodule|begin|bitstype|break|catch|ccall|const|continue|do|else|elseif|end|export|finally|for|function|global|if|immutable|import|importall|in|let|local|macro|module|print|println|quote|return|struct|try|type|typealias|using|while)\b/,boolean:/\b(?:false|true)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[box])?(?:[\da-f]+(?:_[\da-f]+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[efp][+-]?\d+(?:_\d+)*)?j?/i,operator:/&&|\|\||[-+*^%÷⊻&$\\]=?|\/[\/=]?|!=?=?|\|[=>]?|<(?:<=?|[=:|])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥'√∛]/,punctuation:/::?|[{}[\]();,.?]/,constant:/\b(?:(?:Inf|NaN)(?:16|32|64)?|im|pi)\b|[πℯ]/}},6854:function(){!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,function(e){if("function"==typeof o&&!o(e))return e;for(var a,l=i.length;-1!==n.code.indexOf(a=t(r,l));)++l;return i[l]=e,a}),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&!!n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(l){for(var s=0;s<l.length&&!(a>=o.length);s++){;var u=l[s];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=o[a],d=n.tokenStack[c],f="string"==typeof u?u:u.content,p=t(r,c),h=f.indexOf(p);if(h>-1){++a;var g=f.substring(0,h),m=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),y=f.substring(h+p.length),b=[];g&&b.push.apply(b,i([g])),b.push(m),y&&b.push.apply(b,i([y])),"string"==typeof u?l.splice.apply(l,[s,1].concat(b)):u.content=b}}else u.content&&i(u.content)}return l}(n.tokens)}}}})}(Prism)},2353:function(){Prism.languages.nasm={comment:/;.*$/m,string:/(["'`])(?:\\.|(?!\1)[^\\\r\n])*\1/,label:{pattern:/(^\s*)[A-Za-z._?$][\w.?$@~#]*:/m,lookbehind:!0,alias:"function"},keyword:[/\[?BITS (?:16|32|64)\]?/,{pattern:/(^\s*)section\s*[a-z.]+:?/im,lookbehind:!0},/(?:extern|global)[^;\r\n]*/i,/(?:CPU|DEFAULT|FLOAT).*$/m],register:{pattern:/\b(?:st\d|[xyz]mm\d\d?|[cdt]r\d|r\d\d?[bwd]?|[er]?[abcd]x|[abcd][hl]|[er]?(?:bp|di|si|sp)|[cdefgs]s)\b/i,alias:"variable"},number:/(?:\b|(?=\$))(?:0[hx](?:\.[\da-f]+|[\da-f]+(?:\.[\da-f]+)?)(?:p[+-]?\d+)?|\d[\da-f]+[hx]|\$\d[\da-f]*|0[oq][0-7]+|[0-7]+[oq]|0[by][01]+|[01]+[by]|0[dt]\d+|(?:\d+(?:\.\d+)?|\.\d+)(?:\.?e[+-]?\d+)?[dt]?)\b/i,operator:/[\[\]*+\-\/%<>=&|$!]/}},8092:function(e,t,n){var r={"./prism-bash":"7874","./prism-java":"2503","./prism-julia":"6543","./prism-nasm":"2353"};function a(e){return n(o(e))}function o(e){if(!n.o(r,e)){var t=Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id="8092"},2703:function(e,t,n){"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var l=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:function(e,t,n){e.exports=n(2703)()},414:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:function(e,t,n){"use strict";var r,a,o,i,l,s,u=n(7294),c=n(3840);function d(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var f=new Set,p={};function h(e,t){g(e,t),g(e+"Capture",t)}function g(e,t){for(p[e]=t,e=0;e<t.length;e++)f.add(t[e])}var m=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),y=Object.prototype.hasOwnProperty,b=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,v={},x={};function w(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var k={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){k[e]=new w(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];k[t]=new w(t,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){k[e]=new w(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){k[e]=new w(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){k[e]=new w(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){k[e]=new w(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){k[e]=new w(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){k[e]=new w(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){k[e]=new w(e,5,!1,e.toLowerCase(),null,!1,!1)});var S=/[\-:]([a-z])/g;function E(e){return e[1].toUpperCase()}function _(e,t,n,r){var a,o=k.hasOwnProperty(t)?k[t]:null;if(null!==o?0!==o.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1]){;(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":if(r)return!1;if(null!==n)return!n.acceptsBooleans;return"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e;default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1})(t,n,o,r)&&(n=null),r||null===o?(a=t,(!!y.call(x,a)||!y.call(v,a)&&(b.test(a)?x[a]=!0:(v[a]=!0,!1)))&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n))):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&"":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n)))}}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(S,E);k[t]=new w(t,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(S,E);k[t]=new w(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(S,E);k[t]=new w(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){k[e]=new w(e,1,!1,e.toLowerCase(),null,!1,!1)}),k.xlinkHref=new w("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){k[e]=new w(e,1,!1,e.toLowerCase(),null,!0,!0)});var C=u.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,T=Symbol.for("react.element"),N=Symbol.for("react.portal"),A=Symbol.for("react.fragment"),O=Symbol.for("react.strict_mode"),P=Symbol.for("react.profiler"),j=Symbol.for("react.provider"),L=Symbol.for("react.context"),R=Symbol.for("react.forward_ref"),I=Symbol.for("react.suspense"),M=Symbol.for("react.suspense_list"),F=Symbol.for("react.memo"),D=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var z=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var $=Symbol.iterator;function B(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=$&&e[$]||e["@@iterator"])?e:null}var U,H=Object.assign;function Z(e){if(void 0===U)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);U=t&&t[1]||""}return"\n"+U+e}var W=!1;function V(e,t){if(!e||W)return"";W=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t){if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(e){var r=e}Reflect.construct(e,[],t)}else{try{t.call()}catch(e){r=e}e.call(t.prototype)}}else{try{throw Error()}catch(e){r=e}e()}}catch(t){if(t&&r&&"string"==typeof t.stack){for(var a=t.stack.split("\n"),o=r.stack.split("\n"),i=a.length-1,l=o.length-1;1<=i&&0<=l&&a[i]!==o[l];)l--;for(;1<=i&&0<=l;i--,l--)if(a[i]!==o[l]){if(1!==i||1!==l)do if(i--,0>--l||a[i]!==o[l]){var s="\n"+a[i].replace(" at new "," at ");return e.displayName&&s.includes("<anonymous>")&&(s=s.replace("<anonymous>",e.displayName)),s}while(1<=i&&0<=l);break}}}finally{W=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?Z(e):""}function G(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function q(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function Y(e){e._valueTracker||(e._valueTracker=function(e){var t=q(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var a=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(e){r=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function K(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=q(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function Q(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function X(e,t){var n=t.checked;return H({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function J(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=G(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function ee(e,t){null!=(t=t.checked)&&_(e,"checked",t,!1)}function et(e,t){ee(e,t);var n=G(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r){e.removeAttribute("value");return}t.hasOwnProperty("value")?er(e,t.type,n):t.hasOwnProperty("defaultValue")&&er(e,t.type,G(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function en(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function er(e,t,n){("number"!==t||Q(e.ownerDocument)!==e)&&(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var ea=Array.isArray;function eo(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a<n.length;a++)t["$"+n[a]]=!0;for(n=0;n<e.length;n++)a=t.hasOwnProperty("$"+e[n].value),e[n].selected!==a&&(e[n].selected=a),a&&r&&(e[n].defaultSelected=!0)}else{for(a=0,n=""+G(n),t=null;a<e.length;a++){if(e[a].value===n){e[a].selected=!0,r&&(e[a].defaultSelected=!0);return}null!==t||e[a].disabled||(t=e[a])}null!==t&&(t.selected=!0)}}function ei(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(d(91));return H({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function el(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(d(92));if(ea(n)){if(1<n.length)throw Error(d(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:G(n)}}function es(e,t){var n=G(t.value),r=G(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function eu(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}function ec(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function ed(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?ec(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var ef,ep,eh=(ef=function(e,t){if("http://www.w3.org/2000/svg"!==e.namespaceURI||"innerHTML"in e)e.innerHTML=t;else{for((ep=ep||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=ep.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction(function(){return ef(e,t,n,r)})}:ef);function eg(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType){n.nodeValue=t;return}}e.textContent=t}var em={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ey=["Webkit","ms","Moz","O"];function eb(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||em.hasOwnProperty(e)&&em[e]?(""+t).trim():t+"px"}function ev(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),a=eb(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}Object.keys(em).forEach(function(e){ey.forEach(function(t){em[t=t+e.charAt(0).toUpperCase()+e.substring(1)]=em[e]})});var ex=H({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ew(e,t){if(t){if(ex[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(d(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(d(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(d(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(d(62))}}function ek(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var eS=null;function eE(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var e_=null,eC=null,eT=null;function eN(e){if(e=rM(e)){if("function"!=typeof e_)throw Error(d(280));var t=e.stateNode;t&&(t=rD(t),e_(e.stateNode,e.type,t))}}function eA(e){eC?eT?eT.push(e):eT=[e]:eC=e}function eO(){if(eC){var e=eC,t=eT;if(eT=eC=null,eN(e),t)for(e=0;e<t.length;e++)eN(t[e])}}function eP(e,t){return e(t)}function ej(){}var eL=!1;function eR(e,t,n){if(eL)return e(t,n);eL=!0;try{return eP(e,t,n)}finally{eL=!1,(null!==eC||null!==eT)&&(ej(),eO())}}function eI(e,t){var n=e.stateNode;if(null===n)return null;var r=rD(n);if(null===r)return null;switch(n=r[t],t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(d(231,t,typeof n));return n}var eM=!1;if(m)try{var eF={};Object.defineProperty(eF,"passive",{get:function(){eM=!0}}),window.addEventListener("test",eF,eF),window.removeEventListener("test",eF,eF)}catch(e){eM=!1}function eD(e,t,n,r,a,o,i,l,s){var u=Array.prototype.slice.call(arguments,3);try{t.apply(n,u)}catch(e){this.onError(e)}}var ez=!1,e$=null,eB=!1,eU=null,eH={onError:function(e){ez=!0,e$=e}};function eZ(e,t,n,r,a,o,i,l,s){ez=!1,e$=null,eD.apply(eH,arguments)}function eW(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do 0!=(4098&(t=e).flags)&&(n=t.return),e=t.return;while(e)}return 3===t.tag?n:null}function eV(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&null!==(e=e.alternate)&&(t=e.memoizedState),null!==t)return t.dehydrated}return null}function eG(e){if(eW(e)!==e)throw Error(d(188))}function eq(e){return null!==(e=function(e){var t=e.alternate;if(!t){if(null===(t=eW(e)))throw Error(d(188));return t!==e?null:e}for(var n=e,r=t;;){var a=n.return;if(null===a)break;var o=a.alternate;if(null===o){if(null!==(r=a.return)){n=r;continue}break}if(a.child===o.child){for(o=a.child;o;){if(o===n)return eG(a),e;if(o===r)return eG(a),t;o=o.sibling}throw Error(d(188))}if(n.return!==r.return)n=a,r=o;else{for(var i=!1,l=a.child;l;){if(l===n){i=!0,n=a,r=o;break}if(l===r){i=!0,r=a,n=o;break}l=l.sibling}if(!i){for(l=o.child;l;){if(l===n){i=!0,n=o,r=a;break}if(l===r){i=!0,r=o,n=a;break}l=l.sibling}if(!i)throw Error(d(189))}}if(n.alternate!==r)throw Error(d(190))}if(3!==n.tag)throw Error(d(188));return n.stateNode.current===n?e:t}(e))?function e(t){if(5===t.tag||6===t.tag)return t;for(t=t.child;null!==t;){var n=e(t);if(null!==n)return n;t=t.sibling}return null}(e):null}var eY=c.unstable_scheduleCallback,eK=c.unstable_cancelCallback,eQ=c.unstable_shouldYield,eX=c.unstable_requestPaint,eJ=c.unstable_now,e0=c.unstable_getCurrentPriorityLevel,e1=c.unstable_ImmediatePriority,e2=c.unstable_UserBlockingPriority,e3=c.unstable_NormalPriority,e4=c.unstable_LowPriority,e9=c.unstable_IdlePriority,e8=null,e6=null,e5=Math.clz32?Math.clz32:function(e){return 0==(e>>>=0)?32:31-(e7(e)/te|0)|0},e7=Math.log,te=Math.LN2,tt=64,tn=4194304;function tr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 0x1000000:case 0x2000000:case 0x4000000:return 0x7c00000&e;case 0x8000000:return 0x8000000;case 0x10000000:return 0x10000000;case 0x20000000:return 0x20000000;case 0x40000000:return 0x40000000;default:return e}}function ta(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,a=e.suspendedLanes,o=e.pingedLanes,i=0xfffffff&n;if(0!==i){var l=i&~a;0!==l?r=tr(l):0!=(o&=i)&&(r=tr(o))}else 0!=(i=n&~a)?r=tr(i):0!==o&&(r=tr(o));if(0===r)return 0;if(0!==t&&t!==r&&0==(t&a)&&((a=r&-r)>=(o=t&-t)||16===a&&0!=(4194240&o)))return t;if(0!=(4&r)&&(r|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)a=1<<(n=31-e5(t)),r|=e[n],t&=~a;return r}function to(e){return 0!=(e=-0x40000001&e.pendingLanes)?e:0x40000000&e?0x40000000:0}function ti(){var e=tt;return 0==(4194240&(tt<<=1))&&(tt=64),e}function tl(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function ts(e,t,n){e.pendingLanes|=t,0x20000000!==t&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,e[t=31-e5(t)]=n}function tu(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-e5(n),a=1<<r;a&t|e[r]&t&&(e[r]|=t),n&=~a}}var tc=0;function td(e){return 1<(e&=-e)?4<e?0!=(0xfffffff&e)?16:0x20000000:4:1}var tf,tp,th,tg,tm,ty=!1,tb=[],tv=null,tx=null,tw=null,tk=new Map,tS=new Map,tE=[],t_="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function tC(e,t){switch(e){case"focusin":case"focusout":tv=null;break;case"dragenter":case"dragleave":tx=null;break;case"mouseover":case"mouseout":tw=null;break;case"pointerover":case"pointerout":tk.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":tS.delete(t.pointerId)}}function tT(e,t,n,r,a,o){return null===e||e.nativeEvent!==o?(e={blockedOn:t,domEventName:n,eventSystemFlags:r,nativeEvent:o,targetContainers:[a]},null!==t&&null!==(t=rM(t))&&tp(t),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==a&&-1===t.indexOf(a)&&t.push(a),e)}function tN(e){var t=rI(e.target);if(null!==t){var n=eW(t);if(null!==n){if(13===(t=n.tag)){if(null!==(t=eV(n))){e.blockedOn=t,tm(e.priority,function(){th(n)});return}}else if(3===t&&n.stateNode.current.memoizedState.isDehydrated){e.blockedOn=3===n.tag?n.stateNode.containerInfo:null;return}}}e.blockedOn=null}function tA(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=t$(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=rM(n))&&tp(t),e.blockedOn=n,!1;var r=new(n=e.nativeEvent).constructor(n.type,n);eS=r,n.target.dispatchEvent(r),eS=null;t.shift()}return!0}function tO(e,t,n){tA(e)&&n.delete(t)}function tP(){ty=!1,null!==tv&&tA(tv)&&(tv=null),null!==tx&&tA(tx)&&(tx=null),null!==tw&&tA(tw)&&(tw=null),tk.forEach(tO),tS.forEach(tO)}function tj(e,t){e.blockedOn===t&&(e.blockedOn=null,ty||(ty=!0,c.unstable_scheduleCallback(c.unstable_NormalPriority,tP)))}function tL(e){function t(t){return tj(t,e)}if(0<tb.length){tj(tb[0],e);for(var n=1;n<tb.length;n++){var r=tb[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==tv&&tj(tv,e),null!==tx&&tj(tx,e),null!==tw&&tj(tw,e),tk.forEach(t),tS.forEach(t),n=0;n<tE.length;n++)(r=tE[n]).blockedOn===e&&(r.blockedOn=null);for(;0<tE.length&&null===(n=tE[0]).blockedOn;)tN(n),null===n.blockedOn&&tE.shift()}var tR=C.ReactCurrentBatchConfig,tI=!0;function tM(e,t,n,r){var a=tc,o=tR.transition;tR.transition=null;try{tc=1,tD(e,t,n,r)}finally{tc=a,tR.transition=o}}function tF(e,t,n,r){var a=tc,o=tR.transition;tR.transition=null;try{tc=4,tD(e,t,n,r)}finally{tc=a,tR.transition=o}}function tD(e,t,n,r){if(tI){var a=t$(e,t,n,r);if(null===a)rl(e,t,r,tz,n),tC(e,r);else if(function(e,t,n,r,a){switch(t){case"focusin":return tv=tT(tv,e,t,n,r,a),!0;case"dragenter":return tx=tT(tx,e,t,n,r,a),!0;case"mouseover":return tw=tT(tw,e,t,n,r,a),!0;case"pointerover":var o=a.pointerId;return tk.set(o,tT(tk.get(o)||null,e,t,n,r,a)),!0;case"gotpointercapture":return o=a.pointerId,tS.set(o,tT(tS.get(o)||null,e,t,n,r,a)),!0}return!1}(a,e,t,n,r))r.stopPropagation();else if(tC(e,r),4&t&&-1<t_.indexOf(e)){for(;null!==a;){var o=rM(a);if(null!==o&&tf(o),null===(o=t$(e,t,n,r))&&rl(e,t,r,tz,n),o===a)break;a=o}null!==a&&r.stopPropagation()}else rl(e,t,r,null,n)}}var tz=null;function t$(e,t,n,r){if(tz=null,null!==(e=rI(e=eE(r)))){if(null===(t=eW(e)))e=null;else if(13===(n=t.tag)){if(null!==(e=eV(t)))return e;e=null}else if(3===n){if(t.stateNode.current.memoizedState.isDehydrated)return 3===t.tag?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null)}return tz=e,null}function tB(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(e0()){case e1:return 1;case e2:return 4;case e3:case e4:return 16;case e9:return 0x20000000;default:return 16}default:return 16}}var tU=null,tH=null,tZ=null;function tW(){if(tZ)return tZ;var e,t,n=tH,r=n.length,a="value"in tU?tU.value:tU.textContent,o=a.length;for(e=0;e<r&&n[e]===a[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===a[o-t];t++);return tZ=a.slice(e,1<t?1-t:void 0)}function tV(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function tG(){return!0}function tq(){return!1}function tY(e){function t(t,n,r,a,o){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=a,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(a):a[i]);return this.isDefaultPrevented=(null!=a.defaultPrevented?a.defaultPrevented:!1===a.returnValue)?tG:tq,this.isPropagationStopped=tq,this}return H(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=tG)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=tG)},persist:function(){},isPersistent:tG}),t}var tK,tQ,tX,tJ={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},t0=tY(tJ),t1=H({},tJ,{view:0,detail:0}),t2=tY(t1),t3=H({},t1,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:na,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==tX&&(tX&&"mousemove"===e.type?(tK=e.screenX-tX.screenX,tQ=e.screenY-tX.screenY):tQ=tK=0,tX=e),tK)},movementY:function(e){return"movementY"in e?e.movementY:tQ}}),t4=tY(t3),t9=tY(H({},t3,{dataTransfer:0})),t8=tY(H({},t1,{relatedTarget:0})),t6=tY(H({},tJ,{animationName:0,elapsedTime:0,pseudoElement:0})),t5=tY(H({},tJ,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}})),t7=tY(H({},tJ,{data:0})),ne={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},nt={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},nn={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function nr(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=nn[e])&&!!t[e]}function na(){return nr}var no=tY(H({},t1,{key:function(e){if(e.key){var t=ne[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=tV(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?nt[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:na,charCode:function(e){return"keypress"===e.type?tV(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?tV(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}})),ni=tY(H({},t3,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),nl=tY(H({},t1,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:na})),ns=tY(H({},tJ,{propertyName:0,elapsedTime:0,pseudoElement:0})),nu=tY(H({},t3,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0})),nc=[9,13,27,32],nd=m&&"CompositionEvent"in window,nf=null;m&&"documentMode"in document&&(nf=document.documentMode);var np=m&&"TextEvent"in window&&!nf,nh=m&&(!nd||nf&&8<nf&&11>=nf),ng=!1;function nm(e,t){switch(e){case"keyup":return -1!==nc.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ny(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var nb=!1,nv={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function nx(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!nv[e.type]:"textarea"===t}function nw(e,t,n,r){eA(r),0<(t=ru(t,"onChange")).length&&(n=new t0("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var nk=null,nS=null;function nE(e){rt(e,0)}function n_(e){if(K(rF(e)))return e}function nC(e,t){if("change"===e)return t}var nT=!1;if(m){if(m){var nN="oninput"in document;if(!nN){var nA=document.createElement("div");nA.setAttribute("oninput","return;"),nN="function"==typeof nA.oninput}r=nN}else r=!1;nT=r&&(!document.documentMode||9<document.documentMode)}function nO(){nk&&(nk.detachEvent("onpropertychange",nP),nS=nk=null)}function nP(e){if("value"===e.propertyName&&n_(nS)){var t=[];nw(t,nS,e,eE(e)),eR(nE,t)}}function nj(e,t,n){"focusin"===e?(nO(),nk=t,nS=n,nk.attachEvent("onpropertychange",nP)):"focusout"===e&&nO()}function nL(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return n_(nS)}function nR(e,t){if("click"===e)return n_(t)}function nI(e,t){if("input"===e||"change"===e)return n_(t)}var nM="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t};function nF(e,t){if(nM(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++){var a=n[r];if(!y.call(t,a)||!nM(e[a],t[a]))return!1}return!0}function nD(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function nz(e,t){var n,r=nD(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=nD(r)}}function n$(){for(var e=window,t=Q();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(e){n=!1}if(n)e=t.contentWindow;else break;t=Q(e.document)}return t}function nB(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var nU=m&&"documentMode"in document&&11>=document.documentMode,nH=null,nZ=null,nW=null,nV=!1;function nG(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;nV||null==nH||nH!==Q(r)||(r="selectionStart"in(r=nH)&&nB(r)?{start:r.selectionStart,end:r.selectionEnd}:{anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},nW&&nF(nW,r)||(nW=r,0<(r=ru(nZ,"onSelect")).length&&(t=new t0("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=nH)))}function nq(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var nY={animationend:nq("Animation","AnimationEnd"),animationiteration:nq("Animation","AnimationIteration"),animationstart:nq("Animation","AnimationStart"),transitionend:nq("Transition","TransitionEnd")},nK={},nQ={};function nX(e){if(nK[e])return nK[e];if(!nY[e])return e;var t,n=nY[e];for(t in n)if(n.hasOwnProperty(t)&&t in nQ)return nK[e]=n[t];return e}m&&(nQ=document.createElement("div").style,"AnimationEvent"in window||(delete nY.animationend.animation,delete nY.animationiteration.animation,delete nY.animationstart.animation),"TransitionEvent"in window||delete nY.transitionend.transition);var nJ=nX("animationend"),n0=nX("animationiteration"),n1=nX("animationstart"),n2=nX("transitionend"),n3=new Map,n4="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function n9(e,t){n3.set(e,t),h(t,[e])}for(var n8=0;n8<n4.length;n8++){var n6=n4[n8];n9(n6.toLowerCase(),"on"+(n6[0].toUpperCase()+n6.slice(1)))}n9(nJ,"onAnimationEnd"),n9(n0,"onAnimationIteration"),n9(n1,"onAnimationStart"),n9("dblclick","onDoubleClick"),n9("focusin","onFocus"),n9("focusout","onBlur"),n9(n2,"onTransitionEnd"),g("onMouseEnter",["mouseout","mouseover"]),g("onMouseLeave",["mouseout","mouseover"]),g("onPointerEnter",["pointerout","pointerover"]),g("onPointerLeave",["pointerout","pointerover"]),h("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),h("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),h("onBeforeInput",["compositionend","keypress","textInput","paste"]),h("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),h("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),h("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var n5="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),n7=new Set("cancel close invalid load scroll toggle".split(" ").concat(n5));function re(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,!function(e,t,n,r,a,o,i,l,s){if(eZ.apply(this,arguments),ez){if(ez){var u=e$;ez=!1,e$=null}else throw Error(d(198));eB||(eB=!0,eU=u)}}(r,t,void 0,e),e.currentTarget=null}function rt(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var r=e[n],a=r.event;r=r.listeners;e:{var o=void 0;if(t)for(var i=r.length-1;0<=i;i--){var l=r[i],s=l.instance,u=l.currentTarget;if(l=l.listener,s!==o&&a.isPropagationStopped())break e;re(a,l,u),o=s}else for(i=0;i<r.length;i++){if(s=(l=r[i]).instance,u=l.currentTarget,l=l.listener,s!==o&&a.isPropagationStopped())break e;re(a,l,u),o=s}}}if(eB)throw e=eU,eB=!1,eU=null,e}function rn(e,t){var n=t[rj];void 0===n&&(n=t[rj]=new Set);var r=e+"__bubble";n.has(r)||(ri(t,e,2,!1),n.add(r))}function rr(e,t,n){var r=0;t&&(r|=4),ri(n,e,r,t)}var ra="_reactListening"+Math.random().toString(36).slice(2);function ro(e){if(!e[ra]){e[ra]=!0,f.forEach(function(t){"selectionchange"!==t&&(n7.has(t)||rr(t,!1,e),rr(t,!0,e))});var t=9===e.nodeType?e:e.ownerDocument;null===t||t[ra]||(t[ra]=!0,rr("selectionchange",!1,t))}}function ri(e,t,n,r){switch(tB(t)){case 1:var a=tM;break;case 4:a=tF;break;default:a=tD}n=a.bind(null,t,n,e),a=void 0,eM&&("touchstart"===t||"touchmove"===t||"wheel"===t)&&(a=!0),r?void 0!==a?e.addEventListener(t,n,{capture:!0,passive:a}):e.addEventListener(t,n,!0):void 0!==a?e.addEventListener(t,n,{passive:a}):e.addEventListener(t,n,!1)}function rl(e,t,n,r,a){var o=r;if(0==(1&t)&&0==(2&t)&&null!==r)e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var l=r.stateNode.containerInfo;if(l===a||8===l.nodeType&&l.parentNode===a)break;if(4===i)for(i=r.return;null!==i;){var s=i.tag;if((3===s||4===s)&&((s=i.stateNode.containerInfo)===a||8===s.nodeType&&s.parentNode===a))return;i=i.return}for(;null!==l;){if(null===(i=rI(l)))return;if(5===(s=i.tag)||6===s){r=o=i;continue e}l=l.parentNode}}r=r.return}eR(function(){var r=o,a=eE(n),i=[];e:{var l=n3.get(e);if(void 0!==l){var s=t0,u=e;switch(e){case"keypress":if(0===tV(n))break e;case"keydown":case"keyup":s=no;break;case"focusin":u="focus",s=t8;break;case"focusout":u="blur",s=t8;break;case"beforeblur":case"afterblur":s=t8;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":s=t4;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":s=t9;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":s=nl;break;case nJ:case n0:case n1:s=t6;break;case n2:s=ns;break;case"scroll":s=t2;break;case"wheel":s=nu;break;case"copy":case"cut":case"paste":s=t5;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":s=ni}var c=0!=(4&t),d=!c&&"scroll"===e,f=c?null!==l?l+"Capture":null:l;c=[];for(var p,h=r;null!==h;){var g=(p=h).stateNode;if(5===p.tag&&null!==g&&(p=g,null!==f&&null!=(g=eI(h,f))&&c.push(rs(h,g,p))),d)break;h=h.return}0<c.length&&(l=new s(l,u,null,n,a),i.push({event:l,listeners:c}))}}if(0==(7&t)){e:if(l="mouseover"===e||"pointerover"===e,s="mouseout"===e||"pointerout"===e,!(l&&n!==eS&&(u=n.relatedTarget||n.fromElement)&&(rI(u)||u[rP]))){if((s||l)&&(l=a.window===a?a:(l=a.ownerDocument)?l.defaultView||l.parentWindow:window,s?(u=n.relatedTarget||n.toElement,s=r,null!==(u=u?rI(u):null)&&(d=eW(u),u!==d||5!==u.tag&&6!==u.tag)&&(u=null)):(s=null,u=r),s!==u)){if(c=t4,g="onMouseLeave",f="onMouseEnter",h="mouse",("pointerout"===e||"pointerover"===e)&&(c=ni,g="onPointerLeave",f="onPointerEnter",h="pointer"),d=null==s?l:rF(s),p=null==u?l:rF(u),(l=new c(g,h+"leave",s,n,a)).target=d,l.relatedTarget=p,g=null,rI(a)===r&&((c=new c(f,h+"enter",u,n,a)).target=p,c.relatedTarget=d,g=c),d=g,s&&u)t:{for(c=s,f=u,h=0,p=c;p;p=rc(p))h++;for(p=0,g=f;g;g=rc(g))p++;for(;0<h-p;)c=rc(c),h--;for(;0<p-h;)f=rc(f),p--;for(;h--;){if(c===f||null!==f&&c===f.alternate)break t;c=rc(c),f=rc(f)}c=null}else c=null;null!==s&&rd(i,l,s,c,!1),null!==u&&null!==d&&rd(i,d,u,c,!0)}}e:{if("select"===(s=(l=r?rF(r):window).nodeName&&l.nodeName.toLowerCase())||"input"===s&&"file"===l.type)var m,y=nC;else if(nx(l)){if(nT)y=nI;else{y=nL;var b=nj}}else(s=l.nodeName)&&"input"===s.toLowerCase()&&("checkbox"===l.type||"radio"===l.type)&&(y=nR);if(y&&(y=y(e,r))){nw(i,y,n,a);break e}b&&b(e,l,r),"focusout"===e&&(b=l._wrapperState)&&b.controlled&&"number"===l.type&&er(l,"number",l.value)}switch(b=r?rF(r):window,e){case"focusin":(nx(b)||"true"===b.contentEditable)&&(nH=b,nZ=r,nW=null);break;case"focusout":nW=nZ=nH=null;break;case"mousedown":nV=!0;break;case"contextmenu":case"mouseup":case"dragend":nV=!1,nG(i,n,a);break;case"selectionchange":if(nU)break;case"keydown":case"keyup":nG(i,n,a)}if(nd)t:{switch(e){case"compositionstart":var v="onCompositionStart";break t;case"compositionend":v="onCompositionEnd";break t;case"compositionupdate":v="onCompositionUpdate";break t}v=void 0}else nb?nm(e,n)&&(v="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(v="onCompositionStart");v&&(nh&&"ko"!==n.locale&&(nb||"onCompositionStart"!==v?"onCompositionEnd"===v&&nb&&(m=tW()):(tH="value"in(tU=a)?tU.value:tU.textContent,nb=!0)),0<(b=ru(r,v)).length&&(v=new t7(v,e,null,n,a),i.push({event:v,listeners:b}),m?v.data=m:null!==(m=ny(n))&&(v.data=m))),(m=np?function(e,t){switch(e){case"compositionend":return ny(t);case"keypress":if(32!==t.which)return null;return ng=!0," ";case"textInput":return" "===(e=t.data)&&ng?null:e;default:return null}}(e,n):function(e,t){if(nb)return"compositionend"===e||!nd&&nm(e,t)?(e=tW(),tZ=tH=tU=null,nb=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return nh&&"ko"!==t.locale?null:t.data}}(e,n))&&0<(r=ru(r,"onBeforeInput")).length&&(a=new t7("onBeforeInput","beforeinput",null,n,a),i.push({event:a,listeners:r}),a.data=m)}rt(i,t)})}function rs(e,t,n){return{instance:e,listener:t,currentTarget:n}}function ru(e,t){for(var n=t+"Capture",r=[];null!==e;){var a=e,o=a.stateNode;5===a.tag&&null!==o&&(a=o,null!=(o=eI(e,n))&&r.unshift(rs(e,o,a)),null!=(o=eI(e,t))&&r.push(rs(e,o,a))),e=e.return}return r}function rc(e){if(null===e)return null;do e=e.return;while(e&&5!==e.tag);return e||null}function rd(e,t,n,r,a){for(var o=t._reactName,i=[];null!==n&&n!==r;){var l=n,s=l.alternate,u=l.stateNode;if(null!==s&&s===r)break;5===l.tag&&null!==u&&(l=u,a?null!=(s=eI(n,o))&&i.unshift(rs(n,s,l)):a||null!=(s=eI(n,o))&&i.push(rs(n,s,l))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}var rf=/\r\n?/g,rp=/\u0000|\uFFFD/g;function rh(e){return("string"==typeof e?e:""+e).replace(rf,"\n").replace(rp,"")}function rg(e,t,n){if(t=rh(t),rh(e)!==t&&n)throw Error(d(425))}function rm(){}var ry=null,rb=null;function rv(e,t){return"textarea"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var rx="function"==typeof setTimeout?setTimeout:void 0,rw="function"==typeof clearTimeout?clearTimeout:void 0,rk="function"==typeof Promise?Promise:void 0,rS="function"==typeof queueMicrotask?queueMicrotask:void 0!==rk?function(e){return rk.resolve(null).then(e).catch(rE)}:rx;function rE(e){setTimeout(function(){throw e})}function r_(e,t){var n=t,r=0;do{var a=n.nextSibling;if(e.removeChild(n),a&&8===a.nodeType){if("/$"===(n=a.data)){if(0===r){e.removeChild(a),tL(t);return}r--}else"$"!==n&&"$?"!==n&&"$!"!==n||r++}n=a}while(n);tL(t)}function rC(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break;if(8===t){if("$"===(t=e.data)||"$!"===t||"$?"===t)break;if("/$"===t)return null}}return e}function rT(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var rN=Math.random().toString(36).slice(2),rA="__reactFiber$"+rN,rO="__reactProps$"+rN,rP="__reactContainer$"+rN,rj="__reactEvents$"+rN,rL="__reactListeners$"+rN,rR="__reactHandles$"+rN;function rI(e){var t=e[rA];if(t)return t;for(var n=e.parentNode;n;){if(t=n[rP]||n[rA]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=rT(e);null!==e;){if(n=e[rA])return n;e=rT(e)}return t}n=(e=n).parentNode}return null}function rM(e){return(e=e[rA]||e[rP])&&(5===e.tag||6===e.tag||13===e.tag||3===e.tag)?e:null}function rF(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(d(33))}function rD(e){return e[rO]||null}var rz=[],r$=-1;function rB(e){return{current:e}}function rU(e){0>r$||(e.current=rz[r$],rz[r$]=null,r$--)}function rH(e,t){rz[++r$]=e.current,e.current=t}var rZ={},rW=rB(rZ),rV=rB(!1),rG=rZ;function rq(e,t){var n=e.type.contextTypes;if(!n)return rZ;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a,o={};for(a in n)o[a]=t[a];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function rY(e){return null!=(e=e.childContextTypes)}function rK(){rU(rV),rU(rW)}function rQ(e,t,n){if(rW.current!==rZ)throw Error(d(168));rH(rW,t),rH(rV,n)}function rX(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var a in r=r.getChildContext())if(!(a in t))throw Error(d(108,function(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return function e(t){if(null==t)return null;if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t;switch(t){case A:return"Fragment";case N:return"Portal";case P:return"Profiler";case O:return"StrictMode";case I:return"Suspense";case M:return"SuspenseList"}if("object"==typeof t)switch(t.$$typeof){case L:return(t.displayName||"Context")+".Consumer";case j:return(t._context.displayName||"Context")+".Provider";case R:var n=t.render;return(t=t.displayName)||(t=""!==(t=n.displayName||n.name||"")?"ForwardRef("+t+")":"ForwardRef"),t;case F:return null!==(n=t.displayName||null)?n:e(t.type)||"Memo";case D:n=t._payload,t=t._init;try{return e(t(n))}catch(e){}}return null}(t);case 8:return t===O?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}(e)||"Unknown",a));return H({},n,r)}function rJ(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||rZ,rG=rW.current,rH(rW,e),rH(rV,rV.current),!0}function r0(e,t,n){var r=e.stateNode;if(!r)throw Error(d(169));n?(e=rX(e,t,rG),r.__reactInternalMemoizedMergedChildContext=e,rU(rV),rU(rW),rH(rW,e)):rU(rV),rH(rV,n)}var r1=null,r2=!1,r3=!1;function r4(e){null===r1?r1=[e]:r1.push(e)}function r9(){if(!r3&&null!==r1){r3=!0;var e=0,t=tc;try{var n=r1;for(tc=1;e<n.length;e++){var r=n[e];do r=r(!0);while(null!==r)}r1=null,r2=!1}catch(t){throw null!==r1&&(r1=r1.slice(e+1)),eY(e1,r9),t}finally{tc=t,r3=!1}}return null}var r8=[],r6=0,r5=null,r7=0,ae=[],at=0,an=null,ar=1,aa="";function ao(e,t){r8[r6++]=r7,r8[r6++]=r5,r5=e,r7=t}function ai(e,t,n){ae[at++]=ar,ae[at++]=aa,ae[at++]=an,an=e;var r=ar;e=aa;var a=32-e5(r)-1;r&=~(1<<a),n+=1;var o=32-e5(t)+a;if(30<o){var i=a-a%5;o=(r&(1<<i)-1).toString(32),r>>=i,a-=i,ar=1<<32-e5(t)+a|n<<a|r,aa=o+e}else ar=1<<o|n<<a|r,aa=e}function al(e){null!==e.return&&(ao(e,1),ai(e,1,0))}function as(e){for(;e===r5;)r5=r8[--r6],r8[r6]=null,r7=r8[--r6],r8[r6]=null;for(;e===an;)an=ae[--at],ae[at]=null,aa=ae[--at],ae[at]=null,ar=ae[--at],ae[at]=null}var au=null,ac=null,ad=!1,af=null;function ap(e,t){var n=lY(5,null,null,0);n.elementType="DELETED",n.stateNode=t,n.return=e,null===(t=e.deletions)?(e.deletions=[n],e.flags|=16):t.push(n)}function ah(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,au=e,ac=rC(t.firstChild),!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,au=e,ac=null,!0);case 13:return null!==(t=8!==t.nodeType?null:t)&&(n=null!==an?{id:ar,overflow:aa}:null,e.memoizedState={dehydrated:t,treeContext:n,retryLane:0x40000000},(n=lY(18,null,null,0)).stateNode=t,n.return=e,e.child=n,au=e,ac=null,!0);default:return!1}}function ag(e){return 0!=(1&e.mode)&&0==(128&e.flags)}function am(e){if(ad){var t=ac;if(t){var n=t;if(!ah(e,t)){if(ag(e))throw Error(d(418));t=rC(n.nextSibling);var r=au;t&&ah(e,t)?ap(r,n):(e.flags=-4097&e.flags|2,ad=!1,au=e)}}else{if(ag(e))throw Error(d(418));e.flags=-4097&e.flags|2,ad=!1,au=e}}}function ay(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;au=e}function ab(e){if(e!==au)return!1;if(!ad)return ay(e),ad=!0,!1;if((t=3!==e.tag)&&!(t=5!==e.tag)&&(t="head"!==(t=e.type)&&"body"!==t&&!rv(e.type,e.memoizedProps)),t&&(t=ac)){if(ag(e))throw av(),Error(d(418));for(;t;)ap(e,t),t=rC(t.nextSibling)}if(ay(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(d(317));e:{for(t=0,e=e.nextSibling;e;){if(8===e.nodeType){var t,n=e.data;if("/$"===n){if(0===t){ac=rC(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}ac=null}}else ac=au?rC(e.stateNode.nextSibling):null;return!0}function av(){for(var e=ac;e;)e=rC(e.nextSibling)}function ax(){ac=au=null,ad=!1}function aw(e){null===af?af=[e]:af.push(e)}var ak=C.ReactCurrentBatchConfig;function aS(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(d(309));var r=n.stateNode}if(!r)throw Error(d(147,e));var a=r,o=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===o?t.ref:((t=function(e){var t=a.refs;null===e?delete t[o]:t[o]=e})._stringRef=o,t)}if("string"!=typeof e)throw Error(d(284));if(!n._owner)throw Error(d(290,e))}return e}function aE(e,t){throw Error(d(31,"[object Object]"===(e=Object.prototype.toString.call(t))?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function a_(e){return(0,e._init)(e._payload)}function aC(e){function t(t,n){if(e){var r=t.deletions;null===r?(t.deletions=[n],t.flags|=16):r.push(n)}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function a(e,t){return(e=lQ(e,t)).index=0,e.sibling=null,e}function o(t,n,r){return(t.index=r,e)?null!==(r=t.alternate)?(r=r.index)<n?(t.flags|=2,n):r:(t.flags|=2,n):(t.flags|=1048576,n)}function i(t){return e&&null===t.alternate&&(t.flags|=2),t}function l(e,t,n,r){return null===t||6!==t.tag?((t=l1(n,e.mode,r)).return=e,t):((t=a(t,n)).return=e,t)}function s(e,t,n,r){var o=n.type;return o===A?c(e,t,n.props.children,r,n.key):null!==t&&(t.elementType===o||"object"==typeof o&&null!==o&&o.$$typeof===D&&a_(o)===t.type)?((r=a(t,n.props)).ref=aS(e,t,n),r.return=e,r):((r=lX(n.type,n.key,n.props,null,e.mode,r)).ref=aS(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=l2(n,e.mode,r)).return=e,t):((t=a(t,n.children||[])).return=e,t)}function c(e,t,n,r,o){return null===t||7!==t.tag?((t=lJ(n,e.mode,r,o)).return=e,t):((t=a(t,n)).return=e,t)}function f(e,t,n){if("string"==typeof t&&""!==t||"number"==typeof t)return(t=l1(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case T:return(n=lX(t.type,t.key,t.props,null,e.mode,n)).ref=aS(e,null,t),n.return=e,n;case N:return(t=l2(t,e.mode,n)).return=e,t;case D:return f(e,(0,t._init)(t._payload),n)}if(ea(t)||B(t))return(t=lJ(t,e.mode,n,null)).return=e,t;aE(e,t)}return null}function p(e,t,n,r){var a=null!==t?t.key:null;if("string"==typeof n&&""!==n||"number"==typeof n)return null!==a?null:l(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case T:return n.key===a?s(e,t,n,r):null;case N:return n.key===a?u(e,t,n,r):null;case D:return p(e,t,(a=n._init)(n._payload),r)}if(ea(n)||B(n))return null!==a?null:c(e,t,n,r,null);aE(e,n)}return null}function h(e,t,n,r,a){if("string"==typeof r&&""!==r||"number"==typeof r)return l(t,e=e.get(n)||null,""+r,a);if("object"==typeof r&&null!==r){switch(r.$$typeof){case T:return s(t,e=e.get(null===r.key?n:r.key)||null,r,a);case N:return u(t,e=e.get(null===r.key?n:r.key)||null,r,a);case D:return h(e,t,n,(0,r._init)(r._payload),a)}if(ea(r)||B(r))return c(t,e=e.get(n)||null,r,a,null);aE(t,r)}return null}return function l(s,u,c,g){if("object"==typeof c&&null!==c&&c.type===A&&null===c.key&&(c=c.props.children),"object"==typeof c&&null!==c){switch(c.$$typeof){case T:e:{for(var m=c.key,y=u;null!==y;){if(y.key===m){if((m=c.type)===A){if(7===y.tag){n(s,y.sibling),(u=a(y,c.props.children)).return=s,s=u;break e}}else if(y.elementType===m||"object"==typeof m&&null!==m&&m.$$typeof===D&&a_(m)===y.type){n(s,y.sibling),(u=a(y,c.props)).ref=aS(s,y,c),u.return=s,s=u;break e}n(s,y);break}t(s,y);y=y.sibling}c.type===A?((u=lJ(c.props.children,s.mode,g,c.key)).return=s,s=u):((g=lX(c.type,c.key,c.props,null,s.mode,g)).ref=aS(s,u,c),g.return=s,s=g)}return i(s);case N:e:{for(y=c.key;null!==u;){if(u.key===y){if(4===u.tag&&u.stateNode.containerInfo===c.containerInfo&&u.stateNode.implementation===c.implementation){n(s,u.sibling),(u=a(u,c.children||[])).return=s,s=u;break e}else{n(s,u);break}}t(s,u);u=u.sibling}(u=l2(c,s.mode,g)).return=s,s=u}return i(s);case D:return l(s,u,(y=c._init)(c._payload),g)}if(ea(c))return function(a,i,l,s){for(var u=null,c=null,d=i,g=i=0,m=null;null!==d&&g<l.length;g++){d.index>g?(m=d,d=null):m=d.sibling;var y=p(a,d,l[g],s);if(null===y){null===d&&(d=m);break}e&&d&&null===y.alternate&&t(a,d),i=o(y,i,g),null===c?u=y:c.sibling=y,c=y,d=m}if(g===l.length)return n(a,d),ad&&ao(a,g),u;if(null===d){for(;g<l.length;g++)null!==(d=f(a,l[g],s))&&(i=o(d,i,g),null===c?u=d:c.sibling=d,c=d);return ad&&ao(a,g),u}for(d=r(a,d);g<l.length;g++)null!==(m=h(d,a,g,l[g],s))&&(e&&null!==m.alternate&&d.delete(null===m.key?g:m.key),i=o(m,i,g),null===c?u=m:c.sibling=m,c=m);return e&&d.forEach(function(e){return t(a,e)}),ad&&ao(a,g),u}(s,u,c,g);if(B(c))return function(a,i,l,s){var u=B(l);if("function"!=typeof u)throw Error(d(150));if(null==(l=u.call(l)))throw Error(d(151));for(var c=u=null,g=i,m=i=0,y=null,b=l.next();null!==g&&!b.done;m++,b=l.next()){g.index>m?(y=g,g=null):y=g.sibling;var v=p(a,g,b.value,s);if(null===v){null===g&&(g=y);break}e&&g&&null===v.alternate&&t(a,g),i=o(v,i,m),null===c?u=v:c.sibling=v,c=v,g=y}if(b.done)return n(a,g),ad&&ao(a,m),u;if(null===g){for(;!b.done;m++,b=l.next())null!==(b=f(a,b.value,s))&&(i=o(b,i,m),null===c?u=b:c.sibling=b,c=b);return ad&&ao(a,m),u}for(g=r(a,g);!b.done;m++,b=l.next())null!==(b=h(g,a,m,b.value,s))&&(e&&null!==b.alternate&&g.delete(null===b.key?m:b.key),i=o(b,i,m),null===c?u=b:c.sibling=b,c=b);return e&&g.forEach(function(e){return t(a,e)}),ad&&ao(a,m),u}(s,u,c,g);aE(s,c)}return"string"==typeof c&&""!==c||"number"==typeof c?(c=""+c,null!==u&&6===u.tag?(n(s,u.sibling),(u=a(u,c)).return=s):(n(s,u),(u=l1(c,s.mode,g)).return=s),i(s=u)):n(s,u)}}var aT=aC(!0),aN=aC(!1),aA=rB(null),aO=null,aP=null,aj=null;function aL(){aj=aP=aO=null}function aR(e){var t=aA.current;rU(aA),e._currentValue=t}function aI(e,t,n){for(;null!==e;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,null!==r&&(r.childLanes|=t)):null!==r&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function aM(e,t){aO=e,aj=aP=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(ii=!0),e.firstContext=null)}function aF(e){var t=e._currentValue;if(aj!==e){if(e={context:e,memoizedValue:t,next:null},null===aP){if(null===aO)throw Error(d(308));aP=e,aO.dependencies={lanes:0,firstContext:e}}else aP=aP.next=e}return t}var aD=null;function az(e){null===aD?aD=[e]:aD.push(e)}function a$(e,t,n,r){var a=t.interleaved;return null===a?(n.next=n,az(t)):(n.next=a.next,a.next=n),t.interleaved=n,aB(e,r)}function aB(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}var aU=!1;function aH(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function aZ(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function aW(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function aV(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.shared,0!=(2&i4)){var a=r.pending;return null===a?t.next=t:(t.next=a.next,a.next=t),r.pending=t,aB(e,n)}return null===(a=r.interleaved)?(t.next=t,az(r)):(t.next=a.next,a.next=t),r.interleaved=t,aB(e,n)}function aG(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,0!=(4194240&n))){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,tu(e,n)}}function aq(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var a=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?a=o=i:o=o.next=i,n=n.next}while(null!==n);null===o?a=o=t:o=o.next=t}else a=o=t;n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:o,shared:r.shared,effects:r.effects},e.updateQueue=n;return}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function aY(e,t,n,r){var a=e.updateQueue;aU=!1;var o=a.firstBaseUpdate,i=a.lastBaseUpdate,l=a.shared.pending;if(null!==l){a.shared.pending=null;var s=l,u=s.next;s.next=null,null===i?o=u:i.next=u,i=s;var c=e.alternate;null!==c&&(l=(c=c.updateQueue).lastBaseUpdate)!==i&&(null===l?c.firstBaseUpdate=u:l.next=u,c.lastBaseUpdate=s)}if(null!==o){var d=a.baseState;for(i=0,c=u=s=null,l=o;;){var f=l.lane,p=l.eventTime;if((r&f)===f){null!==c&&(c=c.next={eventTime:p,lane:0,tag:l.tag,payload:l.payload,callback:l.callback,next:null});e:{var h=e,g=l;switch(f=t,p=n,g.tag){case 1:if("function"==typeof(h=g.payload)){d=h.call(p,d,f);break e}d=h;break e;case 3:h.flags=-65537&h.flags|128;case 0:if(null==(f="function"==typeof(h=g.payload)?h.call(p,d,f):h))break e;d=H({},d,f);break e;case 2:aU=!0}}null!==l.callback&&0!==l.lane&&(e.flags|=64,null===(f=a.effects)?a.effects=[l]:f.push(l))}else p={eventTime:p,lane:f,tag:l.tag,payload:l.payload,callback:l.callback,next:null},null===c?(u=c=p,s=d):c=c.next=p,i|=f;if(null===(l=l.next)){if(null===(l=a.shared.pending))break;else l=(f=l).next,f.next=null,a.lastBaseUpdate=f,a.shared.pending=null}}if(null===c&&(s=d),a.baseState=s,a.firstBaseUpdate=u,a.lastBaseUpdate=c,null!==(t=a.shared.interleaved)){a=t;do i|=a.lane,a=a.next;while(a!==t)}else null===o&&(a.shared.lanes=0);ln|=i,e.lanes=i,e.memoizedState=d}}function aK(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],a=r.callback;if(null!==a){if(r.callback=null,r=n,"function"!=typeof a)throw Error(d(191,a));a.call(r)}}}var aQ={},aX=rB(aQ),aJ=rB(aQ),a0=rB(aQ);function a1(e){if(e===aQ)throw Error(d(174));return e}function a2(e,t){switch(rH(a0,t),rH(aJ,e),rH(aX,aQ),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:ed(null,"");break;default:t=(e=8===e?t.parentNode:t).namespaceURI||null,t=ed(t,e=e.tagName)}rU(aX),rH(aX,t)}function a3(){rU(aX),rU(aJ),rU(a0)}function a4(e){a1(a0.current);var t=a1(aX.current),n=ed(t,e.type);t!==n&&(rH(aJ,e),rH(aX,n))}function a9(e){aJ.current===e&&(rU(aX),rU(aJ))}var a8=rB(0);function a6(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(128&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var a5=[];function a7(){for(var e=0;e<a5.length;e++)a5[e]._workInProgressVersionPrimary=null;a5.length=0}var oe=C.ReactCurrentDispatcher,ot=C.ReactCurrentBatchConfig,on=0,or=null,oa=null,oo=null,oi=!1,ol=!1,os=0,ou=0;function oc(){throw Error(d(321))}function od(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!nM(e[n],t[n]))return!1;return!0}function of(e,t,n,r,a,o){if(on=o,or=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,oe.current=null===e||null===e.memoizedState?oY:oK,e=n(r,a),ol){o=0;do{if(ol=!1,os=0,25<=o)throw Error(d(301));o+=1,oo=oa=null,t.updateQueue=null,oe.current=oQ,e=n(r,a)}while(ol)}if(oe.current=oq,t=null!==oa&&null!==oa.next,on=0,oo=oa=or=null,oi=!1,t)throw Error(d(300));return e}function op(){var e=0!==os;return os=0,e}function oh(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===oo?or.memoizedState=oo=e:oo=oo.next=e,oo}function og(){if(null===oa){var e=or.alternate;e=null!==e?e.memoizedState:null}else e=oa.next;var t=null===oo?or.memoizedState:oo.next;if(null!==t)oo=t,oa=e;else{if(null===e)throw Error(d(310));e={memoizedState:(oa=e).memoizedState,baseState:oa.baseState,baseQueue:oa.baseQueue,queue:oa.queue,next:null},null===oo?or.memoizedState=oo=e:oo=oo.next=e}return oo}function om(e,t){return"function"==typeof t?t(e):t}function oy(e){var t=og(),n=t.queue;if(null===n)throw Error(d(311));n.lastRenderedReducer=e;var r=oa,a=r.baseQueue,o=n.pending;if(null!==o){if(null!==a){var i=a.next;a.next=o.next,o.next=i}r.baseQueue=a=o,n.pending=null}if(null!==a){o=a.next,r=r.baseState;var l=i=null,s=null,u=o;do{var c=u.lane;if((on&c)===c)null!==s&&(s=s.next={lane:0,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null}),r=u.hasEagerState?u.eagerState:e(r,u.action);else{var f={lane:c,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null};null===s?(l=s=f,i=r):s=s.next=f,or.lanes|=c,ln|=c}u=u.next}while(null!==u&&u!==o);null===s?i=r:s.next=l,nM(r,t.memoizedState)||(ii=!0),t.memoizedState=r,t.baseState=i,t.baseQueue=s,n.lastRenderedState=r}if(null!==(e=n.interleaved)){a=e;do o=a.lane,or.lanes|=o,ln|=o,a=a.next;while(a!==e)}else null===a&&(n.lanes=0);return[t.memoizedState,n.dispatch]}function ob(e){var t=og(),n=t.queue;if(null===n)throw Error(d(311));n.lastRenderedReducer=e;var r=n.dispatch,a=n.pending,o=t.memoizedState;if(null!==a){n.pending=null;var i=a=a.next;do o=e(o,i.action),i=i.next;while(i!==a);nM(o,t.memoizedState)||(ii=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,r]}function ov(){}function ox(e,t){var n=or,r=og(),a=t(),o=!nM(r.memoizedState,a);if(o&&(r.memoizedState=a,ii=!0),r=r.queue,oj(oS.bind(null,n,r,e),[e]),r.getSnapshot!==t||o||null!==oo&&1&oo.memoizedState.tag){if(n.flags|=2048,oT(9,ok.bind(null,n,r,a,t),void 0,null),null===i9)throw Error(d(349));0!=(30&on)||ow(n,t,a)}return a}function ow(e,t,n){e.flags|=16384,e={getSnapshot:t,value:n},null===(t=or.updateQueue)?(t={lastEffect:null,stores:null},or.updateQueue=t,t.stores=[e]):null===(n=t.stores)?t.stores=[e]:n.push(e)}function ok(e,t,n,r){t.value=n,t.getSnapshot=r,oE(t)&&o_(e)}function oS(e,t,n){return n(function(){oE(t)&&o_(e)})}function oE(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!nM(e,n)}catch(e){return!0}}function o_(e){var t=aB(e,1);null!==t&&lk(t,e,1,-1)}function oC(e){var t=oh();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:om,lastRenderedState:e},t.queue=e,e=e.dispatch=oZ.bind(null,or,e),[t.memoizedState,e]}function oT(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=or.updateQueue)?(t={lastEffect:null,stores:null},or.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function oN(){return og().memoizedState}function oA(e,t,n,r){var a=oh();or.flags|=e,a.memoizedState=oT(1|t,n,void 0,void 0===r?null:r)}function oO(e,t,n,r){var a=og();r=void 0===r?null:r;var o=void 0;if(null!==oa){var i=oa.memoizedState;if(o=i.destroy,null!==r&&od(r,i.deps)){a.memoizedState=oT(t,n,o,r);return}}or.flags|=e,a.memoizedState=oT(1|t,n,o,r)}function oP(e,t){return oA(8390656,8,e,t)}function oj(e,t){return oO(2048,8,e,t)}function oL(e,t){return oO(4,2,e,t)}function oR(e,t){return oO(4,4,e,t)}function oI(e,t){return"function"==typeof t?(t(e=e()),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function oM(e,t,n){return n=null!=n?n.concat([e]):null,oO(4,4,oI.bind(null,t,e),n)}function oF(){}function oD(e,t){var n=og();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&od(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function oz(e,t){var n=og();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&od(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function o$(e,t,n){return 0==(21&on)?(e.baseState&&(e.baseState=!1,ii=!0),e.memoizedState=n):(nM(n,t)||(n=ti(),or.lanes|=n,ln|=n,e.baseState=!0),t)}function oB(e,t){var n=tc;tc=0!==n&&4>n?n:4,e(!0);var r=ot.transition;ot.transition={};try{e(!1),t()}finally{tc=n,ot.transition=r}}function oU(){return og().memoizedState}function oH(e,t,n){var r=lw(e);n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},oW(e)?oV(t,n):null!==(n=a$(e,t,n,r))&&(lk(n,e,r,lx()),oG(n,t,r))}function oZ(e,t,n){var r=lw(e),a={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(oW(e))oV(t,a);else{var o=e.alternate;if(0===e.lanes&&(null===o||0===o.lanes)&&null!==(o=t.lastRenderedReducer))try{var i=t.lastRenderedState,l=o(i,n);if(a.hasEagerState=!0,a.eagerState=l,nM(l,i)){var s=t.interleaved;null===s?(a.next=a,az(t)):(a.next=s.next,s.next=a),t.interleaved=a;return}}catch(e){}finally{}null!==(n=a$(e,t,a,r))&&(lk(n,e,r,a=lx()),oG(n,t,r))}}function oW(e){var t=e.alternate;return e===or||null!==t&&t===or}function oV(e,t){ol=oi=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function oG(e,t,n){if(0!=(4194240&n)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,tu(e,n)}}var oq={readContext:aF,useCallback:oc,useContext:oc,useEffect:oc,useImperativeHandle:oc,useInsertionEffect:oc,useLayoutEffect:oc,useMemo:oc,useReducer:oc,useRef:oc,useState:oc,useDebugValue:oc,useDeferredValue:oc,useTransition:oc,useMutableSource:oc,useSyncExternalStore:oc,useId:oc,unstable_isNewReconciler:!1},oY={readContext:aF,useCallback:function(e,t){return oh().memoizedState=[e,void 0===t?null:t],e},useContext:aF,useEffect:oP,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,oA(4194308,4,oI.bind(null,t,e),n)},useLayoutEffect:function(e,t){return oA(4194308,4,e,t)},useInsertionEffect:function(e,t){return oA(4,2,e,t)},useMemo:function(e,t){var n=oh();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=oh();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=oH.bind(null,or,e),[r.memoizedState,e]},useRef:function(e){var t=oh();return e={current:e},t.memoizedState=e},useState:oC,useDebugValue:oF,useDeferredValue:function(e){return oh().memoizedState=e},useTransition:function(){var e=oC(!1),t=e[0];return e=oB.bind(null,e[1]),oh().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=or,a=oh();if(ad){if(void 0===n)throw Error(d(407));n=n()}else{if(n=t(),null===i9)throw Error(d(349));0!=(30&on)||ow(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,oP(oS.bind(null,r,o,e),[e]),r.flags|=2048,oT(9,ok.bind(null,r,o,n,t),void 0,null),n},useId:function(){var e=oh(),t=i9.identifierPrefix;if(ad){var n=aa,r=ar;t=":"+t+"R"+(n=(r&~(1<<32-e5(r)-1)).toString(32)+n),0<(n=os++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=ou++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},oK={readContext:aF,useCallback:oD,useContext:aF,useEffect:oj,useImperativeHandle:oM,useInsertionEffect:oL,useLayoutEffect:oR,useMemo:oz,useReducer:oy,useRef:oN,useState:function(){return oy(om)},useDebugValue:oF,useDeferredValue:function(e){return o$(og(),oa.memoizedState,e)},useTransition:function(){return[oy(om)[0],og().memoizedState]},useMutableSource:ov,useSyncExternalStore:ox,useId:oU,unstable_isNewReconciler:!1},oQ={readContext:aF,useCallback:oD,useContext:aF,useEffect:oj,useImperativeHandle:oM,useInsertionEffect:oL,useLayoutEffect:oR,useMemo:oz,useReducer:ob,useRef:oN,useState:function(){return ob(om)},useDebugValue:oF,useDeferredValue:function(e){var t=og();return null===oa?t.memoizedState=e:o$(t,oa.memoizedState,e)},useTransition:function(){return[ob(om)[0],og().memoizedState]},useMutableSource:ov,useSyncExternalStore:ox,useId:oU,unstable_isNewReconciler:!1};function oX(e,t){if(e&&e.defaultProps)for(var n in t=H({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}function oJ(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:H({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var o0={isMounted:function(e){return!!(e=e._reactInternals)&&eW(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=lx(),a=lw(e),o=aW(r,a);o.payload=t,null!=n&&(o.callback=n),null!==(t=aV(e,o,a))&&(lk(t,e,a,r),aG(t,e,a))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=lx(),a=lw(e),o=aW(r,a);o.tag=1,o.payload=t,null!=n&&(o.callback=n),null!==(t=aV(e,o,a))&&(lk(t,e,a,r),aG(t,e,a))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=lx(),r=lw(e),a=aW(n,r);a.tag=2,null!=t&&(a.callback=t),null!==(t=aV(e,a,r))&&(lk(t,e,r,n),aG(t,e,r))}};function o1(e,t,n,r,a,o,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,o,i):!t.prototype||!t.prototype.isPureReactComponent||!nF(n,r)||!nF(a,o)}function o2(e,t,n){var r=!1,a=rZ,o=t.contextType;return"object"==typeof o&&null!==o?o=aF(o):(a=rY(t)?rG:rW.current,o=(r=null!=(r=t.contextTypes))?rq(e,a):rZ),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=o0,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=a,e.__reactInternalMemoizedMaskedChildContext=o),t}function o3(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&o0.enqueueReplaceState(t,t.state,null)}function o4(e,t,n,r){var a=e.stateNode;a.props=n,a.state=e.memoizedState,a.refs={},aH(e);var o=t.contextType;"object"==typeof o&&null!==o?a.context=aF(o):(o=rY(t)?rG:rW.current,a.context=rq(e,o)),a.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&(oJ(e,t,o,n),a.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof a.getSnapshotBeforeUpdate||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||(t=a.state,"function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount(),t!==a.state&&o0.enqueueReplaceState(a,a.state,null),aY(e,n,a,r),a.state=e.memoizedState),"function"==typeof a.componentDidMount&&(e.flags|=4194308)}function o9(e,t){try{var n="",r=t;do n+=function(e){switch(e.tag){case 5:return Z(e.type);case 16:return Z("Lazy");case 13:return Z("Suspense");case 19:return Z("SuspenseList");case 0:case 2:case 15:return e=V(e.type,!1);case 11:return e=V(e.type.render,!1);case 1:return e=V(e.type,!0);default:return""}}(r),r=r.return;while(r);var a=n}catch(e){a="\nError generating stack: "+e.message+"\n"+e.stack}return{value:e,source:t,stack:a,digest:null}}function o8(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function o6(e,t){try{console.error(t.value)}catch(e){setTimeout(function(){throw e})}}var o5="function"==typeof WeakMap?WeakMap:Map;function o7(e,t,n){(n=aW(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){lc||(lc=!0,ld=r),o6(e,t)},n}function ie(e,t,n){(n=aW(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var a=t.value;n.payload=function(){return r(a)},n.callback=function(){o6(e,t)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){o6(e,t),"function"!=typeof r&&(null===lf?lf=new Set([this]):lf.add(this));var n=t.stack;this.componentDidCatch(t.value,{componentStack:null!==n?n:""})}),n}function it(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new o5;var a=new Set;r.set(t,a)}else void 0===(a=r.get(t))&&(a=new Set,r.set(t,a));a.has(n)||(a.add(n),e=lH.bind(null,e,t,n),t.then(e,e))}function ir(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function ia(e,t,n,r,a){return 0==(1&e.mode)?(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=aW(-1,1)).tag=2,aV(n,t,1))),n.lanes|=1),e):(e.flags|=65536,e.lanes=a,e)}var io=C.ReactCurrentOwner,ii=!1;function il(e,t,n,r){t.child=null===e?aN(t,null,n,r):aT(t,e.child,n,r)}function is(e,t,n,r,a){n=n.render;var o=t.ref;return(aM(t,a),r=of(e,t,n,r,o,a),n=op(),null===e||ii)?(ad&&n&&al(t),t.flags|=1,il(e,t,r,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~a,iN(e,t,a))}function iu(e,t,n,r,a){if(null===e){var o=n.type;return"function"!=typeof o||lK(o)||void 0!==o.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=lX(n.type,null,r,t,t.mode,a)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=o,ic(e,t,o,r,a))}if(o=e.child,0==(e.lanes&a)){var i=o.memoizedProps;if((n=null!==(n=n.compare)?n:nF)(i,r)&&e.ref===t.ref)return iN(e,t,a)}return t.flags|=1,(e=lQ(o,r)).ref=t.ref,e.return=t,t.child=e}function ic(e,t,n,r,a){if(null!==e){var o=e.memoizedProps;if(nF(o,r)&&e.ref===t.ref){if(ii=!1,t.pendingProps=r=o,0==(e.lanes&a))return t.lanes=e.lanes,iN(e,t,a);else 0!=(131072&e.flags)&&(ii=!0)}}return ih(e,t,n,r,a)}function id(e,t,n){var r=t.pendingProps,a=r.children,o=null!==e?e.memoizedState:null;if("hidden"===r.mode){if(0==(1&t.mode))t.memoizedState={baseLanes:0,cachePool:null,transitions:null},rH(i7,i5),i5|=n;else{if(0==(0x40000000&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=0x40000000,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,rH(i7,i5),i5|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=null!==o?o.baseLanes:n,rH(i7,i5),i5|=r}}else null!==o?(r=o.baseLanes|n,t.memoizedState=null):r=n,rH(i7,i5),i5|=r;return il(e,t,a,n),t.child}function ip(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function ih(e,t,n,r,a){var o=rY(n)?rG:rW.current;return(o=rq(t,o),aM(t,a),n=of(e,t,n,r,o,a),r=op(),null===e||ii)?(ad&&r&&al(t),t.flags|=1,il(e,t,n,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~a,iN(e,t,a))}function ig(e,t,n,r,a){if(rY(n)){var o=!0;rJ(t)}else o=!1;if(aM(t,a),null===t.stateNode)iT(e,t),o2(t,n,r),o4(t,n,r,a),r=!0;else if(null===e){var i=t.stateNode,l=t.memoizedProps;i.props=l;var s=i.context,u=n.contextType;u="object"==typeof u&&null!==u?aF(u):rq(t,u=rY(n)?rG:rW.current);var c=n.getDerivedStateFromProps,d="function"==typeof c||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(l!==r||s!==u)&&o3(t,i,r,u),aU=!1;var f=t.memoizedState;i.state=f,aY(t,r,i,a),s=t.memoizedState,l!==r||f!==s||rV.current||aU?("function"==typeof c&&(oJ(t,n,c,r),s=t.memoizedState),(l=aU||o1(t,n,l,r,f,s,u))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4194308)):("function"==typeof i.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=s),i.props=r,i.state=s,i.context=u,r=l):("function"==typeof i.componentDidMount&&(t.flags|=4194308),r=!1)}else{i=t.stateNode,aZ(e,t),l=t.memoizedProps,u=t.type===t.elementType?l:oX(t.type,l),i.props=u,d=t.pendingProps,f=i.context,s="object"==typeof(s=n.contextType)&&null!==s?aF(s):rq(t,s=rY(n)?rG:rW.current);var p=n.getDerivedStateFromProps;(c="function"==typeof p||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(l!==d||f!==s)&&o3(t,i,r,s),aU=!1,f=t.memoizedState,i.state=f,aY(t,r,i,a);var h=t.memoizedState;l!==d||f!==h||rV.current||aU?("function"==typeof p&&(oJ(t,n,p,r),h=t.memoizedState),(u=aU||o1(t,n,u,r,f,h,s)||!1)?(c||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,h,s),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,h,s)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof i.componentDidUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=h),i.props=r,i.state=h,i.context=s,r=u):("function"!=typeof i.componentDidUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),r=!1)}return im(e,t,n,r,o,a)}function im(e,t,n,r,a,o){ip(e,t);var i=0!=(128&t.flags);if(!r&&!i)return a&&r0(t,n,!1),iN(e,t,o);r=t.stateNode,io.current=t;var l=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=aT(t,e.child,null,o),t.child=aT(t,null,l,o)):il(e,t,l,o),t.memoizedState=r.state,a&&r0(t,n,!0),t.child}function iy(e){var t=e.stateNode;t.pendingContext?rQ(e,t.pendingContext,t.pendingContext!==t.context):t.context&&rQ(e,t.context,!1),a2(e,t.containerInfo)}function ib(e,t,n,r,a){return ax(),aw(a),t.flags|=256,il(e,t,n,r),t.child}var iv={dehydrated:null,treeContext:null,retryLane:0};function ix(e){return{baseLanes:e,cachePool:null,transitions:null}}function iw(e,t,n){var r,a=t.pendingProps,o=a8.current,i=!1,l=0!=(128&t.flags);if((r=l)||(r=(null===e||null!==e.memoizedState)&&0!=(2&o)),r?(i=!0,t.flags&=-129):(null===e||null!==e.memoizedState)&&(o|=1),rH(a8,1&o),null===e)return(am(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated))?(0==(1&t.mode)?t.lanes=1:"$!"===e.data?t.lanes=8:t.lanes=0x40000000,null):(l=a.children,e=a.fallback,i?(a=t.mode,i=t.child,l={mode:"hidden",children:l},0==(1&a)&&null!==i?(i.childLanes=0,i.pendingProps=l):i=l0(l,a,0,null),e=lJ(e,a,n,null),i.return=t,e.return=t,i.sibling=e,t.child=i,t.child.memoizedState=ix(n),t.memoizedState=iv,e):ik(t,l));if(null!==(o=e.memoizedState)&&null!==(r=o.dehydrated))return function(e,t,n,r,a,o,i){if(n)return 256&t.flags?(t.flags&=-257,iS(e,t,i,r=o8(Error(d(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(o=r.fallback,a=t.mode,r=l0({mode:"visible",children:r.children},a,0,null),o=lJ(o,a,i,null),o.flags|=2,r.return=t,o.return=t,r.sibling=o,t.child=r,0!=(1&t.mode)&&aT(t,e.child,null,i),t.child.memoizedState=ix(i),t.memoizedState=iv,o);if(0==(1&t.mode))return iS(e,t,i,null);if("$!"===a.data){if(r=a.nextSibling&&a.nextSibling.dataset)var l=r.dgst;return r=l,iS(e,t,i,r=o8(o=Error(d(419)),r,void 0))}if(l=0!=(i&e.childLanes),ii||l){if(null!==(r=i9)){switch(i&-i){case 4:a=2;break;case 16:a=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 0x1000000:case 0x2000000:case 0x4000000:a=32;break;case 0x20000000:a=0x10000000;break;default:a=0}0!==(a=0!=(a&(r.suspendedLanes|i))?0:a)&&a!==o.retryLane&&(o.retryLane=a,aB(e,a),lk(r,e,a,-1))}return lI(),iS(e,t,i,r=o8(Error(d(421))))}return"$?"===a.data?(t.flags|=128,t.child=e.child,t=lW.bind(null,e),a._reactRetry=t,null):(e=o.treeContext,ac=rC(a.nextSibling),au=t,ad=!0,af=null,null!==e&&(ae[at++]=ar,ae[at++]=aa,ae[at++]=an,ar=e.id,aa=e.overflow,an=t),t=ik(t,r.children),t.flags|=4096,t)}(e,t,l,a,r,o,n);if(i){i=a.fallback,l=t.mode,r=(o=e.child).sibling;var s={mode:"hidden",children:a.children};return 0==(1&l)&&t.child!==o?((a=t.child).childLanes=0,a.pendingProps=s,t.deletions=null):(a=lQ(o,s)).subtreeFlags=0xe00000&o.subtreeFlags,null!==r?i=lQ(r,i):(i=lJ(i,l,n,null),i.flags|=2),i.return=t,a.return=t,a.sibling=i,t.child=a,a=i,i=t.child,l=null===(l=e.child.memoizedState)?ix(n):{baseLanes:l.baseLanes|n,cachePool:null,transitions:l.transitions},i.memoizedState=l,i.childLanes=e.childLanes&~n,t.memoizedState=iv,a}return e=(i=e.child).sibling,a=lQ(i,{mode:"visible",children:a.children}),0==(1&t.mode)&&(a.lanes=n),a.return=t,a.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=a,t.memoizedState=null,a}function ik(e,t){return(t=l0({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function iS(e,t,n,r){return null!==r&&aw(r),aT(t,e.child,null,n),e=ik(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function iE(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),aI(e.return,t,n)}function i_(e,t,n,r,a){var o=e.memoizedState;null===o?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:a}:(o.isBackwards=t,o.rendering=null,o.renderingStartTime=0,o.last=r,o.tail=n,o.tailMode=a)}function iC(e,t,n){var r=t.pendingProps,a=r.revealOrder,o=r.tail;if(il(e,t,r.children,n),0!=(2&(r=a8.current)))r=1&r|2,t.flags|=128;else{if(null!==e&&0!=(128&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&iE(e,n,t);else if(19===e.tag)iE(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(rH(a8,r),0==(1&t.mode))t.memoizedState=null;else switch(a){case"forwards":for(a=null,n=t.child;null!==n;)null!==(e=n.alternate)&&null===a6(e)&&(a=n),n=n.sibling;null===(n=a)?(a=t.child,t.child=null):(a=n.sibling,n.sibling=null),i_(t,!1,a,n,o);break;case"backwards":for(n=null,a=t.child,t.child=null;null!==a;){if(null!==(e=a.alternate)&&null===a6(e)){t.child=a;break}e=a.sibling,a.sibling=n,n=a,a=e}i_(t,!0,n,null,o);break;case"together":i_(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function iT(e,t){0==(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function iN(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),ln|=t.lanes,0==(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(d(153));if(null!==t.child){for(n=lQ(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=lQ(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function iA(e,t){if(!ad)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function iO(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var a=e.child;null!==a;)n|=a.lanes|a.childLanes,r|=0xe00000&a.subtreeFlags,r|=0xe00000&a.flags,a.return=e,a=a.sibling;else for(a=e.child;null!==a;)n|=a.lanes|a.childLanes,r|=a.subtreeFlags,r|=a.flags,a.return=e,a=a.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}a=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},o=function(){},i=function(e,t,n,r){var a=e.memoizedProps;if(a!==r){e=t.stateNode,a1(aX.current);var o,i=null;switch(n){case"input":a=X(e,a),r=X(e,r),i=[];break;case"select":a=H({},a,{value:void 0}),r=H({},r,{value:void 0}),i=[];break;case"textarea":a=ei(e,a),r=ei(e,r),i=[];break;default:"function"!=typeof a.onClick&&"function"==typeof r.onClick&&(e.onclick=rm)}for(u in ew(n,r),n=null,a)if(!r.hasOwnProperty(u)&&a.hasOwnProperty(u)&&null!=a[u]){if("style"===u){var l=a[u];for(o in l)l.hasOwnProperty(o)&&(n||(n={}),n[o]="")}else"dangerouslySetInnerHTML"!==u&&"children"!==u&&"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&"autoFocus"!==u&&(p.hasOwnProperty(u)?i||(i=[]):(i=i||[]).push(u,null))}for(u in r){var s=r[u];if(l=null!=a?a[u]:void 0,r.hasOwnProperty(u)&&s!==l&&(null!=s||null!=l)){if("style"===u){if(l){for(o in l)!l.hasOwnProperty(o)||s&&s.hasOwnProperty(o)||(n||(n={}),n[o]="");for(o in s)s.hasOwnProperty(o)&&l[o]!==s[o]&&(n||(n={}),n[o]=s[o])}else n||(i||(i=[]),i.push(u,n)),n=s}else"dangerouslySetInnerHTML"===u?(s=s?s.__html:void 0,l=l?l.__html:void 0,null!=s&&l!==s&&(i=i||[]).push(u,s)):"children"===u?"string"!=typeof s&&"number"!=typeof s||(i=i||[]).push(u,""+s):"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&(p.hasOwnProperty(u)?(null!=s&&"onScroll"===u&&rn("scroll",e),i||l===s||(i=[])):(i=i||[]).push(u,s))}}n&&(i=i||[]).push("style",n);var u=i;(t.updateQueue=u)&&(t.flags|=4)}},l=function(e,t,n,r){n!==r&&(t.flags|=4)};var iP=!1,ij=!1,iL="function"==typeof WeakSet?WeakSet:Set,iR=null;function iI(e,t){var n=e.ref;if(null!==n){if("function"==typeof n)try{n(null)}catch(n){lU(e,t,n)}else n.current=null}}function iM(e,t,n){try{n()}catch(n){lU(e,t,n)}}var iF=!1;function iD(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffect:null)){var a=r=r.next;do{if((a.tag&e)===e){var o=a.destroy;a.destroy=void 0,void 0!==o&&iM(t,n,o)}a=a.next}while(a!==r)}}function iz(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function i$(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag;e=n;"function"==typeof t?t(e):t.current=e}}function iB(e){return 5===e.tag||3===e.tag||4===e.tag}function iU(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||iB(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}var iH=null,iZ=!1;function iW(e,t,n){for(n=n.child;null!==n;)iV(e,t,n),n=n.sibling}function iV(e,t,n){if(e6&&"function"==typeof e6.onCommitFiberUnmount)try{e6.onCommitFiberUnmount(e8,n)}catch(e){}switch(n.tag){case 5:ij||iI(n,t);case 6:var r=iH,a=iZ;iH=null,iW(e,t,n),iH=r,iZ=a,null!==iH&&(iZ?(e=iH,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):iH.removeChild(n.stateNode));break;case 18:null!==iH&&(iZ?(e=iH,n=n.stateNode,8===e.nodeType?r_(e.parentNode,n):1===e.nodeType&&r_(e,n),tL(e)):r_(iH,n.stateNode));break;case 4:r=iH,a=iZ,iH=n.stateNode.containerInfo,iZ=!0,iW(e,t,n),iH=r,iZ=a;break;case 0:case 11:case 14:case 15:if(!ij&&null!==(r=n.updateQueue)&&null!==(r=r.lastEffect)){a=r=r.next;do{var o=a,i=o.destroy;o=o.tag,void 0!==i&&(0!=(2&o)?iM(n,t,i):0!=(4&o)&&iM(n,t,i)),a=a.next}while(a!==r)}iW(e,t,n);break;case 1:if(!ij&&(iI(n,t),"function"==typeof(r=n.stateNode).componentWillUnmount))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(e){lU(n,t,e)}iW(e,t,n);break;case 21:default:iW(e,t,n);break;case 22:1&n.mode?(ij=(r=ij)||null!==n.memoizedState,iW(e,t,n),ij=r):iW(e,t,n)}}function iG(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new iL),t.forEach(function(t){var r=lV.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))})}}function iq(e,t){var n=t.deletions;if(null!==n)for(var r=0;r<n.length;r++){var a=n[r];try{var o=t,i=o;e:for(;null!==i;){switch(i.tag){case 5:iH=i.stateNode,iZ=!1;break e;case 3:case 4:iH=i.stateNode.containerInfo,iZ=!0;break e}i=i.return}if(null===iH)throw Error(d(160));iV(e,o,a),iH=null,iZ=!1;var l=a.alternate;null!==l&&(l.return=null),a.return=null}catch(e){lU(a,t,e)}}if(12854&t.subtreeFlags)for(t=t.child;null!==t;)iY(t,e),t=t.sibling}function iY(e,t){var n=e.alternate,r=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(iq(t,e),iK(e),4&r){try{iD(3,e,e.return),iz(3,e)}catch(t){lU(e,e.return,t)}try{iD(5,e,e.return)}catch(t){lU(e,e.return,t)}}break;case 1:iq(t,e),iK(e),512&r&&null!==n&&iI(n,n.return);break;case 5:if(iq(t,e),iK(e),512&r&&null!==n&&iI(n,n.return),32&e.flags){var a=e.stateNode;try{eg(a,"")}catch(t){lU(e,e.return,t)}}if(4&r&&null!=(a=e.stateNode)){var o=e.memoizedProps,i=null!==n?n.memoizedProps:o,l=e.type,s=e.updateQueue;if(e.updateQueue=null,null!==s)try{"input"===l&&"radio"===o.type&&null!=o.name&&ee(a,o),ek(l,i);var u=ek(l,o);for(i=0;i<s.length;i+=2){var c=s[i],f=s[i+1];"style"===c?ev(a,f):"dangerouslySetInnerHTML"===c?eh(a,f):"children"===c?eg(a,f):_(a,c,f,u)}switch(l){case"input":et(a,o);break;case"textarea":es(a,o);break;case"select":var p=a._wrapperState.wasMultiple;a._wrapperState.wasMultiple=!!o.multiple;var h=o.value;null!=h?eo(a,!!o.multiple,h,!1):!!o.multiple!==p&&(null!=o.defaultValue?eo(a,!!o.multiple,o.defaultValue,!0):eo(a,!!o.multiple,o.multiple?[]:"",!1))}a[rO]=o}catch(t){lU(e,e.return,t)}}break;case 6:if(iq(t,e),iK(e),4&r){if(null===e.stateNode)throw Error(d(162));a=e.stateNode,o=e.memoizedProps;try{a.nodeValue=o}catch(t){lU(e,e.return,t)}}break;case 3:if(iq(t,e),iK(e),4&r&&null!==n&&n.memoizedState.isDehydrated)try{tL(t.containerInfo)}catch(t){lU(e,e.return,t)}break;case 4:default:iq(t,e),iK(e);break;case 13:iq(t,e),iK(e),8192&(a=e.child).flags&&(o=null!==a.memoizedState,a.stateNode.isHidden=o,o&&(null===a.alternate||null===a.alternate.memoizedState)&&(ll=eJ())),4&r&&iG(e);break;case 22:if(c=null!==n&&null!==n.memoizedState,1&e.mode?(ij=(u=ij)||c,iq(t,e),ij=u):iq(t,e),iK(e),8192&r){if(u=null!==e.memoizedState,(e.stateNode.isHidden=u)&&!c&&0!=(1&e.mode))for(iR=e,c=e.child;null!==c;){for(f=iR=c;null!==iR;){switch(h=(p=iR).child,p.tag){case 0:case 11:case 14:case 15:iD(4,p,p.return);break;case 1:iI(p,p.return);var g=p.stateNode;if("function"==typeof g.componentWillUnmount){r=p,n=p.return;try{t=r,g.props=t.memoizedProps,g.state=t.memoizedState,g.componentWillUnmount()}catch(e){lU(r,n,e)}}break;case 5:iI(p,p.return);break;case 22:if(null!==p.memoizedState){iX(f);continue}}null!==h?(h.return=p,iR=h):iX(f)}c=c.sibling}e:for(c=null,f=e;;){if(5===f.tag){if(null===c){c=f;try{a=f.stateNode,u?(o=a.style,"function"==typeof o.setProperty?o.setProperty("display","none","important"):o.display="none"):(l=f.stateNode,i=null!=(s=f.memoizedProps.style)&&s.hasOwnProperty("display")?s.display:null,l.style.display=eb("display",i))}catch(t){lU(e,e.return,t)}}}else if(6===f.tag){if(null===c)try{f.stateNode.nodeValue=u?"":f.memoizedProps}catch(t){lU(e,e.return,t)}}else if((22!==f.tag&&23!==f.tag||null===f.memoizedState||f===e)&&null!==f.child){f.child.return=f,f=f.child;continue}if(f===e)break;for(;null===f.sibling;){if(null===f.return||f.return===e)break e;c===f&&(c=null),f=f.return}c===f&&(c=null),f.sibling.return=f.return,f=f.sibling}}break;case 19:iq(t,e),iK(e),4&r&&iG(e);case 21:}}function iK(e){var t=e.flags;if(2&t){try{e:{for(var n=e.return;null!==n;){if(iB(n)){var r=n;break e}n=n.return}throw Error(d(160))}switch(r.tag){case 5:var a=r.stateNode;32&r.flags&&(eg(a,""),r.flags&=-33);var o=iU(e);!function e(t,n,r){var a=t.tag;if(5===a||6===a)t=t.stateNode,n?r.insertBefore(t,n):r.appendChild(t);else if(4!==a&&null!==(t=t.child))for(e(t,n,r),t=t.sibling;null!==t;)e(t,n,r),t=t.sibling}(e,o,a);break;case 3:case 4:var i=r.stateNode.containerInfo,l=iU(e);!function e(t,n,r){var a=t.tag;if(5===a||6===a)t=t.stateNode,n?8===r.nodeType?r.parentNode.insertBefore(t,n):r.insertBefore(t,n):(8===r.nodeType?(n=r.parentNode).insertBefore(t,r):(n=r).appendChild(t),null!=(r=r._reactRootContainer)||null!==n.onclick||(n.onclick=rm));else if(4!==a&&null!==(t=t.child))for(e(t,n,r),t=t.sibling;null!==t;)e(t,n,r),t=t.sibling}(e,l,i);break;default:throw Error(d(161))}}catch(t){lU(e,e.return,t)}e.flags&=-3}4096&t&&(e.flags&=-4097)}function iQ(e){for(;null!==iR;){var t=iR;if(0!=(8772&t.flags)){var n=t.alternate;try{if(0!=(8772&t.flags))switch(t.tag){case 0:case 11:case 15:ij||iz(5,t);break;case 1:var r=t.stateNode;if(4&t.flags&&!ij){if(null===n)r.componentDidMount();else{var a=t.elementType===t.type?n.memoizedProps:oX(t.type,n.memoizedProps);r.componentDidUpdate(a,n.memoizedState,r.__reactInternalSnapshotBeforeUpdate)}}var o=t.updateQueue;null!==o&&aK(t,o,r);break;case 3:var i=t.updateQueue;if(null!==i){if(n=null,null!==t.child)switch(t.child.tag){case 5:case 1:n=t.child.stateNode}aK(t,i,n)}break;case 5:var l=t.stateNode;if(null===n&&4&t.flags){n=l;var s=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":s.autoFocus&&n.focus();break;case"img":s.src&&(n.src=s.src)}}break;case 6:case 4:case 12:case 19:case 17:case 21:case 22:case 23:case 25:break;case 13:if(null===t.memoizedState){var u=t.alternate;if(null!==u){var c=u.memoizedState;if(null!==c){var f=c.dehydrated;null!==f&&tL(f)}}}break;default:throw Error(d(163))}ij||512&t.flags&&i$(t)}catch(e){lU(t,t.return,e)}}if(t===e){iR=null;break}if(null!==(n=t.sibling)){n.return=t.return,iR=n;break}iR=t.return}}function iX(e){for(;null!==iR;){var t=iR;if(t===e){iR=null;break}var n=t.sibling;if(null!==n){n.return=t.return,iR=n;break}iR=t.return}}function iJ(e){for(;null!==iR;){var t=iR;try{switch(t.tag){case 0:case 11:case 15:var n=t.return;try{iz(4,t)}catch(e){lU(t,n,e)}break;case 1:var r=t.stateNode;if("function"==typeof r.componentDidMount){var a=t.return;try{r.componentDidMount()}catch(e){lU(t,a,e)}}var o=t.return;try{i$(t)}catch(e){lU(t,o,e)}break;case 5:var i=t.return;try{i$(t)}catch(e){lU(t,i,e)}}}catch(e){lU(t,t.return,e)}if(t===e){iR=null;break}var l=t.sibling;if(null!==l){l.return=t.return,iR=l;break}iR=t.return}}var i0=Math.ceil,i1=C.ReactCurrentDispatcher,i2=C.ReactCurrentOwner,i3=C.ReactCurrentBatchConfig,i4=0,i9=null,i8=null,i6=0,i5=0,i7=rB(0),le=0,lt=null,ln=0,lr=0,la=0,lo=null,li=null,ll=0,ls=1/0,lu=null,lc=!1,ld=null,lf=null,lp=!1,lh=null,lg=0,lm=0,ly=null,lb=-1,lv=0;function lx(){return 0!=(6&i4)?eJ():-1!==lb?lb:lb=eJ()}function lw(e){return 0==(1&e.mode)?1:0!=(2&i4)&&0!==i6?i6&-i6:null!==ak.transition?(0===lv&&(lv=ti()),lv):0!==(e=tc)?e:e=void 0===(e=window.event)?16:tB(e.type)}function lk(e,t,n,r){if(50<lm)throw lm=0,ly=null,Error(d(185));ts(e,n,r),(0==(2&i4)||e!==i9)&&(e===i9&&(0==(2&i4)&&(lr|=n),4===le&&lT(e,i6)),lS(e,r),1===n&&0===i4&&0==(1&t.mode)&&(ls=eJ()+500,r2&&r9()))}function lS(e,t){var n,r=e.callbackNode;!function(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,a=e.expirationTimes,o=e.pendingLanes;0<o;){var i=31-e5(o),l=1<<i,s=a[i];-1===s?(0==(l&n)||0!=(l&r))&&(a[i]=function(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;default:return -1}}(l,t)):s<=t&&(e.expiredLanes|=l),o&=~l}}(e,t);var a=ta(e,e===i9?i6:0);if(0===a)null!==r&&eK(r),e.callbackNode=null,e.callbackPriority=0;else if(t=a&-a,e.callbackPriority!==t){if(null!=r&&eK(r),1===t){;0===e.tag?(n=lN.bind(null,e),r2=!0,r4(n)):r4(lN.bind(null,e)),rS(function(){0==(6&i4)&&r9()}),r=null}else{switch(td(a)){case 1:r=e1;break;case 4:r=e2;break;case 16:default:r=e3;break;case 0x20000000:r=e9}r=function(e,t){return eY(e,t)}(r,lE.bind(null,e))}e.callbackPriority=t,e.callbackNode=r}}function lE(e,t){if(lb=-1,lv=0,0!=(6&i4))throw Error(d(327));var n=e.callbackNode;if(l$()&&e.callbackNode!==n)return null;var r=ta(e,e===i9?i6:0);if(0===r)return null;if(0!=(30&r)||0!=(r&e.expiredLanes)||t)t=lM(e,r);else{t=r;var a=i4;i4|=2;var o=lR();for((i9!==e||i6!==t)&&(lu=null,ls=eJ()+500,lj(e,t));;)try{(function(){for(;null!==i8&&!eQ();)lF(i8)})();break}catch(t){lL(e,t)}aL(),i1.current=o,i4=a,null!==i8?t=0:(i9=null,i6=0,t=le)}if(0!==t){if(2===t&&0!==(a=to(e))&&(r=a,t=l_(e,a)),1===t)throw n=lt,lj(e,0),lT(e,r),lS(e,eJ()),n;if(6===t)lT(e,r);else{if(a=e.current.alternate,0==(30&r)&&!function(e){for(var t=e;;){if(16384&t.flags){var n=t.updateQueue;if(null!==n&&null!==(n=n.stores))for(var r=0;r<n.length;r++){var a=n[r],o=a.getSnapshot;a=a.value;try{if(!nM(o(),a))return!1}catch(e){return!1}}}if(n=t.child,16384&t.subtreeFlags&&null!==n)n.return=t,t=n;else{if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}(a)&&(2===(t=lM(e,r))&&0!==(o=to(e))&&(r=o,t=l_(e,o)),1===t))throw n=lt,lj(e,0),lT(e,r),lS(e,eJ()),n;switch(e.finishedWork=a,e.finishedLanes=r,t){case 0:case 1:throw Error(d(345));case 2:case 5:lz(e,li,lu);break;case 3:if(lT(e,r),(0x7c00000&r)===r&&10<(t=ll+500-eJ())){if(0!==ta(e,0))break;if(((a=e.suspendedLanes)&r)!==r){lx(),e.pingedLanes|=e.suspendedLanes&a;break}e.timeoutHandle=rx(lz.bind(null,e,li,lu),t);break}lz(e,li,lu);break;case 4:if(lT(e,r),(4194240&r)===r)break;for(a=-1,t=e.eventTimes;0<r;){var i=31-e5(r);o=1<<i,(i=t[i])>a&&(a=i),r&=~o}if(r=a,10<(r=(120>(r=eJ()-r)?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*i0(r/1960))-r)){e.timeoutHandle=rx(lz.bind(null,e,li,lu),r);break}lz(e,li,lu);break;default:throw Error(d(329))}}}return lS(e,eJ()),e.callbackNode===n?lE.bind(null,e):null}function l_(e,t){var n=lo;return e.current.memoizedState.isDehydrated&&(lj(e,t).flags|=256),2!==(e=lM(e,t))&&(t=li,li=n,null!==t&&lC(t)),e}function lC(e){null===li?li=e:li.push.apply(li,e)}function lT(e,t){for(t&=~la,t&=~lr,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-e5(t),r=1<<n;e[n]=-1,t&=~r}}function lN(e){if(0!=(6&i4))throw Error(d(327));l$();var t=ta(e,0);if(0==(1&t))return lS(e,eJ()),null;var n=lM(e,t);if(0!==e.tag&&2===n){var r=to(e);0!==r&&(t=r,n=l_(e,r))}if(1===n)throw n=lt,lj(e,0),lT(e,t),lS(e,eJ()),n;if(6===n)throw Error(d(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,lz(e,li,lu),lS(e,eJ()),null}function lA(e,t){var n=i4;i4|=1;try{return e(t)}finally{0===(i4=n)&&(ls=eJ()+500,r2&&r9())}}function lO(e){null!==lh&&0===lh.tag&&0==(6&i4)&&l$();var t=i4;i4|=1;var n=i3.transition,r=tc;try{if(i3.transition=null,tc=1,e)return e()}finally{tc=r,i3.transition=n,0==(6&(i4=t))&&r9()}}function lP(){i5=i7.current,rU(i7)}function lj(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,rw(n)),null!==i8)for(n=i8.return;null!==n;){var r=n;switch(as(r),r.tag){case 1:null!=(r=r.type.childContextTypes)&&rK();break;case 3:a3(),rU(rV),rU(rW),a7();break;case 5:a9(r);break;case 4:a3();break;case 13:case 19:rU(a8);break;case 10:aR(r.type._context);break;case 22:case 23:lP()}n=n.return}if(i9=e,i8=e=lQ(e.current,null),i6=i5=t,le=0,lt=null,la=lr=ln=0,li=lo=null,null!==aD){for(t=0;t<aD.length;t++)if(null!==(r=(n=aD[t]).interleaved)){n.interleaved=null;var a=r.next,o=n.pending;if(null!==o){var i=o.next;o.next=a,r.next=i}n.pending=r}aD=null}return e}function lL(e,t){for(;;){var n=i8;try{if(aL(),oe.current=oq,oi){for(var r=or.memoizedState;null!==r;){var a=r.queue;null!==a&&(a.pending=null),r=r.next}oi=!1}if(on=0,oo=oa=or=null,ol=!1,os=0,i2.current=null,null===n||null===n.return){le=1,lt=t,i8=null;break}e:{var o=e,i=n.return,l=n,s=t;if(t=i6,l.flags|=32768,null!==s&&"object"==typeof s&&"function"==typeof s.then){var u=s,c=l,f=c.tag;if(0==(1&c.mode)&&(0===f||11===f||15===f)){var p=c.alternate;p?(c.updateQueue=p.updateQueue,c.memoizedState=p.memoizedState,c.lanes=p.lanes):(c.updateQueue=null,c.memoizedState=null)}var h=ir(i);if(null!==h){h.flags&=-257,ia(h,i,l,o,t),1&h.mode&&it(o,u,t),t=h,s=u;var g=t.updateQueue;if(null===g){var m=new Set;m.add(s),t.updateQueue=m}else g.add(s);break e}if(0==(1&t)){it(o,u,t),lI();break e}s=Error(d(426))}else if(ad&&1&l.mode){var y=ir(i);if(null!==y){0==(65536&y.flags)&&(y.flags|=256),ia(y,i,l,o,t),aw(o9(s,l));break e}}o=s=o9(s,l),4!==le&&(le=2),null===lo?lo=[o]:lo.push(o),o=i;do{switch(o.tag){case 3:o.flags|=65536,t&=-t,o.lanes|=t;var b=o7(o,s,t);aq(o,b);break e;case 1:l=s;var v=o.type,x=o.stateNode;if(0==(128&o.flags)&&("function"==typeof v.getDerivedStateFromError||null!==x&&"function"==typeof x.componentDidCatch&&(null===lf||!lf.has(x)))){o.flags|=65536,t&=-t,o.lanes|=t;var w=ie(o,l,t);aq(o,w);break e}}o=o.return}while(null!==o)}lD(n)}catch(e){t=e,i8===n&&null!==n&&(i8=n=n.return);continue}break}}function lR(){var e=i1.current;return i1.current=oq,null===e?oq:e}function lI(){(0===le||3===le||2===le)&&(le=4),null===i9||0==(0xfffffff&ln)&&0==(0xfffffff&lr)||lT(i9,i6)}function lM(e,t){var n=i4;i4|=2;var r=lR();for((i9!==e||i6!==t)&&(lu=null,lj(e,t));;)try{(function(){for(;null!==i8;)lF(i8)})();break}catch(t){lL(e,t)}if(aL(),i4=n,i1.current=r,null!==i8)throw Error(d(261));return i9=null,i6=0,le}function lF(e){var t=s(e.alternate,e,i5);e.memoizedProps=e.pendingProps,null===t?lD(e):i8=t,i2.current=null}function lD(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(32768&t.flags)){if(null!==(n=function(e,t,n){var r=t.pendingProps;switch(as(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return iO(t),null;case 1:case 17:return rY(t.type)&&rK(),iO(t),null;case 3:return r=t.stateNode,a3(),rU(rV),rU(rW),a7(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),(null===e||null===e.child)&&(ab(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&0==(256&t.flags)||(t.flags|=1024,null!==af&&(lC(af),af=null))),o(e,t),iO(t),null;case 5:a9(t);var s=a1(a0.current);if(n=t.type,null!==e&&null!=t.stateNode)i(e,t,n,r,s),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!r){if(null===t.stateNode)throw Error(d(166));return iO(t),null}if(e=a1(aX.current),ab(t)){r=t.stateNode,n=t.type;var u=t.memoizedProps;switch(r[rA]=t,r[rO]=u,e=0!=(1&t.mode),n){case"dialog":rn("cancel",r),rn("close",r);break;case"iframe":case"object":case"embed":rn("load",r);break;case"video":case"audio":for(s=0;s<n5.length;s++)rn(n5[s],r);break;case"source":rn("error",r);break;case"img":case"image":case"link":rn("error",r),rn("load",r);break;case"details":rn("toggle",r);break;case"input":J(r,u),rn("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!u.multiple},rn("invalid",r);break;case"textarea":el(r,u),rn("invalid",r)}for(var c in ew(n,u),s=null,u)if(u.hasOwnProperty(c)){var f=u[c];"children"===c?"string"==typeof f?r.textContent!==f&&(!0!==u.suppressHydrationWarning&&rg(r.textContent,f,e),s=["children",f]):"number"==typeof f&&r.textContent!==""+f&&(!0!==u.suppressHydrationWarning&&rg(r.textContent,f,e),s=["children",""+f]):p.hasOwnProperty(c)&&null!=f&&"onScroll"===c&&rn("scroll",r)}switch(n){case"input":Y(r),en(r,u,!0);break;case"textarea":Y(r),eu(r);break;case"select":case"option":break;default:"function"==typeof u.onClick&&(r.onclick=rm)}r=s,t.updateQueue=r,null!==r&&(t.flags|=4)}else{c=9===s.nodeType?s:s.ownerDocument,"http://www.w3.org/1999/xhtml"===e&&(e=ec(n)),"http://www.w3.org/1999/xhtml"===e?"script"===n?((e=c.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=c.createElement(n,{is:r.is}):(e=c.createElement(n),"select"===n&&(c=e,r.multiple?c.multiple=!0:r.size&&(c.size=r.size))):e=c.createElementNS(e,n),e[rA]=t,e[rO]=r,a(e,t,!1,!1),t.stateNode=e;e:{switch(c=ek(n,r),n){case"dialog":rn("cancel",e),rn("close",e),s=r;break;case"iframe":case"object":case"embed":rn("load",e),s=r;break;case"video":case"audio":for(s=0;s<n5.length;s++)rn(n5[s],e);s=r;break;case"source":rn("error",e),s=r;break;case"img":case"image":case"link":rn("error",e),rn("load",e),s=r;break;case"details":rn("toggle",e),s=r;break;case"input":J(e,r),s=X(e,r),rn("invalid",e);break;case"option":default:s=r;break;case"select":e._wrapperState={wasMultiple:!!r.multiple},s=H({},r,{value:void 0}),rn("invalid",e);break;case"textarea":el(e,r),s=ei(e,r),rn("invalid",e)}for(u in ew(n,s),f=s)if(f.hasOwnProperty(u)){var h=f[u];"style"===u?ev(e,h):"dangerouslySetInnerHTML"===u?null!=(h=h?h.__html:void 0)&&eh(e,h):"children"===u?"string"==typeof h?("textarea"!==n||""!==h)&&eg(e,h):"number"==typeof h&&eg(e,""+h):"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&"autoFocus"!==u&&(p.hasOwnProperty(u)?null!=h&&"onScroll"===u&&rn("scroll",e):null!=h&&_(e,u,h,c))}switch(n){case"input":Y(e),en(e,r,!1);break;case"textarea":Y(e),eu(e);break;case"option":null!=r.value&&e.setAttribute("value",""+G(r.value));break;case"select":e.multiple=!!r.multiple,null!=(u=r.value)?eo(e,!!r.multiple,u,!1):null!=r.defaultValue&&eo(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof s.onClick&&(e.onclick=rm)}switch(n){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}}r&&(t.flags|=4)}null!==t.ref&&(t.flags|=512,t.flags|=2097152)}return iO(t),null;case 6:if(e&&null!=t.stateNode)l(e,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(d(166));if(n=a1(a0.current),a1(aX.current),ab(t)){if(r=t.stateNode,n=t.memoizedProps,r[rA]=t,(u=r.nodeValue!==n)&&null!==(e=au))switch(e.tag){case 3:rg(r.nodeValue,n,0!=(1&e.mode));break;case 5:!0!==e.memoizedProps.suppressHydrationWarning&&rg(r.nodeValue,n,0!=(1&e.mode))}u&&(t.flags|=4)}else(r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[rA]=t,t.stateNode=r}return iO(t),null;case 13:if(rU(a8),r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(ad&&null!==ac&&0!=(1&t.mode)&&0==(128&t.flags))av(),ax(),t.flags|=98560,u=!1;else if(u=ab(t),null!==r&&null!==r.dehydrated){if(null===e){if(!u)throw Error(d(318));if(!(u=null!==(u=t.memoizedState)?u.dehydrated:null))throw Error(d(317));u[rA]=t}else ax(),0==(128&t.flags)&&(t.memoizedState=null),t.flags|=4;iO(t),u=!1}else null!==af&&(lC(af),af=null),u=!0;if(!u)return 65536&t.flags?t:null}if(0!=(128&t.flags))return t.lanes=n,t;return(r=null!==r)!=(null!==e&&null!==e.memoizedState)&&r&&(t.child.flags|=8192,0!=(1&t.mode)&&(null===e||0!=(1&a8.current)?0===le&&(le=3):lI())),null!==t.updateQueue&&(t.flags|=4),iO(t),null;case 4:return a3(),o(e,t),null===e&&ro(t.stateNode.containerInfo),iO(t),null;case 10:return aR(t.type._context),iO(t),null;case 19:if(rU(a8),null===(u=t.memoizedState))return iO(t),null;if(r=0!=(128&t.flags),null===(c=u.rendering)){if(r)iA(u,!1);else{if(0!==le||null!==e&&0!=(128&e.flags))for(e=t.child;null!==e;){if(null!==(c=a6(e))){for(t.flags|=128,iA(u,!1),null!==(r=c.updateQueue)&&(t.updateQueue=r,t.flags|=4),t.subtreeFlags=0,r=n,n=t.child;null!==n;)u=n,e=r,u.flags&=0xe00002,null===(c=u.alternate)?(u.childLanes=0,u.lanes=e,u.child=null,u.subtreeFlags=0,u.memoizedProps=null,u.memoizedState=null,u.updateQueue=null,u.dependencies=null,u.stateNode=null):(u.childLanes=c.childLanes,u.lanes=c.lanes,u.child=c.child,u.subtreeFlags=0,u.deletions=null,u.memoizedProps=c.memoizedProps,u.memoizedState=c.memoizedState,u.updateQueue=c.updateQueue,u.type=c.type,e=c.dependencies,u.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return rH(a8,1&a8.current|2),t.child}e=e.sibling}null!==u.tail&&eJ()>ls&&(t.flags|=128,r=!0,iA(u,!1),t.lanes=4194304)}}else{if(!r){if(null!==(e=a6(c))){if(t.flags|=128,r=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),iA(u,!0),null===u.tail&&"hidden"===u.tailMode&&!c.alternate&&!ad)return iO(t),null}else 2*eJ()-u.renderingStartTime>ls&&0x40000000!==n&&(t.flags|=128,r=!0,iA(u,!1),t.lanes=4194304)}u.isBackwards?(c.sibling=t.child,t.child=c):(null!==(n=u.last)?n.sibling=c:t.child=c,u.last=c)}if(null!==u.tail)return t=u.tail,u.rendering=t,u.tail=t.sibling,u.renderingStartTime=eJ(),t.sibling=null,n=a8.current,rH(a8,r?1&n|2:1&n),t;return iO(t),null;case 22:case 23:return lP(),r=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==r&&(t.flags|=8192),r&&0!=(1&t.mode)?0!=(0x40000000&i5)&&(iO(t),6&t.subtreeFlags&&(t.flags|=8192)):iO(t),null;case 24:case 25:return null}throw Error(d(156,t.tag))}(n,t,i5))){i8=n;return}}else{if(null!==(n=function(e,t){switch(as(t),t.tag){case 1:return rY(t.type)&&rK(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return a3(),rU(rV),rU(rW),a7(),0!=(65536&(e=t.flags))&&0==(128&e)?(t.flags=-65537&e|128,t):null;case 5:return a9(t),null;case 13:if(rU(a8),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(d(340));ax()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return rU(a8),null;case 4:return a3(),null;case 10:return aR(t.type._context),null;case 22:case 23:return lP(),null;default:return null}}(n,t))){n.flags&=32767,i8=n;return}if(null!==e)e.flags|=32768,e.subtreeFlags=0,e.deletions=null;else{le=6,i8=null;return}}if(null!==(t=t.sibling)){i8=t;return}i8=t=e}while(null!==t);0===le&&(le=5)}function lz(e,t,n){var r=tc,a=i3.transition;try{i3.transition=null,tc=1,function(e,t,n,r){do l$();while(null!==lh);if(0!=(6&i4))throw Error(d(327));n=e.finishedWork;var a=e.finishedLanes;if(null===n)return;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(d(177));e.callbackNode=null,e.callbackPriority=0;var o=n.lanes|n.childLanes;if(!function(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0<n;){var a=31-e5(n),o=1<<a;t[a]=0,r[a]=-1,e[a]=-1,n&=~o}}(e,o),e===i9&&(i8=i9=null,i6=0),0==(2064&n.subtreeFlags)&&0==(2064&n.flags)||lp||(lp=!0,lG(e3,function(){return l$(),null})),o=0!=(15990&n.flags),0!=(15990&n.subtreeFlags)||o){o=i3.transition,i3.transition=null;var i,l,s,u=tc;tc=1;var c=i4;i4|=4,i2.current=null,!function(e,t){if(ry=tI,nB(e=n$())){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{var r=(n=(n=e.ownerDocument)&&n.defaultView||window).getSelection&&n.getSelection();if(r&&0!==r.rangeCount){n=r.anchorNode;var a,o=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch(e){n=null;break e}var l=0,s=-1,u=-1,c=0,f=0,p=e,h=null;t:for(;;){for(;p!==n||0!==o&&3!==p.nodeType||(s=l+o),p!==i||0!==r&&3!==p.nodeType||(u=l+r),3===p.nodeType&&(l+=p.nodeValue.length),null!==(a=p.firstChild);){;h=p,p=a}for(;;){if(p===e)break t;if(h===n&&++c===o&&(s=l),h===i&&++f===r&&(u=l),null!==(a=p.nextSibling))break;h=(p=h).parentNode}p=a}n=-1===s||-1===u?null:{start:s,end:u}}else n=null}n=n||{start:0,end:0}}else n=null;for(rb={focusedElem:e,selectionRange:n},tI=!1,iR=t;null!==iR;)if(e=(t=iR).child,0!=(1028&t.subtreeFlags)&&null!==e)e.return=t,iR=e;else for(;null!==iR;){t=iR;try{var g=t.alternate;if(0!=(1024&t.flags))switch(t.tag){case 0:case 11:case 15:case 5:case 6:case 4:case 17:break;case 1:if(null!==g){var m=g.memoizedProps,y=g.memoizedState,b=t.stateNode,v=b.getSnapshotBeforeUpdate(t.elementType===t.type?m:oX(t.type,m),y);b.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var x=t.stateNode.containerInfo;1===x.nodeType?x.textContent="":9===x.nodeType&&x.documentElement&&x.removeChild(x.documentElement);break;default:throw Error(d(163))}}catch(e){lU(t,t.return,e)}if(null!==(e=t.sibling)){e.return=t.return,iR=e;break}iR=t.return}g=iF,iF=!1}(e,n),iY(n,e),!function(e){var t=n$(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&function e(t,n){return!!t&&!!n&&(t===n||(!t||3!==t.nodeType)&&(n&&3===n.nodeType?e(t,n.parentNode):"contains"in t?t.contains(n):!!t.compareDocumentPosition&&!!(16&t.compareDocumentPosition(n))))}(n.ownerDocument.documentElement,n)){if(null!==r&&nB(n)){if(t=r.start,void 0===(e=r.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var a=n.textContent.length,o=Math.min(r.start,a);r=void 0===r.end?o:Math.min(r.end,a),!e.extend&&o>r&&(a=r,r=o,o=a),a=nz(n,o);var i=nz(n,r);a&&i&&(1!==e.rangeCount||e.anchorNode!==a.node||e.anchorOffset!==a.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&((t=t.createRange()).setStart(a.node,a.offset),e.removeAllRanges(),o>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n<t.length;n++)(e=t[n]).element.scrollLeft=e.left,e.element.scrollTop=e.top}}(rb),tI=!!ry,rb=ry=null,e.current=n,i=n,l=e,s=a,iR=i,function e(t,n,r){for(var a=0!=(1&t.mode);null!==iR;){var o=iR,i=o.child;if(22===o.tag&&a){var l=null!==o.memoizedState||iP;if(!l){var s=o.alternate,u=null!==s&&null!==s.memoizedState||ij;s=iP;var c=ij;if(iP=l,(ij=u)&&!c)for(iR=o;null!==iR;)u=(l=iR).child,22===l.tag&&null!==l.memoizedState?iJ(o):null!==u?(u.return=l,iR=u):iJ(o);for(;null!==i;)iR=i,e(i,n,r),i=i.sibling;iR=o,iP=s,ij=c}iQ(t,n,r)}else 0!=(8772&o.subtreeFlags)&&null!==i?(i.return=o,iR=i):iQ(t,n,r)}}(i,l,s),eX(),i4=c,tc=u,i3.transition=o}else e.current=n;if(lp&&(lp=!1,lh=e,lg=a),0===(o=e.pendingLanes)&&(lf=null),!function(e){if(e6&&"function"==typeof e6.onCommitFiberRoot)try{e6.onCommitFiberRoot(e8,e,void 0,128==(128&e.current.flags))}catch(e){}}(n.stateNode,r),lS(e,eJ()),null!==t)for(r=e.onRecoverableError,n=0;n<t.length;n++)r((a=t[n]).value,{componentStack:a.stack,digest:a.digest});if(lc)throw lc=!1,e=ld,ld=null,e;0!=(1&lg)&&0!==e.tag&&l$(),0!=(1&(o=e.pendingLanes))?e===ly?lm++:(lm=0,ly=e):lm=0,r9()}(e,t,n,r)}finally{i3.transition=a,tc=r}return null}function l$(){if(null!==lh){var e=td(lg),t=i3.transition,n=tc;try{if(i3.transition=null,tc=16>e?16:e,null===lh)var r=!1;else{if(e=lh,lh=null,lg=0,0!=(6&i4))throw Error(d(331));var a=i4;for(i4|=4,iR=e.current;null!==iR;){var o=iR,i=o.child;if(0!=(16&iR.flags)){var l=o.deletions;if(null!==l){for(var s=0;s<l.length;s++){var u=l[s];for(iR=u;null!==iR;){var c=iR;switch(c.tag){case 0:case 11:case 15:iD(8,c,o)}var f=c.child;if(null!==f)f.return=c,iR=f;else for(;null!==iR;){var p=(c=iR).sibling,h=c.return;if(!function e(t){var n=t.alternate;null!==n&&(t.alternate=null,e(n)),t.child=null,t.deletions=null,t.sibling=null,5===t.tag&&null!==(n=t.stateNode)&&(delete n[rA],delete n[rO],delete n[rj],delete n[rL],delete n[rR]),t.stateNode=null,t.return=null,t.dependencies=null,t.memoizedProps=null,t.memoizedState=null,t.pendingProps=null,t.stateNode=null,t.updateQueue=null}(c),c===u){iR=null;break}if(null!==p){p.return=h,iR=p;break}iR=h}}}var g=o.alternate;if(null!==g){var m=g.child;if(null!==m){g.child=null;do{var y=m.sibling;m.sibling=null,m=y}while(null!==m)}}iR=o}}if(0!=(2064&o.subtreeFlags)&&null!==i)i.return=o,iR=i;else for(;null!==iR;){if(o=iR,0!=(2048&o.flags))switch(o.tag){case 0:case 11:case 15:iD(9,o,o.return)}var b=o.sibling;if(null!==b){b.return=o.return,iR=b;break}iR=o.return}}var v=e.current;for(iR=v;null!==iR;){var x=(i=iR).child;if(0!=(2064&i.subtreeFlags)&&null!==x)x.return=i,iR=x;else for(i=v;null!==iR;){if(l=iR,0!=(2048&l.flags))try{switch(l.tag){case 0:case 11:case 15:iz(9,l)}}catch(e){lU(l,l.return,e)}if(l===i){iR=null;break}var w=l.sibling;if(null!==w){w.return=l.return,iR=w;break}iR=l.return}}if(i4=a,r9(),e6&&"function"==typeof e6.onPostCommitFiberRoot)try{e6.onPostCommitFiberRoot(e8,e)}catch(e){}r=!0}return r}finally{tc=n,i3.transition=t}}return!1}function lB(e,t,n){t=o7(e,t=o9(n,t),1),e=aV(e,t,1),t=lx(),null!==e&&(ts(e,1,t),lS(e,t))}function lU(e,t,n){if(3===e.tag)lB(e,e,n);else for(;null!==t;){if(3===t.tag){lB(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"==typeof t.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===lf||!lf.has(r))){e=ie(t,e=o9(n,e),1),t=aV(t,e,1),e=lx(),null!==t&&(ts(t,1,e),lS(t,e));break}}t=t.return}}function lH(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=lx(),e.pingedLanes|=e.suspendedLanes&n,i9===e&&(i6&n)===n&&(4===le||3===le&&(0x7c00000&i6)===i6&&500>eJ()-ll?lj(e,0):la|=n),lS(e,t)}function lZ(e,t){0===t&&(0==(1&e.mode)?t=1:(t=tn,0==(0x7c00000&(tn<<=1))&&(tn=4194304)));var n=lx();null!==(e=aB(e,t))&&(ts(e,t,n),lS(e,n))}function lW(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),lZ(e,n)}function lV(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,a=e.memoizedState;null!==a&&(n=a.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(d(314))}null!==r&&r.delete(t),lZ(e,n)}function lG(e,t){return eY(e,t)}function lq(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function lY(e,t,n,r){return new lq(e,t,n,r)}function lK(e){return!(!(e=e.prototype)||!e.isReactComponent)}s=function(e,t,n){if(null!==e){if(e.memoizedProps!==t.pendingProps||rV.current)ii=!0;else{if(0==(e.lanes&n)&&0==(128&t.flags))return ii=!1,function(e,t,n){switch(t.tag){case 3:iy(t),ax();break;case 5:a4(t);break;case 1:rY(t.type)&&rJ(t);break;case 4:a2(t,t.stateNode.containerInfo);break;case 10:var r=t.type._context,a=t.memoizedProps.value;rH(aA,r._currentValue),r._currentValue=a;break;case 13:if(null!==(r=t.memoizedState)){if(null!==r.dehydrated)return rH(a8,1&a8.current),t.flags|=128,null;if(0!=(n&t.child.childLanes))return iw(e,t,n);return rH(a8,1&a8.current),null!==(e=iN(e,t,n))?e.sibling:null}rH(a8,1&a8.current);break;case 19:if(r=0!=(n&t.childLanes),0!=(128&e.flags)){if(r)return iC(e,t,n);t.flags|=128}if(null!==(a=t.memoizedState)&&(a.rendering=null,a.tail=null,a.lastEffect=null),rH(a8,a8.current),!r)return null;break;case 22:case 23:return t.lanes=0,id(e,t,n)}return iN(e,t,n)}(e,t,n);ii=0!=(131072&e.flags)}}else ii=!1,ad&&0!=(1048576&t.flags)&&ai(t,r7,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;iT(e,t),e=t.pendingProps;var a=rq(t,rW.current);aM(t,n),a=of(null,t,r,e,a,n);var o=op();return t.flags|=1,"object"==typeof a&&null!==a&&"function"==typeof a.render&&void 0===a.$$typeof?(t.tag=1,t.memoizedState=null,t.updateQueue=null,rY(r)?(o=!0,rJ(t)):o=!1,t.memoizedState=null!==a.state&&void 0!==a.state?a.state:null,aH(t),a.updater=o0,t.stateNode=a,a._reactInternals=t,o4(t,r,e,n),t=im(null,t,r,!0,o,n)):(t.tag=0,ad&&o&&al(t),il(null,t,a,n),t=t.child),t;case 16:r=t.elementType;e:{switch(iT(e,t),e=t.pendingProps,r=(a=r._init)(r._payload),t.type=r,a=t.tag=function(e){if("function"==typeof e)return lK(e)?1:0;if(null!=e){if((e=e.$$typeof)===R)return 11;if(e===F)return 14}return 2}(r),e=oX(r,e),a){case 0:t=ih(null,t,r,e,n);break e;case 1:t=ig(null,t,r,e,n);break e;case 11:t=is(null,t,r,e,n);break e;case 14:t=iu(null,t,r,oX(r.type,e),n);break e}throw Error(d(306,r,""))}return t;case 0:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:oX(r,a),ih(e,t,r,a,n);case 1:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:oX(r,a),ig(e,t,r,a,n);case 3:e:{if(iy(t),null===e)throw Error(d(387));r=t.pendingProps,a=(o=t.memoizedState).element,aZ(e,t),aY(t,r,null,n);var i=t.memoizedState;if(r=i.element,o.isDehydrated){if(o={element:r,isDehydrated:!1,cache:i.cache,pendingSuspenseBoundaries:i.pendingSuspenseBoundaries,transitions:i.transitions},t.updateQueue.baseState=o,t.memoizedState=o,256&t.flags){a=o9(Error(d(423)),t),t=ib(e,t,r,n,a);break e}else if(r!==a){a=o9(Error(d(424)),t),t=ib(e,t,r,n,a);break e}else for(ac=rC(t.stateNode.containerInfo.firstChild),au=t,ad=!0,af=null,n=aN(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|4096,n=n.sibling}else{if(ax(),r===a){t=iN(e,t,n);break e}il(e,t,r,n)}t=t.child}return t;case 5:return a4(t),null===e&&am(t),r=t.type,a=t.pendingProps,o=null!==e?e.memoizedProps:null,i=a.children,rv(r,a)?i=null:null!==o&&rv(r,o)&&(t.flags|=32),ip(e,t),il(e,t,i,n),t.child;case 6:return null===e&&am(t),null;case 13:return iw(e,t,n);case 4:return a2(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=aT(t,null,r,n):il(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:oX(r,a),is(e,t,r,a,n);case 7:return il(e,t,t.pendingProps,n),t.child;case 8:case 12:return il(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,a=t.pendingProps,o=t.memoizedProps,i=a.value,rH(aA,r._currentValue),r._currentValue=i,null!==o){if(nM(o.value,i)){if(o.children===a.children&&!rV.current){t=iN(e,t,n);break e}}else for(null!==(o=t.child)&&(o.return=t);null!==o;){var l=o.dependencies;if(null!==l){i=o.child;for(var s=l.firstContext;null!==s;){if(s.context===r){if(1===o.tag){(s=aW(-1,n&-n)).tag=2;var u=o.updateQueue;if(null!==u){var c=(u=u.shared).pending;null===c?s.next=s:(s.next=c.next,c.next=s),u.pending=s}}o.lanes|=n,null!==(s=o.alternate)&&(s.lanes|=n),aI(o.return,n,t),l.lanes|=n;break}s=s.next}}else if(10===o.tag)i=o.type===t.type?null:o.child;else if(18===o.tag){if(null===(i=o.return))throw Error(d(341));i.lanes|=n,null!==(l=i.alternate)&&(l.lanes|=n),aI(i,n,t),i=o.sibling}else i=o.child;if(null!==i)i.return=o;else for(i=o;null!==i;){if(i===t){i=null;break}if(null!==(o=i.sibling)){o.return=i.return,i=o;break}i=i.return}o=i}}il(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=t.pendingProps.children,aM(t,n),r=r(a=aF(a)),t.flags|=1,il(e,t,r,n),t.child;case 14:return a=oX(r=t.type,t.pendingProps),a=oX(r.type,a),iu(e,t,r,a,n);case 15:return ic(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:oX(r,a),iT(e,t),t.tag=1,rY(r)?(e=!0,rJ(t)):e=!1,aM(t,n),o2(t,r,a),o4(t,r,a,n),im(null,t,r,!0,e,n);case 19:return iC(e,t,n);case 22:return id(e,t,n)}throw Error(d(156,t.tag))};function lQ(e,t){var n=e.alternate;return null===n?((n=lY(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=0xe00000&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function lX(e,t,n,r,a,o){var i=2;if(r=e,"function"==typeof e)lK(e)&&(i=1);else if("string"==typeof e)i=5;else e:switch(e){case A:return lJ(n.children,a,o,t);case O:i=8,a|=8;break;case P:return(e=lY(12,n,t,2|a)).elementType=P,e.lanes=o,e;case I:return(e=lY(13,n,t,a)).elementType=I,e.lanes=o,e;case M:return(e=lY(19,n,t,a)).elementType=M,e.lanes=o,e;case z:return l0(n,a,o,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case j:i=10;break e;case L:i=9;break e;case R:i=11;break e;case F:i=14;break e;case D:i=16,r=null;break e}throw Error(d(130,null==e?e:typeof e,""))}return(t=lY(i,n,t,a)).elementType=e,t.type=r,t.lanes=o,t}function lJ(e,t,n,r){return(e=lY(7,e,r,t)).lanes=n,e}function l0(e,t,n,r){return(e=lY(22,e,r,t)).elementType=z,e.lanes=n,e.stateNode={isHidden:!1},e}function l1(e,t,n){return(e=lY(6,e,null,t)).lanes=n,e}function l2(e,t,n){return(t=lY(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function l3(e,t,n,r,a){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=tl(0),this.expirationTimes=tl(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=tl(0),this.identifierPrefix=r,this.onRecoverableError=a,this.mutableSourceEagerHydrationData=null}function l4(e,t,n,r,a,o,i,l,s){return e=new l3(e,t,n,l,s),1===t?(t=1,!0===o&&(t|=8)):t=0,o=lY(3,null,null,t),e.current=o,o.stateNode=e,o.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},aH(o),e}function l9(e){if(!e)return rZ;e=e._reactInternals;e:{if(eW(e)!==e||1!==e.tag)throw Error(d(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(rY(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(d(171))}if(1===e.tag){var n=e.type;if(rY(n))return rX(e,n,t)}return t}function l8(e,t,n,r,a,o,i,l,s){return(e=l4(n,r,!0,e,a,o,i,l,s)).context=l9(null),n=e.current,r=lx(),(o=aW(r,a=lw(n))).callback=null!=t?t:null,aV(n,o,a),e.current.lanes=a,ts(e,a,r),lS(e,r),e}function l6(e,t,n,r){var a=t.current,o=lx(),i=lw(a);return n=l9(n),null===t.context?t.context=n:t.pendingContext=n,(t=aW(o,i)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),null!==(e=aV(a,t,i))&&(lk(e,a,i,o),aG(e,a,i)),i}function l5(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function l7(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function se(e,t){l7(e,t),(e=e.alternate)&&l7(e,t)}var st="function"==typeof reportError?reportError:function(e){console.error(e)};function sn(e){this._internalRoot=e}function sr(e){this._internalRoot=e}function sa(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType)}function so(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function si(){}sr.prototype.render=sn.prototype.render=function(e){var t=this._internalRoot;if(null===t)throw Error(d(409));l6(e,t,null,null)},sr.prototype.unmount=sn.prototype.unmount=function(){var e=this._internalRoot;if(null!==e){this._internalRoot=null;var t=e.containerInfo;lO(function(){l6(null,e,null,null)}),t[rP]=null}},sr.prototype.unstable_scheduleHydration=function(e){if(e){var t=tg();e={blockedOn:null,target:e,priority:t};for(var n=0;n<tE.length&&0!==t&&t<tE[n].priority;n++);tE.splice(n,0,e),0===n&&tN(e)}};function sl(e,t,n,r,a){var o=n._reactRootContainer;if(o){var i=o;if("function"==typeof a){var l=a;a=function(){var e=l5(i);l.call(e)}}l6(t,i,e,a)}else i=function(e,t,n,r,a){if(a){if("function"==typeof r){var o=r;r=function(){var e=l5(i);o.call(e)}}var i=l8(t,r,e,0,null,!1,!1,"",si);return e._reactRootContainer=i,e[rP]=i.current,ro(8===e.nodeType?e.parentNode:e),lO(),i}for(;a=e.lastChild;)e.removeChild(a);if("function"==typeof r){var l=r;r=function(){var e=l5(s);l.call(e)}}var s=l4(e,0,!1,null,null,!1,!1,"",si);return e._reactRootContainer=s,e[rP]=s.current,ro(8===e.nodeType?e.parentNode:e),lO(function(){l6(t,s,n,r)}),s}(n,t,e,a,r);return l5(i)}tf=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var n=tr(t.pendingLanes);0!==n&&(tu(t,1|n),lS(t,eJ()),0==(6&i4)&&(ls=eJ()+500,r9()))}break;case 13:lO(function(){var t=aB(e,1);null!==t&&lk(t,e,1,lx())}),se(e,1)}},tp=function(e){if(13===e.tag){var t=aB(e,0x8000000);null!==t&&lk(t,e,0x8000000,lx()),se(e,0x8000000)}},th=function(e){if(13===e.tag){var t=lw(e),n=aB(e,t);null!==n&&lk(n,e,t,lx()),se(e,t)}},tg=function(){return tc},tm=function(e,t){var n=tc;try{return tc=e,t()}finally{tc=n}},e_=function(e,t,n){switch(t){case"input":if(et(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var a=rD(r);if(!a)throw Error(d(90));K(r),et(r,a)}}}break;case"textarea":es(e,n);break;case"select":null!=(t=n.value)&&eo(e,!!n.multiple,t,!1)}},eP=lA,ej=lO;var ss={findFiberByHostInstance:rI,bundleType:0,version:"18.3.1",rendererPackageName:"react-dom"},su={bundleType:ss.bundleType,version:ss.version,rendererPackageName:ss.rendererPackageName,rendererConfig:ss.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:C.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=eq(e))?null:e.stateNode},findFiberByHostInstance:ss.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.3.1-next-f1338f8080-20240426"};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var sc=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!sc.isDisabled&&sc.supportsFiber)try{e8=sc.inject(su),e6=sc}catch(e){}}t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED={usingClientEntryPoint:!1,Events:[rM,rF,rD,eA,eO,lA]},t.createPortal=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!sa(t))throw Error(d(200));return function(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:N,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}(e,t,null,n)},t.createRoot=function(e,t){if(!sa(e))throw Error(d(299));var n=!1,r="",a=st;return null!=t&&(!0===t.unstable_strictMode&&(n=!0),void 0!==t.identifierPrefix&&(r=t.identifierPrefix),void 0!==t.onRecoverableError&&(a=t.onRecoverableError)),t=l4(e,1,!1,null,null,n,!1,r,a),e[rP]=t.current,ro(8===e.nodeType?e.parentNode:e),new sn(t)},t.findDOMNode=function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=e._reactInternals;if(void 0===t){if("function"==typeof e.render)throw Error(d(188));throw Error(d(268,e=Object.keys(e).join(",")))}return e=null===(e=eq(t))?null:e.stateNode},t.flushSync=function(e){return lO(e)},t.hydrate=function(e,t,n){if(!so(t))throw Error(d(200));return sl(null,e,t,!0,n)},t.hydrateRoot=function(e,t,n){if(!sa(e))throw Error(d(405));var r=null!=n&&n.hydratedSources||null,a=!1,o="",i=st;if(null!=n&&(!0===n.unstable_strictMode&&(a=!0),void 0!==n.identifierPrefix&&(o=n.identifierPrefix),void 0!==n.onRecoverableError&&(i=n.onRecoverableError)),t=l8(t,null,e,1,null!=n?n:null,a,!1,o,i),e[rP]=t.current,ro(e),r)for(e=0;e<r.length;e++)a=(a=(n=r[e])._getVersion)(n._source),null==t.mutableSourceEagerHydrationData?t.mutableSourceEagerHydrationData=[n,a]:t.mutableSourceEagerHydrationData.push(n,a);return new sr(t)},t.render=function(e,t,n){if(!so(t))throw Error(d(200));return sl(null,e,t,!1,n)},t.unmountComponentAtNode=function(e){if(!so(e))throw Error(d(40));return!!e._reactRootContainer&&(lO(function(){sl(null,null,e,!1,function(){e._reactRootContainer=null,e[rP]=null})}),!0)},t.unstable_batchedUpdates=lA,t.unstable_renderSubtreeIntoContainer=function(e,t,n,r){if(!so(n))throw Error(d(200));if(null==e||void 0===e._reactInternals)throw Error(d(38));return sl(e,t,n,!1,r)},t.version="18.3.1-next-f1338f8080-20240426"},745:function(e,t,n){"use strict";var r=n(3935);t.createRoot=r.createRoot,t.hydrateRoot=r.hydrateRoot},3935:function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),e.exports=n(4448)},9590:function(e){var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,a="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;e.exports=function(e,o){try{return function e(o,i){if(o===i)return!0;if(o&&i&&"object"==typeof o&&"object"==typeof i){var l,s,u,c;if(o.constructor!==i.constructor)return!1;if(Array.isArray(o)){if((l=o.length)!=i.length)return!1;for(s=l;0!=s--;)if(!e(o[s],i[s]))return!1;return!0}if(n&&o instanceof Map&&i instanceof Map){if(o.size!==i.size)return!1;for(c=o.entries();!(s=c.next()).done;)if(!i.has(s.value[0]))return!1;for(c=o.entries();!(s=c.next()).done;)if(!e(s.value[1],i.get(s.value[0])))return!1;return!0}if(r&&o instanceof Set&&i instanceof Set){if(o.size!==i.size)return!1;for(c=o.entries();!(s=c.next()).done;)if(!i.has(s.value[0]))return!1;return!0}if(a&&ArrayBuffer.isView(o)&&ArrayBuffer.isView(i)){if((l=o.length)!=i.length)return!1;for(s=l;0!=s--;)if(o[s]!==i[s])return!1;return!0}if(o.constructor===RegExp)return o.source===i.source&&o.flags===i.flags;if(o.valueOf!==Object.prototype.valueOf&&"function"==typeof o.valueOf&&"function"==typeof i.valueOf)return o.valueOf()===i.valueOf();if(o.toString!==Object.prototype.toString&&"function"==typeof o.toString&&"function"==typeof i.toString)return o.toString()===i.toString();if((l=(u=Object.keys(o)).length)!==Object.keys(i).length)return!1;for(s=l;0!=s--;)if(!Object.prototype.hasOwnProperty.call(i,u[s]))return!1;if(t&&o instanceof Element)return!1;for(s=l;0!=s--;){if("_owner"!==u[s]&&"__v"!==u[s]&&"__o"!==u[s]||!o.$$typeof){if(!e(o[u[s]],i[u[s]]))return!1}}return!0}return o!=o&&i!=i}(e,o)}catch(e){if((e.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw e}}},405:function(e,t,n){"use strict";n.d(t,{B6:function(){return H},ql:function(){return Q}});var r=n(7294),a=n(5697),o=n.n(a),i=n(9590),l=n.n(i),s=n(1143),u=n.n(s),c=n(6774),d=n.n(c);function f(){return(f=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function p(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,h(e,t)}function h(e,t){return(h=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function g(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(a[n]=e[n]);return a}var m={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},y={rel:["amphtml","canonical","alternate"]},b={type:["application/ld+json"]},v={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},x=Object.keys(m).map(function(e){return m[e]}),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(w).reduce(function(e,t){return e[w[t]]=t,e},{}),S=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},E=function(e){var t=S(e,m.TITLE),n=S(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,function(){return t});var r=S(e,"defaultTitle");return t||r||void 0},_=function(e,t){return t.filter(function(t){return void 0!==t[e]}).map(function(t){return t[e]}).reduce(function(e,t){return f({},e,t)},{})},C=function(e,t,n){var r={};return n.filter(function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)}).map(function(t){return t[e]}).reverse().reduce(function(e,n){var a={};n.filter(function(e){for(var n,o=Object.keys(e),i=0;i<o.length;i+=1){var l=o[i],s=l.toLowerCase();-1===t.indexOf(s)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===s&&"stylesheet"===e[s].toLowerCase()||(n=s),-1===t.indexOf(l)||"innerHTML"!==l&&"cssText"!==l&&"itemprop"!==l||(n=l)}if(!n||!e[n])return!1;var u=e[n].toLowerCase();return r[n]||(r[n]={}),a[n]||(a[n]={}),!r[n][u]&&(a[n][u]=!0,!0)}).reverse().forEach(function(t){return e.push(t)});for(var o=Object.keys(a),i=0;i<o.length;i+=1){var l=o[i],s=f({},r[l],a[l]);r[l]=s}return e},[]).reverse()},T=function(e,t){if(Array.isArray(e)&&e.length){for(var n=0;n<e.length;n+=1)if(e[n][t])return!0}return!1},N=function(e){return Array.isArray(e)?e.join(""):e},A=function(e,t){return Array.isArray(e)?e.reduce(function(e,n){return!function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.default.push(n):e.priority.push(n),e},{priority:[],default:[]}):{default:e}},O=function(e,t){var n;return f({},e,((n={})[t]=void 0,n))},P=[m.NOSCRIPT,m.SCRIPT,m.STYLE],j=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},L=function(e){return Object.keys(e).reduce(function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r},"")},R=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce(function(t,n){return t[w[n]||n]=e[n],t},t)},I=function(e,t){return t.map(function(t,n){var a,o=((a={key:n})["data-rh"]=!0,a);return Object.keys(t).forEach(function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]}),r.createElement(e,o)})},M=function(e,t,n){switch(e){case m.TITLE:return{toComponent:function(){var e,n,a,o;return n=t.titleAttributes,(a={key:e=t.title})["data-rh"]=!0,o=R(n,a),[r.createElement(m.TITLE,o,e)]},toString:function(){var r,a,o,i,l,s;return r=e,a=t.title,o=t.titleAttributes,i=n,l=L(o),s=N(a),l?"<"+r+' data-rh="true" '+l+">"+j(s,i)+"</"+r+">":"<"+r+' data-rh="true">'+j(s,i)+"</"+r+">"}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return R(t)},toString:function(){return L(t)}};default:return{toComponent:function(){return I(e,t)},toString:function(){var r,a,o;return r=e,a=t,o=n,a.reduce(function(e,t){var n=Object.keys(t).filter(function(e){return!("innerHTML"===e||"cssText"===e)}).reduce(function(e,n){var r=void 0===t[n]?n:n+'="'+j(t[n],o)+'"';return e?e+" "+r:r},""),a=t.innerHTML||t.cssText||"",i=-1===P.indexOf(r);return e+"<"+r+' data-rh="true" '+n+(i?"/>":">"+a+"</"+r+">")},"")}}}},F=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,a=e.htmlAttributes,o=e.noscriptTags,i=e.styleTags,l=e.title,s=e.titleAttributes,u=e.linkTags,c=e.metaTags,d=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var p,h,g,x,w,k,S,E=(h=(p=e).linkTags,g=p.scriptTags,x=p.encode,w=A(p.metaTags,v),k=A(h,y),S=A(g,b),{priorityMethods:{toComponent:function(){return[].concat(I(m.META,w.priority),I(m.LINK,k.priority),I(m.SCRIPT,S.priority))},toString:function(){return M(m.META,w.priority,x)+" "+M(m.LINK,k.priority,x)+" "+M(m.SCRIPT,S.priority,x)}},metaTags:w.default,linkTags:k.default,scriptTags:S.default});f=E.priorityMethods,u=E.linkTags,c=E.metaTags,d=E.scriptTags}return{priority:f,base:M(m.BASE,t,r),bodyAttributes:M("bodyAttributes",n,r),htmlAttributes:M("htmlAttributes",a,r),link:M(m.LINK,u,r),meta:M(m.META,c,r),noscript:M(m.NOSCRIPT,o,r),script:M(m.SCRIPT,d,r),style:M(m.STYLE,i,r),title:M(m.TITLE,{title:void 0===l?"":l,titleAttributes:s},r)}},D=[],z=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?D:n.instances},add:function(e){(n.canUseDOM?D:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?D:n.instances).indexOf(e);(n.canUseDOM?D:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=F({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},$=r.createContext({}),B=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),U="undefined"!=typeof document,H=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new z(r.props.context,t.canUseDOM),r}return p(t,e),t.prototype.render=function(){return r.createElement($.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);H.canUseDOM=U,H.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},H.defaultProps={context:{}},H.displayName="HelmetProvider";var Z=function(e,t){var n,r=document.head||document.querySelector(m.HEAD),a=r.querySelectorAll(e+"[data-rh]"),o=[].slice.call(a),i=[];return t&&t.length&&t.forEach(function(t){var r=document.createElement(e);for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&("innerHTML"===a?r.innerHTML=t.innerHTML:"cssText"===a?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(a,void 0===t[a]?"":t[a]));r.setAttribute("data-rh","true"),o.some(function(e,t){return n=t,r.isEqualNode(e)})?o.splice(n,1):i.push(r)}),o.forEach(function(e){return e.parentNode.removeChild(e)}),i.forEach(function(e){return r.appendChild(e)}),{oldTags:o,newTags:i}},W=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),a=r?r.split(","):[],o=[].concat(a),i=Object.keys(t),l=0;l<i.length;l+=1){var s=i[l],u=t[s]||"";n.getAttribute(s)!==u&&n.setAttribute(s,u),-1===a.indexOf(s)&&a.push(s);var c=o.indexOf(s);-1!==c&&o.splice(c,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);a.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},V=function(e,t){var n,r,a=e.baseTag,o=e.htmlAttributes,i=e.linkTags,l=e.metaTags,s=e.noscriptTags,u=e.onChangeClientState,c=e.scriptTags,d=e.styleTags,f=e.title,p=e.titleAttributes;W(m.BODY,e.bodyAttributes),W(m.HTML,o),n=f,r=p,void 0!==n&&document.title!==n&&(document.title=N(n)),W(m.TITLE,r);var h={baseTag:Z(m.BASE,a),linkTags:Z(m.LINK,i),metaTags:Z(m.META,l),noscriptTags:Z(m.NOSCRIPT,s),scriptTags:Z(m.SCRIPT,c),styleTags:Z(m.STYLE,d)},g={},y={};Object.keys(h).forEach(function(e){var t=h[e],n=t.newTags,r=t.oldTags;n.length&&(g[e]=n),r.length&&(y[e]=h[e].oldTags)}),t&&t(),u(e,g,y)},G=null,q=function(e){function t(){for(var t,n=arguments.length,r=Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,a=null,o={baseTag:(e=["href"],(t=n.helmetInstances.get().map(function(e){var t=f({},e.props);return delete t.context,t})).filter(function(e){return void 0!==e[m.BASE]}).map(function(e){return e[m.BASE]}).reverse().reduce(function(t,n){if(!t.length)for(var r=Object.keys(n),a=0;a<r.length;a+=1){var o=r[a].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t},[])),bodyAttributes:_("bodyAttributes",t),defer:S(t,"defer"),encode:S(t,"encodeSpecialCharacters"),htmlAttributes:_("htmlAttributes",t),linkTags:C(m.LINK,["rel","href"],t),metaTags:C(m.META,["name","charset","http-equiv","property","itemprop"],t),noscriptTags:C(m.NOSCRIPT,["innerHTML"],t),onChangeClientState:S(t,"onChangeClientState")||function(){},scriptTags:C(m.SCRIPT,["src","innerHTML"],t),styleTags:C(m.STYLE,["cssText"],t),title:E(t),titleAttributes:_("titleAttributes",t),prioritizeSeoTags:T(t,"prioritizeSeoTags")};H.canUseDOM?(G&&cancelAnimationFrame(G),o.defer?G=requestAnimationFrame(function(){V(o,function(){G=null})}):(V(o),G=null)):F&&(a=F(o)),r(a)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);q.propTypes={context:B.isRequired},q.displayName="HelmetDispatcher";var Y=["children"],K=["children"],Q=function(e){function t(){return e.apply(this,arguments)||this}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!l()(O(this.props,"helmetData"),O(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case m.SCRIPT:case m.NOSCRIPT:return{innerHTML:t};case m.STYLE:return{cssText:t};default:throw Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return f({},r,((t={})[n.type]=[].concat(r[n.type]||[],[f({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,a=e.newProps,o=e.newChildProps,i=e.nestedChildren;switch(r.type){case m.TITLE:return f({},a,((t={})[r.type]=i,t.titleAttributes=f({},o),t));case m.BODY:return f({},a,{bodyAttributes:f({},o)});case m.HTML:return f({},a,{htmlAttributes:f({},o)});default:return f({},a,((n={})[r.type]=f({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=f({},t);return Object.keys(e).forEach(function(t){var r;n=f({},n,((r={})[t]=e[t],r))}),n},n.warnOnInvalidChildren=function(e,t){return u()(x.some(function(t){return e.type===t}),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+x.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),u()(!t||"string"==typeof t||Array.isArray(t)&&!t.some(function(e){return"string"!=typeof e}),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,a={};return r.Children.forEach(e,function(e){if(e&&e.props){var r=e.props,o=r.children,i=g(r,Y),l=Object.keys(i).reduce(function(e,t){return e[k[t]||t]=i[t],e},{}),s=e.type;switch("symbol"==typeof s?s=s.toString():n.warnOnInvalidChildren(e,o),s){case m.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case m.LINK:case m.META:case m.NOSCRIPT:case m.SCRIPT:case m.STYLE:a=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:a,newChildProps:l,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:l,nestedChildren:o})}}}),this.mapArrayTypeChildrenToProps(a,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,K),a=f({},n),o=n.helmetData;return t&&(a=this.mapChildrenToProps(t,a)),!o||o instanceof z||(o=new z(o.context,o.instances)),o?r.createElement(q,f({},a,{context:o.value,helmetData:void 0})):r.createElement($.Consumer,null,function(e){return r.createElement(q,f({},a,{context:e}))})},t}(r.Component);Q.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},Q.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},Q.displayName="Helmet"},9921:function(e,t){"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,a=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,l=n?Symbol.for("react.profiler"):60114,s=n?Symbol.for("react.provider"):60109,u=n?Symbol.for("react.context"):60110,c=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,h=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,m=n?Symbol.for("react.lazy"):60116,y=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,v=n?Symbol.for("react.responder"):60118,x=n?Symbol.for("react.scope"):60119;function w(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case c:case d:case o:case l:case i:case p:return e;default:switch(e=e&&e.$$typeof){case u:case f:case m:case g:case s:return e;default:return t}}case a:return t}}}function k(e){return w(e)===d}t.AsyncMode=c,t.ConcurrentMode=d,t.ContextConsumer=u,t.ContextProvider=s,t.Element=r,t.ForwardRef=f,t.Fragment=o,t.Lazy=m,t.Memo=g,t.Portal=a,t.Profiler=l,t.StrictMode=i,t.Suspense=p,t.isAsyncMode=function(e){return k(e)||w(e)===c},t.isConcurrentMode=k,t.isContextConsumer=function(e){return w(e)===u},t.isContextProvider=function(e){return w(e)===s},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return w(e)===f},t.isFragment=function(e){return w(e)===o},t.isLazy=function(e){return w(e)===m},t.isMemo=function(e){return w(e)===g},t.isPortal=function(e){return w(e)===a},t.isProfiler=function(e){return w(e)===l},t.isStrictMode=function(e){return w(e)===i},t.isSuspense=function(e){return w(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===l||e===i||e===p||e===h||"object"==typeof e&&null!==e&&(e.$$typeof===m||e.$$typeof===g||e.$$typeof===s||e.$$typeof===u||e.$$typeof===f||e.$$typeof===b||e.$$typeof===v||e.$$typeof===x||e.$$typeof===y)},t.typeOf=w},9864:function(e,t,n){"use strict";e.exports=n(9921)},8356:function(e,t,n){"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}var l=n(7294),s=[],u=[],c=l.createContext(null);function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then(function(e){return n.loading=!1,n.loaded=e,e}).catch(function(e){throw n.loading=!1,n.error=e,e}),n}function f(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach(function(r){var a=d(e[r]);a.loading?t.loading=!0:(t.loaded[r]=a.loaded,t.error=a.error),n.push(a.promise),a.promise.then(function(e){t.loaded[r]=e}).catch(function(e){t.error=e})})}catch(e){t.error=e}return t.promise=Promise.all(n).then(function(e){return t.loading=!1,e}).catch(function(e){throw t.loading=!1,e}),t}function p(e,t){var n;return l.createElement((n=e)&&n.__esModule?n.default:n,t)}function h(e,t){if(!t.loading)throw Error("react-loadable requires a `loading` component");var d,f,h=i({loader:null,loading:null,delay:200,timeout:null,render:p,webpack:null,modules:null},t),g=null;function m(){return!g&&(g=e(h.loader)),g.promise}return s.push(m),"function"==typeof h.webpack&&u.push(function(){if((0,h.webpack)().every(function(e){return void 0!==e&&void 0!==n.m[e]}))return m()}),f=d=function(t){function n(n){var r;return o(a(a(r=t.call(this,n)||this)),"retry",function(){r.setState({error:null,loading:!0,timedOut:!1}),g=e(h.loader),r._loadModule()}),m(),r.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},r}r(n,t),n.preload=function(){return m()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context&&Array.isArray(h.modules)&&h.modules.forEach(function(t){e.context.report(t)}),!!g.loading){var t=function(t){if(!!e._mounted)e.setState(t)};"number"==typeof h.delay&&(0===h.delay?this.setState({pastDelay:!0}):this._delay=setTimeout(function(){t({pastDelay:!0})},h.delay)),"number"==typeof h.timeout&&(this._timeout=setTimeout(function(){t({timedOut:!0})},h.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then(function(){return n(),null}).catch(function(e){return n(),null})}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?l.createElement(h.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?h.render(this.state.loaded,this.props):null},n}(l.Component),o(d,"contextType",c),f}function g(e){return h(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw Error("LoadableMap requires a `render(loaded, props)` function");return h(f,e)};var m=function(e){function t(){return e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(){return l.createElement(c.Provider,{value:{report:this.props.report}},l.Children.only(this.props.children))},t}(l.Component);function y(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then(function(){if(e.length)return y(e)})}g.Capture=m,g.preloadAll=function(){return new Promise(function(e,t){y(s).then(e,t)})},g.preloadReady=function(){return new Promise(function(e,t){y(u).then(e,e)})},e.exports=g},3727:function(e,t,n){"use strict";n.d(t,{OL:function(){return x},UT:function(){return d},VK:function(){return c},rU:function(){return y}});var r=n(6550),a=n(5091),o=n(7294),i=n(1381),l=n(6019),s=n(443),u=n(1835),c=function(e){function t(){for(var t,n=arguments.length,r=Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.lX)(t.props),t}return(0,a.Z)(t,e),t.prototype.render=function(){return o.createElement(r.F0,{history:this.history,children:this.props.children})},t}(o.Component),d=function(e){function t(){for(var t,n=arguments.length,r=Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.q_)(t.props),t}return(0,a.Z)(t,e),t.prototype.render=function(){return o.createElement(r.F0,{history:this.history,children:this.props.children})},t}(o.Component),f=function(e,t){return"function"==typeof e?e(t):e},p=function(e,t){return"string"==typeof e?(0,i.ob)(e,null,null,t):e},h=function(e){return e},g=o.forwardRef;void 0===g&&(g=h);var m=g(function(e,t){var n=e.innerRef,r=e.navigate,a=e.onClick,i=(0,s.Z)(e,["innerRef","navigate","onClick"]),u=i.target,c=(0,l.Z)({},i,{onClick:function(e){var t;try{a&&a(e)}catch(t){throw e.preventDefault(),t}if(!e.defaultPrevented&&0===e.button&&(!u||"_self"===u)&&!((t=e).metaKey||t.altKey||t.ctrlKey||t.shiftKey))e.preventDefault(),r()}});return h!==g?c.ref=t||n:c.ref=n,o.createElement("a",c)}),y=g(function(e,t){var n=e.component,a=void 0===n?m:n,c=e.replace,d=e.to,y=e.innerRef,b=(0,s.Z)(e,["component","replace","to","innerRef"]);return o.createElement(r.s6.Consumer,null,function(e){e||(0,u.Z)(!1);var n=e.history,r=p(f(d,e.location),e.location),s=r?n.createHref(r):"",m=(0,l.Z)({},b,{href:s,navigate:function(){var t=f(d,e.location),r=(0,i.Ep)(e.location)===(0,i.Ep)(p(t));(c||r?n.replace:n.push)(t)}});return h!==g?m.ref=t||y:m.innerRef=y,o.createElement(a,m)})}),b=function(e){return e},v=o.forwardRef;void 0===v&&(v=b);var x=v(function(e,t){var n=e["aria-current"],a=void 0===n?"page":n,i=e.activeClassName,c=void 0===i?"active":i,d=e.activeStyle,h=e.className,g=e.exact,m=e.isActive,x=e.location,w=e.sensitive,k=e.strict,S=e.style,E=e.to,_=e.innerRef,C=(0,s.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(r.s6.Consumer,null,function(e){e||(0,u.Z)(!1);var n=x||e.location,i=p(f(E,n),n),s=i.pathname,T=s&&s.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),N=T?(0,r.LX)(n.pathname,{path:T,exact:g,sensitive:w,strict:k}):null,A=!!(m?m(N,n):N),O="function"==typeof h?h(A):h,P="function"==typeof S?S(A):S;A&&(O=function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter(function(e){return e}).join(" ")}(O,c),P=(0,l.Z)({},P,d));var j=(0,l.Z)({"aria-current":A&&a||null,className:O,style:P,to:i},C);return b!==v?j.ref=t||_:j.innerRef=_,o.createElement(y,j)})})},6550:function(e,t,n){"use strict";n.d(t,{AW:function(){return w},F0:function(){return y},LX:function(){return x},TH:function(){return C},k6:function(){return _},rs:function(){return S},s6:function(){return m}});var r=n(5091),a=n(7294),o=n(5697),i=n.n(o),l=n(1381),s=n(1835),u=n(6019),c=n(4779),d=n.n(c);n(9864),n(443),n(8679);var f="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{},p=a.createContext||function(e,t){var n,o,l,s="__create-react-context-"+(f[n="__global_unique_id__"]=(f[n]||0)+1)+"__",u=function(e){function n(){for(var t,n,r,a=arguments.length,o=Array(a),i=0;i<a;i++)o[i]=arguments[i];return(t=e.call.apply(e,[this].concat(o))||this).emitter=(n=t.props.value,r=[],{on:function(e){r.push(e)},off:function(e){r=r.filter(function(t){return t!==e})},get:function(){return n},set:function(e,t){n=e,r.forEach(function(e){return e(n,t)})}}),t}(0,r.Z)(n,e);var a=n.prototype;return a.getChildContext=function(){var e;return(e={})[s]=this.emitter,e},a.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r,a,o=this.props.value,i=e.value;if((n=o)===(r=i)?0!==n||1/n==1/r:n!=n&&r!=r)a=0;else{a="function"==typeof t?t(o,i):0x3fffffff;0!=(a|=0)&&this.emitter.set(e.value,a)}}},a.render=function(){return this.props.children},n}(a.Component);u.childContextTypes=((o={})[s]=i().object.isRequired,o);var c=function(t){function n(){for(var e,n=arguments.length,r=Array(n),a=0;a<n;a++)r[a]=arguments[a];return(e=t.call.apply(t,[this].concat(r))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){((0|e.observedBits)&n)!=0&&e.setState({value:e.getValue()})},e}(0,r.Z)(n,t);var a=n.prototype;return a.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?0x3fffffff:t},a.componentDidMount=function(){this.context[s]&&this.context[s].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?0x3fffffff:e},a.componentWillUnmount=function(){this.context[s]&&this.context[s].off(this.onUpdate)},a.getValue=function(){return this.context[s]?this.context[s].get():e},a.render=function(){var e;return(Array.isArray(e=this.props.children)?e[0]:e)(this.state.value)},n}(a.Component);return c.contextTypes=((l={})[s]=i().object,l),{Provider:u,Consumer:c}},h=function(e){var t=p();return t.displayName=e,t},g=h("Router-History"),m=h("Router"),y=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,!t.staticContext&&(n.unlisten=t.history.listen(function(e){n._pendingLocation=e})),n}(0,r.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),!this.props.staticContext&&(this.unlisten=this.props.history.listen(function(t){e._isMounted&&e.setState({location:t})})),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return a.createElement(m.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},a.createElement(g.Provider,{children:this.props.children||null,value:this.props.history}))},t}(a.Component);a.Component;a.Component;var b={},v=0;function x(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,a=n.exact,o=void 0!==a&&a,i=n.strict,l=void 0!==i&&i,s=n.sensitive,u=void 0!==s&&s;return[].concat(r).reduce(function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=b[n]||(b[n]={});if(r[e])return r[e];var a=[],o={regexp:d()(e,a,t),keys:a};return v<1e4&&(r[e]=o,v++),o}(n,{end:o,strict:l,sensitive:u}),a=r.regexp,i=r.keys,s=a.exec(e);if(!s)return null;var c=s[0],f=s.slice(1),p=e===c;return o&&!p?null:{path:n,url:"/"===n&&""===c?"/":c,isExact:p,params:i.reduce(function(e,t,n){return e[t.name]=f[n],e},{})}},null)}var w=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(m.Consumer,null,function(t){t||(0,s.Z)(!1);var n,r=e.props.location||t.location,o=e.props.computedMatch?e.props.computedMatch:e.props.path?x(r.pathname,e.props):t.match,i=(0,u.Z)({},t,{location:r,match:o}),l=e.props,c=l.children,d=l.component,f=l.render;if(Array.isArray(c)&&(n=c,0===a.Children.count(n)))c=null;return a.createElement(m.Provider,{value:i},i.match?c?"function"==typeof c?c(i):c:d?a.createElement(d,i):f?f(i):null:"function"==typeof c?c(i):null)})},t}(a.Component);function k(e){return"/"===e.charAt(0)?e:"/"+e}a.Component;var S=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(m.Consumer,null,function(t){t||(0,s.Z)(!1);var n,r,o=e.props.location||t.location;return a.Children.forEach(e.props.children,function(e){if(null==r&&a.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?x(o.pathname,(0,u.Z)({},e.props,{path:i})):t.match}}),r?a.cloneElement(n,{location:o,computedMatch:r}):null})},t}(a.Component),E=a.useContext;function _(){return E(g)}function C(){return E(m).location}},5251:function(e,t,n){"use strict";var r=n(7294),a=Symbol.for("react.element"),o=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,l=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s={key:!0,ref:!0,__self:!0,__source:!0};function u(e,t,n){var r,o={},u=null,c=null;for(r in void 0!==n&&(u=""+n),void 0!==t.key&&(u=""+t.key),void 0!==t.ref&&(c=t.ref),t)i.call(t,r)&&!s.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:a,type:e,key:u,ref:c,props:o,_owner:l.current}}t.Fragment=o,t.jsx=u,t.jsxs=u},2408:function(e,t){"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),l=Symbol.for("react.provider"),s=Symbol.for("react.context"),u=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),f=Symbol.for("react.lazy"),p=Symbol.iterator,h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,m={};function y(e,t,n){this.props=e,this.context=t,this.refs=m,this.updater=n||h}function b(){}function v(e,t,n){this.props=e,this.context=t,this.refs=m,this.updater=n||h}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},b.prototype=y.prototype;var x=v.prototype=new b;x.constructor=v,g(x,y.prototype),x.isPureReactComponent=!0;var w=Array.isArray,k=Object.prototype.hasOwnProperty,S={current:null},E={key:!0,ref:!0,__self:!0,__source:!0};function _(e,t,r){var a,o={},i=null,l=null;if(null!=t)for(a in void 0!==t.ref&&(l=t.ref),void 0!==t.key&&(i=""+t.key),t)k.call(t,a)&&!E.hasOwnProperty(a)&&(o[a]=t[a]);var s=arguments.length-2;if(1===s)o.children=r;else if(1<s){for(var u=Array(s),c=0;c<s;c++)u[c]=arguments[c+2];o.children=u}if(e&&e.defaultProps)for(a in s=e.defaultProps)void 0===o[a]&&(o[a]=s[a]);return{$$typeof:n,type:e,key:i,ref:l,props:o,_owner:S.current}}function C(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}var T=/\/+/g;function N(e,t){var n,r;return"object"==typeof e&&null!==e&&null!=e.key?(n=""+e.key,r={"=":"=0",":":"=2"},"$"+n.replace(/[=:]/g,function(e){return r[e]})):t.toString(36)}function A(e,t,a){if(null==e)return e;var o=[],i=0;return!function e(t,a,o,i,l){var s,u,c,d=typeof t;("undefined"===d||"boolean"===d)&&(t=null);var f=!1;if(null===t)f=!0;else switch(d){case"string":case"number":f=!0;break;case"object":switch(t.$$typeof){case n:case r:f=!0}}if(f){;return l=l(f=t),t=""===i?"."+N(f,0):i,w(l)?(o="",null!=t&&(o=t.replace(T,"$&/")+"/"),e(l,a,o,"",function(e){return e})):null!=l&&(C(l)&&(s=l,u=o+(!l.key||f&&f.key===l.key?"":(""+l.key).replace(T,"$&/")+"/")+t,l={$$typeof:n,type:s.type,key:u,ref:s.ref,props:s.props,_owner:s._owner}),a.push(l)),1}if(f=0,i=""===i?".":i+":",w(t))for(var h=0;h<t.length;h++){var g=i+N(d=t[h],h);f+=e(d,a,o,g,l)}else{;if("function"==typeof(g=null===(c=t)||"object"!=typeof c?null:"function"==typeof(c=p&&c[p]||c["@@iterator"])?c:null))for(t=g.call(t),h=0;!(d=t.next()).done;)g=i+N(d=d.value,h++),f+=e(d,a,o,g,l);else if("object"===d)throw Error("Objects are not valid as a React child (found: "+("[object Object]"===(a=String(t))?"object with keys {"+Object.keys(t).join(", ")+"}":a)+"). If you meant to render a collection of children, use an array instead.")}return f}(e,o,"","",function(e){return t.call(a,e,i++)}),o}function O(e){if(-1===e._status){var t=e._result;(t=t()).then(function(t){(0===e._status||-1===e._status)&&(e._status=1,e._result=t)},function(t){(0===e._status||-1===e._status)&&(e._status=2,e._result=t)}),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var P={current:null},j={transition:null};function L(){throw Error("act(...) is not supported in production builds of React.")}t.Children={map:A,forEach:function(e,t,n){A(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return A(e,function(){t++}),t},toArray:function(e){return A(e,function(e){return e})||[]},only:function(e){if(!C(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=y,t.Fragment=a,t.Profiler=i,t.PureComponent=v,t.StrictMode=o,t.Suspense=c,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED={ReactCurrentDispatcher:P,ReactCurrentBatchConfig:j,ReactCurrentOwner:S},t.act=L,t.cloneElement=function(e,t,r){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var a=g({},e.props),o=e.key,i=e.ref,l=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,l=S.current),void 0!==t.key&&(o=""+t.key),e.type&&e.type.defaultProps)var s=e.type.defaultProps;for(u in t)k.call(t,u)&&!E.hasOwnProperty(u)&&(a[u]=void 0===t[u]&&void 0!==s?s[u]:t[u])}var u=arguments.length-2;if(1===u)a.children=r;else if(1<u){s=Array(u);for(var c=0;c<u;c++)s[c]=arguments[c+2];a.children=s}return{$$typeof:n,type:e.type,key:o,ref:i,props:a,_owner:l}},t.createContext=function(e){return(e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:l,_context:e},e.Consumer=e},t.createElement=_,t.createFactory=function(e){var t=_.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:u,render:e}},t.isValidElement=C,t.lazy=function(e){return{$$typeof:f,_payload:{_status:-1,_result:e},_init:O}},t.memo=function(e,t){return{$$typeof:d,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=j.transition;j.transition={};try{e()}finally{j.transition=t}},t.unstable_act=L,t.useCallback=function(e,t){return P.current.useCallback(e,t)},t.useContext=function(e){return P.current.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e){return P.current.useDeferredValue(e)},t.useEffect=function(e,t){return P.current.useEffect(e,t)},t.useId=function(){return P.current.useId()},t.useImperativeHandle=function(e,t,n){return P.current.useImperativeHandle(e,t,n)},t.useInsertionEffect=function(e,t){return P.current.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return P.current.useLayoutEffect(e,t)},t.useMemo=function(e,t){return P.current.useMemo(e,t)},t.useReducer=function(e,t,n){return P.current.useReducer(e,t,n)},t.useRef=function(e){return P.current.useRef(e)},t.useState=function(e){return P.current.useState(e)},t.useSyncExternalStore=function(e,t,n){return P.current.useSyncExternalStore(e,t,n)},t.useTransition=function(){return P.current.useTransition()},t.version="18.3.1"},7294:function(e,t,n){"use strict";e.exports=n(2408)},5893:function(e,t,n){"use strict";e.exports=n(5251)},53:function(e,t){"use strict";function n(e,t){var n=e.length;for(e.push(t);0<n;){var r=n-1>>>1,a=e[r];if(0<o(a,t))e[r]=t,e[n]=a,n=r;else break}}function r(e){return 0===e.length?null:e[0]}function a(e){if(0===e.length)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;for(var r=0,a=e.length,i=a>>>1;r<i;){var l=2*(r+1)-1,s=e[l],u=l+1,c=e[u];if(0>o(s,n))u<a&&0>o(c,s)?(e[r]=c,e[u]=n,r=u):(e[r]=s,e[l]=n,r=l);else if(u<a&&0>o(c,n))e[r]=c,e[u]=n,r=u;else break}}return t}function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i,l=performance;t.unstable_now=function(){return l.now()}}else{var s=Date,u=s.now();t.unstable_now=function(){return s.now()-u}}var c=[],d=[],f=1,p=null,h=3,g=!1,m=!1,y=!1,b="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,x="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var t=r(d);null!==t;){if(null===t.callback)a(d);else if(t.startTime<=e)a(d),t.sortIndex=t.expirationTime,n(c,t);else break;t=r(d)}}function k(e){if(y=!1,w(e),!m){if(null!==r(c))m=!0,L(S);else{var t=r(d);null!==t&&R(k,t.startTime-e)}}}function S(e,n){m=!1,y&&(y=!1,v(C),C=-1),g=!0;var o=h;try{for(w(n),p=r(c);null!==p&&(!(p.expirationTime>n)||e&&!A());){var i=p.callback;if("function"==typeof i){p.callback=null,h=p.priorityLevel;var l=i(p.expirationTime<=n);n=t.unstable_now(),"function"==typeof l?p.callback=l:p===r(c)&&a(c),w(n)}else a(c);p=r(c)}if(null!==p)var s=!0;else{var u=r(d);null!==u&&R(k,u.startTime-n),s=!1}return s}finally{p=null,h=o,g=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var E=!1,_=null,C=-1,T=5,N=-1;function A(){return!(t.unstable_now()-N<T)}function O(){if(null!==_){var e=t.unstable_now();N=e;var n=!0;try{n=_(!0,e)}finally{n?i():(E=!1,_=null)}}else E=!1}if("function"==typeof x)i=function(){x(O)};else if("undefined"!=typeof MessageChannel){var P=new MessageChannel,j=P.port2;P.port1.onmessage=O,i=function(){j.postMessage(null)}}else i=function(){b(O,0)};function L(e){_=e,E||(E=!0,i())}function R(e,n){C=b(function(){e(t.unstable_now())},n)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){m||g||(m=!0,L(S))},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):T=0<e?Math.floor(1e3/e):5},t.unstable_getCurrentPriorityLevel=function(){return h},t.unstable_getFirstCallbackNode=function(){return r(c)},t.unstable_next=function(e){switch(h){case 1:case 2:case 3:var t=3;break;default:t=h}var n=h;h=t;try{return e()}finally{h=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=function(){},t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=h;h=e;try{return t()}finally{h=n}},t.unstable_scheduleCallback=function(e,a,o){var i=t.unstable_now();switch(o="object"==typeof o&&null!==o?"number"==typeof(o=o.delay)&&0<o?i+o:i:i,e){case 1:var l=-1;break;case 2:l=250;break;case 5:l=0x3fffffff;break;case 4:l=1e4;break;default:l=5e3}return l=o+l,e={id:f++,callback:a,priorityLevel:e,startTime:o,expirationTime:l,sortIndex:-1},o>i?(e.sortIndex=o,n(d,e),null===r(c)&&e===r(d)&&(y?(v(C),C=-1):y=!0,R(k,o-i))):(e.sortIndex=l,n(c,e),m||g||(m=!0,L(S))),e},t.unstable_shouldYield=A,t.unstable_wrapCallback=function(e){var t=h;return function(){var n=h;h=t;try{return e.apply(this,arguments)}finally{h=n}}}},3840:function(e,t,n){"use strict";e.exports=n(53)},6774:function(e){e.exports=function(e,t,n,r){var a=n?n.call(r,e,t):void 0;if(void 0!==a)return!!a;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),i=Object.keys(t);if(o.length!==i.length)return!1;for(var l=Object.prototype.hasOwnProperty.bind(t),s=0;s<o.length;s++){var u=o[s];if(!l(u))return!1;var c=e[u],d=t[u];if(!1===(a=n?n.call(r,c,d,u):void 0)||void 0===a&&c!==d)return!1}return!0}},4143:function(e,t,n){"use strict";n.d(t,{Z:()=>f}),n("7294");var r=n("5893"),a=n("8356"),o=n.n(a),i=n("7138");let l={"0fb9ce37":[()=>n.e("7848").then(n.bind(n,6330)),"@site/blog/2019-12-14-release-the-gil/index.mdx",6330],"130b4a4b":[()=>n.e("294").then(n.bind(n,6056)),"@site/blog/2018-09-01-primitives-in-rust-are-weird/index.mdx",6056],"16c8da5a":[()=>n.e("95").then(n.bind(n,8066)),"@site/blog/2018-06-25-dateutil-parser-to-rust/index.mdx",8066],"1803684d":[()=>n.e("7624").then(n.bind(n,3570)),"@site/blog/2016-10-22-rustic-repodcasting/index.mdx",3570],"1806d708":[()=>n.e("3241").then(n.bind(n,1859)),"@site/blog/2015-11-27-autocallable/index.mdx",1859],"1a1424c7":[()=>n.e("9763").then(n.t.bind(n,829,19)),"@generated/docusaurus-plugin-content-blog/default/p/index-0ee.json",829],"1b190668":[()=>n.e("5229").then(n.bind(n,7897)),"@site/blog/2016-03-05-predicting-santander-customer-happiness/index.mdx?truncated=true",7897],"1d2da633":[()=>n.e("5373").then(n.bind(n,695)),"@site/blog/2016-01-23-cloudy-in-seattle/index.mdx?truncated=true",695],"1e5192b9":[()=>n.e("5644").then(n.bind(n,4092)),"@site/blog/2022-11-20-webpack-industrial-complex/index.mdx",4092],"1f1953c8":[()=>n.e("2410").then(n.bind(n,9959)),"@site/blog/2019-09-28-binary-format-shootout/index.mdx?truncated=true",9959],"1fe257c0":[()=>n.e("3837").then(n.bind(n,1883)),"@site/blog/2015-11-14-welcome/index.mdx?truncated=true",1883],"2062e753":[()=>n.e("8770").then(n.bind(n,984)),"@site/blog/2019-06-31-high-performance-systems/index.mdx?truncated=true",984],"319b187a":[()=>n.e("4809").then(n.bind(n,3227)),"@site/blog/2016-02-03-guaranteed-money-maker/index.mdx?truncated=true",3227],"33496f92":[()=>n.e("1680").then(n.t.bind(n,2187,19)),"@generated/docusaurus-plugin-content-blog/default/p/page-3-7c8.json",2187],"35b21e3d":[()=>n.e("4833").then(n.bind(n,6171)),"@site/blog/2016-02-26-profitability-using-the-investment-formula/index.mdx",6171],"36994c47":[()=>n.e("2792").then(n.t.bind(n,7934,19)),"@generated/docusaurus-plugin-content-blog/default/__plugin.json",7934],"39c8d8a0":[()=>n.e("156").then(n.bind(n,5100)),"@site/blog/2019-09-28-binary-format-shootout/index.mdx",5100],"3a2ddf2f":[()=>n.e("4844").then(n.bind(n,531)),"@site/blog/2018-12-04-what-small-business-really-means/index.mdx",531],"3aab746c":[()=>n.e("1672").then(n.bind(n,8204)),"@site/blog/2019-06-31-high-performance-systems/index.mdx",8204],"3cafba32":[()=>n.e("6267").then(n.bind(n,6376)),"@site/blog/2016-01-23-cloudy-in-seattle/index.mdx",6376],"3d0fb9fd":[()=>n.e("4384").then(n.bind(n,2736)),"@site/blog/2018-09-15-isomorphic-apps/index.mdx",2736],"3f9ae9f6":[()=>n.e("7109").then(n.t.bind(n,9948,19)),"@generated/docusaurus-plugin-content-blog/default/p/authors-d6c.json",9948],"47f41a37":[()=>n.e("7073").then(n.bind(n,2134)),"@site/blog/2015-12-26-testing-cramer/index.mdx?truncated=true",2134],"4c2b0735":[()=>n.e("4718").then(n.bind(n,5960)),"@site/blog/2016-06-08-event-studies-and-earnings-releases/index.mdx",5960],"4cf7e30f":[()=>n.e("1446").then(n.bind(n,8636)),"@site/blog/2019-05-03-making-bread/index.mdx?truncated=true",8636],"4dbec139":[()=>n.e("7953").then(n.bind(n,8873)),"@site/blog/2018-01-16-captains-cookbook-part-2/index.mdx?truncated=true",8873],"522b09ee":[()=>n.e("5810").then(n.bind(n,341)),"@site/blog/2018-09-15-isomorphic-apps/index.mdx?truncated=true",341],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,5150)),"@generated/docusaurus.config",5150],"5f602fa1":[()=>n.e("8345").then(n.bind(n,84)),"@site/blog/2016-05-15-the-unfair-casino/index.mdx",84],"621db11d":[()=>Promise.all([n.e("6212"),n.e("5601"),n.e("9854")]).then(n.bind(n,8448)),"@theme/Blog/Pages/BlogAuthorsListPage",8448],"6fa48b14":[()=>n.e("1511").then(n.bind(n,6836)),"@site/blog/2018-09-01-primitives-in-rust-are-weird/index.mdx?truncated=true",6836],"71d18034":[()=>n.e("4558").then(n.bind(n,10)),"@site/blog/2018-01-16-captains-cookbook-part-2/index.mdx",10],"724b3f70":[()=>n.e("5747").then(n.bind(n,7519)),"@site/blog/2018-05-28-hello/index.mdx?truncated=true",7519],"72c73938":[()=>n.e("9658").then(n.bind(n,8190)),"@site/blog/2016-03-28-tweet-like-me/index.mdx",8190],"761aff6b":[()=>n.e("7366").then(n.bind(n,5623)),"@site/blog/2019-02-07-a-heaping-helping/index.mdx",5623],"76b3b3f5":[()=>n.e("8987").then(n.bind(n,3699)),"@site/blog/2018-12-15-allocation-safety/index.mdx?truncated=true",3699],"77bf0009":[()=>n.e("6240").then(n.bind(n,5615)),"@site/blog/2019-05-03-making-bread/index.mdx",5615],"78d2eb38":[()=>n.e("8977").then(n.bind(n,5155)),"@site/blog/2018-06-25-dateutil-parser-to-rust/index.mdx?truncated=true",5155],"7ba60abf":[()=>n.e("7702").then(n.bind(n,9085)),"@site/blog/2016-02-26-profitability-using-the-investment-formula/index.mdx?truncated=true",9085],"814f3328":[()=>n.e("106").then(n.t.bind(n,4200,19)),"~blog/default/blog-post-list-prop-default.json",4200],"818287cf":[()=>n.e("5095").then(n.bind(n,2181)),"@site/blog/2015-11-14-welcome/index.mdx",2181],"84329d6a":[()=>n.e("2433").then(n.bind(n,5241)),"@site/blog/2019-02-09-summary/index.mdx?truncated=true",5241],"857496c7":[()=>n.e("5168").then(n.bind(n,1200)),"@site/blog/2016-11-01-PCA-audio-compression/index.mdx?truncated=true",1200],"85b3a5ed":[()=>n.e("1874").then(n.bind(n,2763)),"@site/blog/2019-02-06-stacking-up/index.mdx",2763],"868a7989":[()=>n.e("5969").then(n.bind(n,3807)),"@site/src/pages/feed.xml.tsx",3807],"88eed8c4":[()=>n.e("1652").then(n.bind(n,4257)),"@site/blog/2019-02-05-the-whole-world/index.mdx",4257],"89fbf712":[()=>n.e("4794").then(n.bind(n,3775)),"@site/blog/2015-11-27-autocallable/index.mdx?truncated=true",3775],"8fedb115":[()=>n.e("4593").then(n.bind(n,5959)),"@site/blog/2019-02-08-compiler-optimizations/index.mdx?truncated=true",5959],"92079dc1":[()=>n.e("9366").then(n.bind(n,3244)),"@site/blog/2016-01-01-complaining-about-the-weather/index.mdx",3244],"94d32f6c":[()=>n.e("7580").then(n.bind(n,4935)),"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx",4935],"962a4168":[()=>n.e("302").then(n.bind(n,8674)),"@site/blog/2016-03-05-predicting-santander-customer-happiness/index.mdx",8674],"975a028b":[()=>n.e("5478").then(n.bind(n,8422)),"@site/blog/2018-12-04-what-small-business-really-means/index.mdx?truncated=true",8422],"9e4087bc":[()=>n.e("7293").then(n.bind(n,2204)),"@theme/BlogArchivePage",2204],a14a666c:[()=>n.e("1000").then(n.bind(n,7493)),"@site/blog/2019-02-06-stacking-up/index.mdx?truncated=true",7493],a6aa9e1f:[()=>Promise.all([n.e("6212"),n.e("5601"),n.e("2519"),n.e("8514")]).then(n.bind(n,1434)),"@theme/BlogListPage",1434],a7456010:[()=>n.e("7365").then(n.t.bind(n,2050,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",2050],acecf23e:[()=>n.e("7627").then(n.t.bind(n,7548,19)),"~blog/default/blogMetadata-default.json",7548],aea41ef6:[()=>n.e("4595").then(n.t.bind(n,3200,19)),"@generated/docusaurus-plugin-content-blog/default/p/page-2-b69.json",3200],b08f0f32:[()=>n.e("9363").then(n.bind(n,1998)),"@site/blog/2016-04-06-tick-tock/index.mdx",1998],b16509ac:[()=>n.e("2628").then(n.bind(n,9804)),"@site/blog/2016-10-22-rustic-repodcasting/index.mdx?truncated=true",9804],b266de79:[()=>n.e("1225").then(n.t.bind(n,6760,19)),"@generated/docusaurus-plugin-content-blog/default/p/archive-66b.json",6760],b537349a:[()=>n.e("6078").then(n.bind(n,7126)),"@site/blog/2018-05-28-hello/index.mdx",7126],b5b60058:[()=>n.e("9798").then(n.bind(n,6563)),"@site/blog/2016-04-06-tick-tock/index.mdx?truncated=true",6563],b5d84c45:[()=>n.e("5523").then(n.bind(n,6297)),"@site/blog/2016-03-28-tweet-like-me/index.mdx?truncated=true",6297],c32740fe:[()=>n.e("6992").then(n.bind(n,1712)),"@site/blog/2016-05-15-the-unfair-casino/index.mdx?truncated=true",1712],c97f4488:[()=>n.e("9437").then(n.bind(n,4217)),"@site/blog/2018-12-15-allocation-safety/index.mdx",4217],ccc49370:[()=>Promise.all([n.e("6212"),n.e("5601"),n.e("2519"),n.e("9555"),n.e("2998")]).then(n.bind(n,3549)),"@theme/BlogPostPage",3549],cd68b6a4:[()=>n.e("1408").then(n.bind(n,4849)),"@site/blog/2016-11-01-PCA-audio-compression/index.mdx",4849],d085497a:[()=>n.e("8704").then(n.bind(n,2372)),"@site/blog/2015-12-26-testing-cramer/index.mdx",2372],d185f613:[()=>n.e("5407").then(n.bind(n,3561)),"@site/blog/2019-02-08-compiler-optimizations/index.mdx",3561],d280b035:[()=>n.e("7120").then(n.bind(n,4260)),"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx?truncated=true",4260],d7ab2b33:[()=>n.e("9127").then(n.bind(n,4487)),"@site/blog/2019-02-07-a-heaping-helping/index.mdx?truncated=true",4487],db76ea4b:[()=>n.e("6138").then(n.bind(n,9994)),"@site/blog/2018-10-08-case-study-optimization/index.mdx?truncated=true",9994],dca2e11d:[()=>n.e("6424").then(n.bind(n,5347)),"@site/blog/2019-12-14-release-the-gil/index.mdx?truncated=true",5347],de854ad9:[()=>n.e("9994").then(n.t.bind(n,1244,19)),"@generated/docusaurus-plugin-content-blog/default/p/page-4-04a.json",1244],de863535:[()=>n.e("8276").then(n.bind(n,2128)),"@site/blog/2022-11-20-webpack-industrial-complex/index.mdx?truncated=true",2128],e0aaf982:[()=>n.e("8998").then(n.bind(n,7508)),"@site/blog/2019-02-05-the-whole-world/index.mdx?truncated=true",7508],e37dfb5c:[()=>n.e("3956").then(n.bind(n,4297)),"@site/blog/2019-02-09-summary/index.mdx",4297],e62372be:[()=>n.e("6781").then(n.bind(n,1490)),"@site/blog/2016-06-08-event-studies-and-earnings-releases/index.mdx?truncated=true",1490],ed9b7162:[()=>n.e("3533").then(n.bind(n,1867)),"@site/blog/2018-01-16-captains-cookbok-part-1/index.mdx?truncated=true",1867],ef7aa1ca:[()=>n.e("832").then(n.bind(n,8603)),"@site/blog/2018-01-16-captains-cookbok-part-1/index.mdx",8603],f2eb9457:[()=>n.e("8863").then(n.bind(n,4174)),"@site/blog/2016-01-01-complaining-about-the-weather/index.mdx?truncated=true",4174],f8fee0f7:[()=>n.e("4760").then(n.bind(n,3643)),"@site/blog/2018-10-08-case-study-optimization/index.mdx",3643],fd7e7e63:[()=>n.e("8868").then(n.bind(n,1450)),"@site/blog/2016-02-03-guaranteed-money-maker/index.mdx",1450]};function s(e){let{error:t,retry:n,pastDelay:a}=e;return t?(0,r.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,r.jsx)("p",{children:String(t)}),(0,r.jsx)("div",{children:(0,r.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):a?(0,r.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,r.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,r.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,r.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,r.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,r.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,r.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,r.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,r.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,r.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,r.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,r.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,r.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var u=n("6464"),c=n("4879");function d(e,t){if("*"===e)return o()({loading:s,loader:()=>n.e("6472").then(n.bind(n,3726)),modules:["@theme/NotFound"],webpack:()=>[3726],render(e,t){let n=e.default;return(0,r.jsx)(c.z,{value:{plugin:{name:"native",id:"default"}},children:(0,r.jsx)(n,{...t})})}});let a=i[`${e}-${t}`],d={},f=[],p=[];return Object.entries((0,u.Z)(a)).forEach(e=>{let[t,n]=e,r=l[n];r&&(d[t]=r[0],f.push(r[1]),p.push(r[2]))}),o().Map({loading:s,loader:d,modules:f,webpack:()=>p,render(t,n){let o=JSON.parse(JSON.stringify(a));Object.entries(t).forEach(t=>{let[n,r]=t,a=r.default;if(!a)throw Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);("object"==typeof a||"function"==typeof a)&&Object.keys(r).filter(e=>"default"!==e).forEach(e=>{a[e]=r[e]});let i=o,l=n.split(".");l.slice(0,-1).forEach(e=>{i=i[e]}),i[l[l.length-1]]=a});let i=o.__comp;delete o.__comp;let l=o.__context;delete o.__context;let s=o.__props;return delete o.__props,(0,r.jsx)(c.z,{value:l,children:(0,r.jsx)(i,{...o,...s,...n})})}})}let f=[{path:"/2011/11/webpack-industrial-complex",component:d("/2011/11/webpack-industrial-complex","1d7"),exact:!0},{path:"/2015/11/autocallable",component:d("/2015/11/autocallable","259"),exact:!0},{path:"/2015/11/welcome",component:d("/2015/11/welcome","fd8"),exact:!0},{path:"/2015/12/testing-cramer",component:d("/2015/12/testing-cramer","e37"),exact:!0},{path:"/2016/01/cloudy-in-seattle",component:d("/2016/01/cloudy-in-seattle","72a"),exact:!0},{path:"/2016/01/complaining-about-the-weather",component:d("/2016/01/complaining-about-the-weather","598"),exact:!0},{path:"/2016/02/guaranteed-money-maker",component:d("/2016/02/guaranteed-money-maker","911"),exact:!0},{path:"/2016/02/profitability-using-the-investment-formula",component:d("/2016/02/profitability-using-the-investment-formula","47f"),exact:!0},{path:"/2016/03/predicting-santander-customer-happiness",component:d("/2016/03/predicting-santander-customer-happiness","906"),exact:!0},{path:"/2016/03/tweet-like-me",component:d("/2016/03/tweet-like-me","e83"),exact:!0},{path:"/2016/04/tick-tock",component:d("/2016/04/tick-tock","a99"),exact:!0},{path:"/2016/05/the-unfair-casino",component:d("/2016/05/the-unfair-casino","11e"),exact:!0},{path:"/2016/06/event-studies-and-earnings-releases",component:d("/2016/06/event-studies-and-earnings-releases","d88"),exact:!0},{path:"/2016/10/rustic-repodcasting",component:d("/2016/10/rustic-repodcasting","0a7"),exact:!0},{path:"/2016/11/pca-audio-compression",component:d("/2016/11/pca-audio-compression","31c"),exact:!0},{path:"/2018/01/captains-cookbook-part-1",component:d("/2018/01/captains-cookbook-part-1","555"),exact:!0},{path:"/2018/01/captains-cookbook-part-2",component:d("/2018/01/captains-cookbook-part-2","98a"),exact:!0},{path:"/2018/05/hello",component:d("/2018/05/hello","98e"),exact:!0},{path:"/2018/06/dateutil-parser-to-rust",component:d("/2018/06/dateutil-parser-to-rust","63f"),exact:!0},{path:"/2018/09/isomorphic-apps",component:d("/2018/09/isomorphic-apps","cc3"),exact:!0},{path:"/2018/09/primitives-in-rust-are-weird",component:d("/2018/09/primitives-in-rust-are-weird","ead"),exact:!0},{path:"/2018/10/case-study-optimization",component:d("/2018/10/case-study-optimization","062"),exact:!0},{path:"/2018/12/allocation-safety",component:d("/2018/12/allocation-safety","1ae"),exact:!0},{path:"/2018/12/what-small-business-really-means",component:d("/2018/12/what-small-business-really-means","71f"),exact:!0},{path:"/2019/02/08/compiler-optimizations",component:d("/2019/02/08/compiler-optimizations","a2d"),exact:!0},{path:"/2019/02/a-heaping-helping",component:d("/2019/02/a-heaping-helping","b4d"),exact:!0},{path:"/2019/02/stacking-up",component:d("/2019/02/stacking-up","1cc"),exact:!0},{path:"/2019/02/summary",component:d("/2019/02/summary","194"),exact:!0},{path:"/2019/02/the-whole-world",component:d("/2019/02/the-whole-world","ccd"),exact:!0},{path:"/2019/02/understanding-allocations-in-rust",component:d("/2019/02/understanding-allocations-in-rust","e0a"),exact:!0},{path:"/2019/05/making-bread",component:d("/2019/05/making-bread","3d0"),exact:!0},{path:"/2019/06/high-performance-systems",component:d("/2019/06/high-performance-systems","46f"),exact:!0},{path:"/2019/09/binary-format-shootout",component:d("/2019/09/binary-format-shootout","6d5"),exact:!0},{path:"/2019/12/release-the-gil",component:d("/2019/12/release-the-gil","8c2"),exact:!0},{path:"/archive",component:d("/archive","51a"),exact:!0},{path:"/authors",component:d("/authors","498"),exact:!0},{path:"/feed.xml",component:d("/feed.xml","eda"),exact:!0},{path:"/page/2",component:d("/page/2","e79"),exact:!0},{path:"/page/3",component:d("/page/3","92e"),exact:!0},{path:"/page/4",component:d("/page/4","0bb"),exact:!0},{path:"/",component:d("/","e81"),exact:!0},{path:"*",component:d("*")}]},258:function(e,t,n){"use strict";n.d(t,{_:function(){return o},t:function(){return i}});var r=n(5893),a=n(7294);let o=a.createContext(!1);function i(e){let{children:t}=e,[n,i]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{i(!0)},[]),(0,r.jsx)(o.Provider,{value:n,children:t})}},3426:function(e,t,n){"use strict";var r,a,o,i=n("5893"),l=n("7294"),s=n("745"),u=n("405"),c=n("3727"),d=n("5150"),f=n("7565");let p=[n(3601),n(1569),n(1987),n(7686)];var h=n("4143"),g=n("6550"),m=n("6019");function y(e,t,n){return void 0===n&&(n=[]),e.some(function(e){var r=e.path?(0,g.LX)(t,e):n.length?n[n.length-1].match:g.F0.computeRootMatch(t);return r&&(n.push({route:e,match:r}),e.routes&&y(e.routes,t,n)),r}),n}function b(e){let{children:t}=e;return(0,i.jsx)(i.Fragment,{children:t})}var v=n("4819"),x=n("2933"),w=n("4757"),k=n("140"),S=n("2743"),E=n("8910"),_=n("6959"),C=n("8365"),T=n("4315");function N(){let{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,x.Z)(),r=(0,E.l)(),a=n[e].htmlLang,o=e=>e.replace("-","_");return(0,i.jsxs)(v.Z,{children:[Object.entries(n).map(e=>{let[t,{htmlLang:n}]=e;return(0,i.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)}),(0,i.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,i.jsx)("meta",{property:"og:locale",content:o(a)}),Object.values(n).filter(e=>a!==e.htmlLang).map(e=>(0,i.jsx)("meta",{property:"og:locale:alternate",content:o(e.htmlLang)},`meta-og-${e.htmlLang}`))]})}function A(e){let{permalink:t}=e,{siteConfig:{url:n}}=(0,x.Z)(),r=function(){let{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,x.Z)(),{pathname:r}=(0,g.TH)();return e+(0,C.applyTrailingSlash)((0,w.ZP)(r),{trailingSlash:n,baseUrl:t})}(),a=t?`${n}${t}`:r;return(0,i.jsxs)(v.Z,{children:[(0,i.jsx)("meta",{property:"og:url",content:a}),(0,i.jsx)("link",{rel:"canonical",href:a})]})}function O(){let{i18n:{currentLocale:e}}=(0,x.Z)(),{metadata:t,image:n}=(0,k.L)();return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(v.Z,{children:[(0,i.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,i.jsx)("body",{className:_.h})]}),n&&(0,i.jsx)(S.d,{image:n}),(0,i.jsx)(A,{}),(0,i.jsx)(N,{}),(0,i.jsx)(T.Z,{tag:"default",locale:e}),(0,i.jsx)(v.Z,{children:t.map((e,t)=>(0,i.jsx)("meta",{...e},t))})]})}let P=new Map;var j=n("258"),L=n("1716"),R=n("2000");function I(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];let a=p.map(t=>{let r=t.default?.[e]??t[e];return r?.(...n)});return()=>a.forEach(e=>e?.())}let M=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,R.Z)(()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;let r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;let{hash:i}=t;if(i){let e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),I("onRouteDidUpdate",{previousLocation:r,location:n}))},[r,n]),t};function F(e){return Promise.all(Array.from(new Set([e,decodeURI(e)])).map(e=>y(h.Z,e)).flat().map(e=>e.route.component.preload?.()))}class D extends l.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=f.Z.canUseDOM?I("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;let n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=I("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),F(n.pathname).then(()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})}).catch(e=>{console.warn(e),window.location.reload()}),!1}render(){let{children:e,location:t}=this.props;return(0,i.jsx)(M,{previousLocation:this.previousLocation,location:t,children:(0,i.jsx)(g.AW,{location:t,render:()=>e})})}}let z="__docusaurus-base-url-issue-banner-suggestion-container";function $(){var e,t;let{siteConfig:{baseUrl:n}}=(0,x.Z)();return(0,i.jsx)(i.Fragment,{children:!f.Z.canUseDOM&&(0,i.jsx)(v.Z,{children:(0,i.jsx)("script",{children:(e=n,` +document.addEventListener('DOMContentLoaded', function maybeInsertBanner() { + var shouldInsert = typeof window['docusaurus'] === 'undefined'; + shouldInsert && insertBanner(); +}); + +function insertBanner() { + var bannerContainer = document.createElement('div'); + bannerContainer.id = '__docusaurus-base-url-issue-banner-container'; + var bannerHtml = ${JSON.stringify((t=e,` +<div id="__docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;"> + <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p> + <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p> + <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${t}</span> ${"/"===t?" (default value)":""}</p> + <p>We suggest trying baseUrl = <span id="${z}" style="font-weight: bold; color: green;"></span></p> +</div> +`)).replace(/</g,"\\<")}; + bannerContainer.innerHTML = bannerHtml; + document.body.prepend(bannerContainer); + var suggestionContainer = document.getElementById('${z}'); + var actualHomePagePath = window.location.pathname; + var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/' + ? actualHomePagePath + : actualHomePagePath + '/'; + suggestionContainer.innerHTML = suggestedBaseUrl; +} +`)})})})}function B(){let{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,x.Z)(),{pathname:n}=(0,g.TH)();return t&&n===e?(0,i.jsx)($,{}):null}function U(){let{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:a}}=(0,x.Z)(),o=(0,w.ZP)(e),{htmlLang:l,direction:s}=a[r];return(0,i.jsxs)(v.Z,{children:[(0,i.jsx)("html",{lang:l,dir:s}),(0,i.jsx)("title",{children:t}),(0,i.jsx)("meta",{property:"og:title",content:t}),(0,i.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"}),e&&(0,i.jsx)("link",{rel:"icon",href:o})]})}var H=n("6893"),Z=n("7227");function W(){let e=(0,Z.Z)();return(0,i.jsx)(v.Z,{children:(0,i.jsx)("html",{"data-has-hydrated":e})})}let V=(r=h.Z,void 0===a&&(a={}),void 0===o&&(o={}),r?l.createElement(g.rs,o,r.map(function(e,t){return l.createElement(g.AW,{key:e.key||t,path:e.path,exact:e.exact,strict:e.strict,render:function(t){return e.render?e.render((0,m.Z)({},t,{},a,{route:e})):l.createElement(e.component,(0,m.Z)({},t,a,{route:e}))}})})):null);function G(){let e=function(e){if(P.has(e.pathname))return{...e,pathname:P.get(e.pathname)};if(y(h.Z,e.pathname).some(e=>{let{route:t}=e;return!0===t.exact}))return P.set(e.pathname,e.pathname),e;let t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return P.set(e.pathname,t),{...e,pathname:t}}((0,g.TH)());return(0,i.jsx)(D,{location:e,children:V})}var q=n("7138");let Y=!function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise((t,n)=>{let r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)})}:function(e){return new Promise((t,n)=>{if("undefined"==typeof document){n();return}let r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();let a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)})};var K=n("6464");let Q=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee=e=>!J()&&!X.has(e)&&!Q.has(e),et=e=>!J()&&!X.has(e),en=e=>Object.entries(q).filter(t=>{let[n]=t;return n.replace(/-[^-]+$/,"")===e}).flatMap(e=>{let[,t]=e;return Object.values((0,K.Z)(t))}),er=Object.freeze({prefetch:e=>!!ee(e)&&(Q.add(e),Promise.all(y(h.Z,e).flatMap(e=>en(e.route.path)).map(e=>{let t=n.gca(e);if(t&&!t.includes("undefined"))return Y(t).catch(()=>{});return Promise.resolve()}))),preload:e=>!!et(e)&&(X.add(e),F(e))});e=n.hmd(e);if(f.Z.canUseDOM){window.docusaurus=er;let t=document.getElementById("__docusaurus"),n=(0,i.jsx)(u.B6,{children:(0,i.jsx)(function(e){let{children:t}=e;return"hash"===d.default.future.experimental_router?(0,i.jsx)(c.UT,{children:t}):(0,i.jsx)(c.VK,{children:t})},{children:(0,i.jsx)(function(){return(0,i.jsx)(H.Z,{children:(0,i.jsx)(L.M,{children:(0,i.jsxs)(j.t,{children:[(0,i.jsxs)(b,{children:[(0,i.jsx)(U,{}),(0,i.jsx)(O,{}),(0,i.jsx)(B,{}),(0,i.jsx)(G,{})]}),(0,i.jsx)(W,{})]})})})},{})})}),r=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},a=()=>{if(window.docusaurusRoot){window.docusaurusRoot.render(n);return}window.docusaurusRoot=s.hydrateRoot(t,n,{onRecoverableError:r})};F(window.location.pathname).then(()=>{(0,l.startTransition)(a)}),e.hot&&e.hot.accept()}},1716:function(e,t,n){"use strict";n.d(t,{_:()=>d,M:()=>f});var r=n("5893"),a=n("7294"),o=n("5150"),i=JSON.parse('{"docusaurus-lunr-search":{"default":{"fileNames":{"searchDoc":"search-doc-1731274975527.json","lunrIndex":"lunr-index-1731274975527.json"}}}}'),l=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}'),s=n("2627"),u=JSON.parse('{"docusaurusVersion":"3.6.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.6.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.6.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.6.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.6.0"},"docusaurus-lunr-search":{"type":"package","name":"docusaurus-lunr-search","version":"3.5.0"}}}');let c={siteConfig:o.default,siteMetadata:u,globalData:i,i18n:l,codeTranslations:s},d=a.createContext(c);function f(e){let{children:t}=e;return(0,r.jsx)(d.Provider,{value:c,children:t})}},6893:function(e,t,n){"use strict";n.d(t,{Z:()=>g});var r=n("5893"),a=n("7294"),o=n("7565"),i=n("4819"),l=n("8365"),s=n("5654"),u=n("4879");function c(e){let{error:t,tryAgain:n}=e;return(0,r.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,r.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,r.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,r.jsx)(d,{error:t})]})}function d(e){let{error:t}=e,n=(0,l.getErrorCausalChain)(t).map(e=>e.message).join("\n\nCause:\n");return(0,r.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function f(e){let{children:t}=e;return(0,r.jsx)(u.z,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function p(e){let{error:t,tryAgain:n}=e;return(0,r.jsx)(f,{children:(0,r.jsxs)(g,{fallback:()=>(0,r.jsx)(c,{error:t,tryAgain:n}),children:[(0,r.jsx)(i.Z,{children:(0,r.jsx)("title",{children:"Page Error"})}),(0,r.jsx)(s.Z,{children:(0,r.jsx)(c,{error:t,tryAgain:n})})]})})}let h=e=>(0,r.jsx)(p,{...e});class g extends a.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.Z.canUseDOM&&this.setState({error:e})}render(){let{children:e}=this.props,{error:t}=this.state;return t?(this.props.fallback??h)({error:t,tryAgain:()=>this.setState({error:null})}):e??null}}},7565:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});let r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},4819:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var r=n(5893);n(7294);var a=n(405);function o(e){return(0,r.jsx)(a.ql,{...e})}},3012:function(e,t,n){"use strict";n.d(t,{Z:function(){return p}});var r=n(5893),a=n(7294),o=n(3727),i=n(8365),l=n(2933),s=n(3150),u=n(7565),c=n(1065),d=n(4757);let f=e=>e.startsWith("/"),p=a.forwardRef(function(e,t){var n;let{isNavLink:p,to:h,href:g,activeClassName:m,isActive:y,"data-noBrokenLinkCheck":b,autoAddBaseUrl:v=!0,...x}=e,{siteConfig:w}=(0,l.Z)(),{trailingSlash:k,baseUrl:S}=w,E=w.future.experimental_router,{withBaseUrl:_}=(0,d.Cg)(),C=(0,c.Z)(),T=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,()=>T.current);let N=h||g,A=(0,s.Z)(N),O=N?.replace("pathname://","");let P=void 0!==O?(n=O,v&&f(n)?_(n):n):void 0;"hash"===E&&P?.startsWith("./")&&(P=P?.slice(1)),P&&A&&(P=(0,i.applyTrailingSlash)(P,{trailingSlash:k,baseUrl:S}));let j=(0,a.useRef)(!1),L=p?o.OL:o.rU,R=u.Z.canUseIntersectionObserver,I=(0,a.useRef)(),M=()=>{!j.current&&null!=P&&(window.docusaurus.preload(P),j.current=!0)};(0,a.useEffect)(()=>(!R&&A&&u.Z.canUseDOM&&null!=P&&window.docusaurus.prefetch(P),()=>{R&&I.current&&I.current.disconnect()}),[I,P,R,A]);let F=P?.startsWith("#")??!1,D=!x.target||"_self"===x.target,z=!P||!A||!D||F&&"hash"!==E;!b&&(F||!z)&&C.collectLink(P),x.id&&C.collectAnchor(x.id);let $={};return z?(0,r.jsx)("a",{ref:T,href:P,...N&&!A&&{target:"_blank",rel:"noopener noreferrer"},...x,...$}):(0,r.jsx)(L,{...x,onMouseEnter:M,onTouchStart:M,innerRef:e=>{T.current=e,R&&e&&A&&(I.current=new window.IntersectionObserver(t=>{t.forEach(t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(I.current.unobserve(e),I.current.disconnect(),null!=P&&window.docusaurus.prefetch(P))})}),I.current.observe(e))},to:P,...p&&{isActive:y,activeClassName:m},...$})})},6025:function(e,t,n){"use strict";n.d(t,{Z:()=>u,I:()=>s});var r=n("5893"),a=n("7294");function o(e,t){let n=e.split(/(\{\w+\})/).map((e,n)=>{if(n%2==1){let n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e});return n.some(e=>(0,a.isValidElement)(e))?n.map((e,t)=>(0,a.isValidElement)(e)?a.cloneElement(e,{key:t}):e).filter(e=>""!==e):n.join("")}var i=n("2627");function l(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return o(l({message:n,id:r}),t)}function u(e){let{children:t,id:n,values:a}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),Error("The Docusaurus <Translate> component only accept simple string values");let i=l({message:t,id:n});return(0,r.jsx)(r.Fragment,{children:o(i,a)})}},3150:function(e,t,n){"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:function(){return a},b:function(){return r}})},4757:function(e,t,n){"use strict";n.d(t,{Cg:function(){return i},ZP:function(){return l}});var r=n(7294),a=n(2933),o=n(3150);function i(){let{siteConfig:e}=(0,a.Z)(),{baseUrl:t,url:n}=e,i=e.future.experimental_router;return{withBaseUrl:(0,r.useCallback)((e,r)=>(function(e){let{siteUrl:t,baseUrl:n,url:r,options:{forcePrependBaseUrl:a=!1,absolute:i=!1}={},router:l}=e;if(!r||r.startsWith("#")||(0,o.b)(r))return r;if("hash"===l)return r.startsWith("/")?`.${r}`:`./${r}`;if(a)return n+r.replace(/^\//,"");if(r===n.replace(/\/$/,""))return n;let s=r.startsWith(n)?r:n+r.replace(/^\//,"");return i?t+s:s})({siteUrl:n,baseUrl:t,url:e,options:r,router:i}),[n,t,i])}}function l(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},{withBaseUrl:n}=i();return n(e,t)}},1065:function(e,t,n){"use strict";n.d(t,{Z:()=>i}),n("5893");var r=n("7294");let a=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),o=()=>(0,r.useContext)(a);function i(){return o()}},2933:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var r=n(7294),a=n(1716);function o(){return(0,r.useContext)(a._)}},7227:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var r=n(7294),a=n(258);function o(){return(0,r.useContext)(a._)}},2e3:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});var r=n(7294);let a=n(7565).Z.canUseDOM?r.useLayoutEffect:r.useEffect},8312:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var r=n(7294),a=n(4879);function o(){let e=r.useContext(a._);if(!e)throw Error("Unexpected: no Docusaurus route context found");return e}},6464:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});let r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){let t={};return!function e(n,a){Object.entries(n).forEach(n=>{let[o,i]=n,l=a?`${a}.${o}`:o;r(i)?e(i,l):t[l]=i})}(e),t}},4879:function(e,t,n){"use strict";n.d(t,{_:function(){return o},z:function(){return i}});var r=n(5893),a=n(7294);let o=a.createContext(null);function i(e){let{children:t,value:n}=e,i=a.useContext(o),l=(0,a.useMemo)(()=>(function(e){let{parent:t,value:n}=e;if(!t){if(n){if(!("plugin"in n))throw Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute")}else throw Error("Unexpected: no Docusaurus route context found");return n}let r={...t.data,...n?.data};return{plugin:t.plugin,data:r}})({parent:i,value:n}),[i,n]);return(0,r.jsx)(o.Provider,{value:l,children:t})}},1987:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return o}});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});let o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){let e=window.setTimeout(()=>{a().start()},200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},1569:function(e,t,n){"use strict";var r=n("3229"),a=n("5150");!function(e){let{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t,o=globalThis.Prism;globalThis.Prism=e,r.forEach(e=>{"php"===e&&n(6854),n(8092)(`./prism-${e}`)}),delete globalThis.Prism,void 0!==o&&(globalThis.Prism=e)}(r.p1)},4403:function(e,t,n){"use strict";n.d(t,{Z:()=>c});var r=n("5893");n("7294");var a=n("7026"),o=n("6025"),i=n("140"),l=n("3012"),s=n("1065");let u={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};function c(e){let{as:t,id:n,...c}=e,d=(0,s.Z)(),{navbar:{hideOnScroll:f}}=(0,i.L)();if("h1"===t||!n)return(0,r.jsx)(t,{...c,id:void 0});d.collectAnchor(n);let p=(0,o.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof c.children?c.children:n});return(0,r.jsxs)(t,{...c,className:(0,a.Z)("anchor",f?u.anchorWithHideOnScrollNavbar:u.anchorWithStickyNavbar,c.className),id:n,children:[c.children,(0,r.jsx)(l.Z,{className:"hash-link",to:`#${n}`,"aria-label":p,title:p,children:"\u200B"})]})}},5654:function(e,t,n){"use strict";n.d(t,{Z:()=>tL});var r=n("5893"),a=n("7294"),o=n("7026"),i=n("6893"),l=n("2743"),s=n("6550"),u=n("6025"),c=n("5346");function d(e){let t=(0,s.TH)(),n=(0,c.D9)(t),r=(0,c.zX)(e);(0,a.useEffect)(()=>{if(!!n)t!==n&&r({location:t,previousLocation:n})},[r,t,n])}let f="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}let h=(0,u.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){let t=e.children??h,{containerRef:n,onClick:o}=function(){let e=(0,a.useRef)(null),{action:t}=(0,s.k6)(),n=(0,a.useCallback)(e=>{e.preventDefault();let t=document.querySelector("main:first-of-type")??document.getElementById(f);t&&p(t)},[]);return d(n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)}),{containerRef:e,onClick:n}}();return(0,r.jsx)("div",{ref:n,role:"region","aria-label":h,children:(0,r.jsx)("a",{...e,href:`#${f}`,onClick:o,children:t})})}var m=n("4681"),y=n("6959");let b="skipToContent_fXgn";function v(){return(0,r.jsx)(g,{className:b})}var x=n("140"),w=n("7227"),k=n("6009");let S=(0,k.WA)("docusaurus.announcement.dismiss"),E=(0,k.WA)("docusaurus.announcement.id"),_=()=>"true"===S.get(),C=e=>S.set(String(e)),T=a.createContext(null);function N(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return(0,r.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...l,children:(0,r.jsx)("g",{stroke:a,strokeWidth:o,children:(0,r.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}let A="closeButton_CVFx";function O(e){return(0,r.jsx)("button",{type:"button","aria-label":(0,u.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.Z)("clean-btn close",A,e.className),children:(0,r.jsx)(N,{width:14,height:14,strokeWidth:3.1})})}let P="content_knG7";function j(e){let{announcementBar:t}=(0,x.L)(),{content:n}=t;return(0,r.jsx)("div",{...e,className:(0,o.Z)(P,e.className),dangerouslySetInnerHTML:{__html:n}})}let L={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function R(){let{announcementBar:e}=(0,x.L)(),{isActive:t,close:n}=function(){let e=(0,a.useContext)(T);if(!e)throw new c.i6("AnnouncementBarProvider");return e}();if(!t)return null;let{backgroundColor:o,textColor:i,isCloseable:l}=e;return(0,r.jsxs)("div",{className:L.announcementBar,style:{backgroundColor:o,color:i},role:"banner",children:[l&&(0,r.jsx)("div",{className:L.announcementBarPlaceholder}),(0,r.jsx)(j,{className:L.announcementBarContent}),l&&(0,r.jsx)(O,{onClick:n,className:L.announcementBarClose})]})}var I=n("1179"),M=n("4704");let F=a.createContext(void 0);function D(e){let{children:t}=e,n=function(){var e;let t=function(){let e=(0,I.HY)(),{items:t}=(0,x.L)().navbar;return 0===t.length&&!e.component}(),n=(0,M.i)(),r=!t&&"mobile"===n,[o,i]=(0,a.useState)(!1);e=()=>{if(o)return i(!1),!1},function(e){let t=(0,s.k6)(),n=(0,c.zX)(e);(0,a.useEffect)(()=>t.block((e,t)=>n(e,t)),[t,n])}((t,n)=>{if("POP"===n)return e(t,n)});let l=(0,a.useCallback)(()=>{i(e=>!e)},[]);return(0,a.useEffect)(()=>{"desktop"===n&&i(!1)},[n]),(0,a.useMemo)(()=>({disabled:t,shouldRender:r,toggle:l,shown:o}),[t,r,l,o])}();return(0,r.jsx)(F.Provider,{value:n,children:t})}function z(){let e=a.useContext(F);if(void 0===e)throw new c.i6("NavbarMobileSidebarProvider");return e}var $=n("7565");n("2000");let B=a.createContext(void 0),U=()=>$.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null,H=a.createContext(null);function Z(e){let{children:t}=e,n=function(){let e=z(),t=(0,I.HY)(),[n,r]=(0,a.useState)(!1),o=null!==t.component,i=(0,c.D9)(o);return(0,a.useEffect)(()=>{o&&!i&&r(!0)},[o,i]),(0,a.useEffect)(()=>{if(!o){r(!1);return}!e.shown&&r(!0)},[e.shown,o]),(0,a.useMemo)(()=>[n,r],[n])}();return(0,r.jsx)(H.Provider,{value:n,children:t})}function W(){let e=(0,a.useContext)(H);if(!e)throw new c.i6("NavbarSecondaryMenuDisplayProvider");let[t,n]=e,o=(0,a.useCallback)(()=>n(!1),[n]),i=(0,I.HY)();return(0,a.useMemo)(()=>({shown:t,hide:o,content:function(e){if(e.component){let t=e.component;return(0,r.jsx)(t,{...e.props})}}(i)}),[o,i,t])}function V(e){let{header:t,primaryMenu:n,secondaryMenu:a}=e,{shown:i}=W();return(0,r.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,r.jsxs)("div",{className:(0,o.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i}),children:[(0,r.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,r.jsx)("div",{className:"navbar-sidebar__item menu",children:a})]})]})}var G=n("4239");function q(e){return(0,r.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,r.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function Y(e){return(0,r.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,r.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}let K={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"},Q=a.memo(function(e){let{className:t,buttonClassName:n,value:a,onChange:i}=e,l=(0,w.Z)(),s=(0,u.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===a?(0,u.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,u.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,r.jsx)("div",{className:(0,o.Z)(K.toggle,t),children:(0,r.jsxs)("button",{className:(0,o.Z)("clean-btn",K.toggleButton,!l&&K.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===a?"light":"dark"),disabled:!l,title:s,"aria-label":s,"aria-live":"polite","aria-pressed":"dark"===a?"true":"false",children:[(0,r.jsx)(q,{className:(0,o.Z)(K.toggleIcon,K.lightToggleIcon)}),(0,r.jsx)(Y,{className:(0,o.Z)(K.toggleIcon,K.darkToggleIcon)})]})})}),X={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function J(e){let{className:t}=e,n=(0,x.L)().navbar.style,a=(0,x.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:i}=(0,G.I)();return a?null:(0,r.jsx)(Q,{className:t,buttonClassName:"dark"===n?X.darkNavbarColorModeToggle:void 0,value:o,onChange:i})}var ee=n("3012"),et=n("4757"),en=n("2933");let er={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};function ea(e){let{className:t,children:n}=e,i=(0,w.Z)(),{colorMode:l}=(0,G.I)();return(0,r.jsx)(r.Fragment,{children:(i?"dark"===l?["dark"]:["light"]:["light","dark"]).map(e=>{let i=n({theme:e,className:(0,o.Z)(t,er.themedComponent,er[`themedComponent--${e}`])});return(0,r.jsx)(a.Fragment,{children:i},e)})})}function eo(e){let{sources:t,className:n,alt:a,...o}=e;return(0,r.jsx)(ea,{className:n,children:e=>{let{theme:n,className:i}=e;return(0,r.jsx)("img",{src:t[n],alt:a,className:i,...o})}})}function ei(e){let{logo:t,alt:n,imageClassName:a}=e,o={light:(0,et.ZP)(t.src),dark:(0,et.ZP)(t.srcDark||t.src)},i=(0,r.jsx)(eo,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return a?(0,r.jsx)("div",{className:a,children:i}):i}function el(e){let{siteConfig:{title:t}}=(0,en.Z)(),{navbar:{title:n,logo:a}}=(0,x.L)(),{imageClassName:o,titleClassName:i,...l}=e,s=(0,et.ZP)(a?.href||"/"),u=a?.alt??(n?"":t);return(0,r.jsxs)(ee.Z,{to:s,...l,...a?.target&&{target:a.target},children:[a&&(0,r.jsx)(ei,{logo:a,alt:u,imageClassName:o}),null!=n&&(0,r.jsx)("b",{className:i,children:n})]})}function es(){return(0,r.jsx)(el,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function eu(){let e=z();return(0,r.jsx)("button",{type:"button","aria-label":(0,u.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,r.jsx)(N,{color:"var(--ifm-color-emphasis-600)"})})}function ec(){return(0,r.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,r.jsx)(es,{}),(0,r.jsx)(J,{className:"margin-right--md"}),(0,r.jsx)(eu,{})]})}var ed=n("3150");function ef(e,t){return void 0!==e&&void 0!==t&&RegExp(e,"gi").test(t)}let ep="iconExternalLink_nPIU";function eh(e){let{width:t=13.5,height:n=13.5}=e;return(0,r.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:ep,children:(0,r.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}function eg(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:l,isDropdownLink:s,prependBaseUrlToHref:u,...c}=e,d=(0,et.ZP)(a),f=(0,et.ZP)(t),p=(0,et.ZP)(o,{forcePrependBaseUrl:!0}),h=i&&o&&!(0,ed.Z)(o),g=l?{dangerouslySetInnerHTML:{__html:l}}:{children:(0,r.jsxs)(r.Fragment,{children:[i,h&&(0,r.jsx)(eh,{...s&&{width:12,height:12}})]})};return o?(0,r.jsx)(ee.Z,{href:u?p:o,...c,...g}):(0,r.jsx)(ee.Z,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ef(n,t.pathname):t.pathname.startsWith(f)},...c,...g})}function em(e){let{className:t,isDropdownItem:n=!1,...a}=e,i=(0,r.jsx)(eg,{className:(0,o.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...a});return n?(0,r.jsx)("li",{children:i}):i}function ey(e){let{className:t,isDropdownItem:n,...a}=e;return(0,r.jsx)("li",{className:"menu__list-item",children:(0,r.jsx)(eg,{className:(0,o.Z)("menu__link",t),...a})})}function eb(e){let{mobile:t=!1,position:n,...a}=e;return(0,r.jsx)(t?ey:em,{...a,activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ev=n("1276"),ex=n("9246");let ew="dropdownNavbarItemMobile_S0Fm";function ek(e){let{items:t,position:n,className:i,onClick:l,...s}=e,u=(0,a.useRef)(null),[c,d]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{let e=e=>{if(!(!u.current||u.current.contains(e.target)))d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}},[u]),(0,r.jsxs)("div",{ref:u,className:(0,o.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,r.jsx)(eg,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,o.Z)("navbar__link",i),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,r.jsx)("ul",{className:"dropdown__menu",children:t.map((e,t)=>(0,a.createElement)(e4,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t}))})]})}function eS(e){var t,n;let{items:i,className:l,position:u,onClick:c,...d}=e,f=function(){let{siteConfig:{baseUrl:e}}=(0,en.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}();let p=(t=i,n=f,t.some(e=>{var t,r;return t=e,r=n,!!((0,ex.Mg)(t.to,r)||ef(t.activeBaseRegex,r)||t.activeBasePath&&r.startsWith(t.activeBasePath))||!1})),{collapsed:h,toggleCollapsed:g,setCollapsed:m}=(0,ev.u)({initialState:()=>!p});return(0,a.useEffect)(()=>{p&&m(!p)},[f,p,m]),(0,r.jsxs)("li",{className:(0,o.Z)("menu__list-item",{"menu__list-item--collapsed":h}),children:[(0,r.jsx)(eg,{role:"button",className:(0,o.Z)(ew,"menu__link menu__link--sublist menu__link--sublist-caret",l),...d,onClick:e=>{e.preventDefault(),g()},children:d.children??d.label}),(0,r.jsx)(ev.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:h,children:i.map((e,t)=>(0,a.createElement)(e4,{mobile:!0,isDropdownItem:!0,onClick:c,activeClassName:"menu__link--active",...e,key:t}))})]})}function eE(e){let{mobile:t=!1,...n}=e;return(0,r.jsx)(t?eS:ek,{...n})}var e_=n("8910");function eC(e){let{width:t=20,height:n=20,...a}=e;return(0,r.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...a,children:(0,r.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}let eT="iconLanguage_nlXk",eN=function(){for(var e,t,n=0,r="";n<arguments.length;)(e=arguments[n++])&&(t=function e(t){var n,r,a="";if("string"==typeof t||"number"==typeof t)a+=t;else if("object"==typeof t){if(Array.isArray(t))for(n=0;n<t.length;n++)t[n]&&(r=e(t[n]))&&(a&&(a+=" "),a+=r);else for(n in t)t[n]&&(a&&(a+=" "),a+=n)}return a}(e))&&(r&&(r+=" "),r+=t);return r},eA="default";function eO(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=function(){let{globalData:e}=(0,en.Z)();return e}()[e];if(!n&&t.failfast)throw Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}function eP(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:eA,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=eO(e),a=r?.[t];if(!a&&n.failfast)throw Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}var ej=n("813"),eL=n.n(ej);function eR(){let e=(0,s.TH)(),t=(0,s.k6)(),{siteConfig:{baseUrl:n}}=(0,en.Z)(),[r,o]=(0,a.useState)({wordToHighlight:"",isTitleSuggestion:!1,titleText:""});return(0,a.useEffect)(()=>{if(!e.state?.highlightState||0===e.state.highlightState.wordToHighlight.length)return;o(e.state.highlightState);let{highlightState:n,...r}=e.state;t.replace({...e,state:r})},[e.state?.highlightState,t,e]),(0,a.useEffect)(()=>{if(0===r.wordToHighlight.length)return;let e=document.getElementsByTagName("article")[0]??document.getElementsByTagName("main")[0];if(!e)return;let t=new(eL())(e),n={ignoreJoiners:!0};return t.mark(r.wordToHighlight,n),()=>t.unmark(n)},[r,n]),null}let eI=e=>{let t;let o=(0,a.useRef)(!1),i=(0,a.useRef)(null),[l,u]=(0,a.useState)(!1),c=(0,s.k6)(),{siteConfig:d={}}=(0,en.Z)(),f=(d.plugins||[]).find(e=>Array.isArray(e)&&"string"==typeof e[0]&&e[0].includes("docusaurus-lunr-search")),p=(0,w.Z)(),{baseUrl:h}=d,g=f&&f[1]?.assetUrl||h,m=(e,t,n,r)=>{new n({searchDocs:e,searchIndex:t,baseUrl:h,inputSelector:"#search_input_react",handleSelected:(e,t,n)=>{let a=n.url||"/";document.createElement("a").href=a,e.setVal(""),t.target.blur();let o="";if(r.highlightResult)try{let e=(n.text||n.subcategory||n.title).match(RegExp("<span.+span>\\w*","g"));if(e&&e.length>0){let t=document.createElement("div");t.innerHTML=e[0],o=t.textContent}}catch(e){console.log(e)}c.push(a,{highlightState:{wordToHighlight:o}})},maxHits:r.maxHits})},y=eP("docusaurus-lunr-search"),b=()=>fetch(`${g}${y.fileNames.searchDoc}`).then(e=>e.json()),v=()=>fetch(`${g}${y.fileNames.lunrIndex}`).then(e=>e.json()),x=()=>{!o.current&&(Promise.all([b(),v(),Promise.all([n.e("4294"),n.e("9990")]).then(n.bind(n,5322)),Promise.all([n.e("6212"),n.e("2061")]).then(n.bind(n,8544))]).then(e=>{let[t,n,{default:r}]=e,{searchDocs:a,options:o}=t;if(!!a&&0!==a.length)m(a,n,r,o),u(!0)}),o.current=!0)},k=(0,a.useCallback)(t=>{!i.current.contains(t.target)&&i.current.focus(),e.handleSearchBarToggle&&e.handleSearchBarToggle(!e.isSearchBarExpanded)},[e.isSearchBarExpanded]);return p&&(x(),t=window.navigator.platform.startsWith("Mac")?"Search \u2318+K":"Search Ctrl+K"),(0,a.useEffect)(()=>{e.autoFocus&&l&&i.current.focus()},[l]),(0,r.jsxs)("div",{className:"navbar__search",children:[(0,r.jsx)("span",{"aria-label":"expand searchbar",role:"button",className:eN("search-icon",{"search-icon-hidden":e.isSearchBarExpanded}),onClick:k,onKeyDown:k,tabIndex:0}),(0,r.jsx)("input",{id:"search_input_react",type:"search",placeholder:l?t:"Loading...","aria-label":"Search",className:eN("navbar__search-input",{"search-bar-expanded":e.isSearchBarExpanded},{"search-bar":!e.isSearchBarExpanded}),onClick:x,onMouseOver:x,onFocus:k,onBlur:k,ref:i,disabled:!l}),(0,r.jsx)(eR,{})]},"search-box")},eM="navbarSearchContainer_Bca1";function eF(e){let{children:t,className:n}=e;return(0,r.jsx)("div",{className:(0,o.Z)(n,eM),children:t})}let eD=e=>e.versions.find(e=>e.isLast),ez={},e$=()=>eO("docusaurus-plugin-content-docs")??ez,eB=e=>{try{return eP("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw Error(`You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled${"Default"===e?"":` (pluginId=${e}`}`,{cause:t})}};function eU(e){let t=eB(e),{pathname:n}=(0,s.TH)();return function(e,t){var n,r;let a=(n=e,r=t,[...n.versions].sort((e,t)=>e.path===t.path?0:e.path.includes(t.path)?-1:t.path.includes(e.path)?1:0).find(e=>!!(0,s.LX)(r,{path:e.path,exact:!1,strict:!1}))),o=a?.docs.find(e=>!!s.LX(t,{path:e.path,exact:!0,strict:!1})),i=o?function(t){let n={};return e.versions.forEach(e=>{e.docs.forEach(r=>{r.id===t&&(n[e.name]=r)})}),n}(o.id):{};return{activeVersion:a,activeDoc:o,alternateDocVersions:i}}(t,n)}function eH(e){return Array.from(new Set(e))}let eZ=e=>`docs-preferred-version-${e}`,eW=(e,t,n)=>{(0,k.WA)(eZ(e),{persistence:t}).set(n)},eV=(e,t)=>(0,k.WA)(eZ(e),{persistence:t}).get(),eG=(e,t)=>{(0,k.WA)(eZ(e),{persistence:t}).del()},eq=e=>Object.fromEntries(e.map(e=>[e,{preferredVersionName:null}])),eY=a.createContext(null);function eK(e){let{children:t}=e,n=function(){let e=e$(),t=(0,x.L)().docs.versionPersistence,n=(0,a.useMemo)(()=>Object.keys(e),[e]),[r,o]=(0,a.useState)(()=>eq(n));return(0,a.useEffect)(()=>{o(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;return Object.fromEntries(t.map(e=>[e,function(e){let t=eV(e,n);return r[e].versions.some(e=>e.name===t)?{preferredVersionName:t}:(eG(e,n),{preferredVersionName:null})}(e)]))}({allDocsData:e,versionPersistence:t,pluginIds:n}))},[e,t,n]),[r,(0,a.useMemo)(()=>({savePreferredVersion:function(e,n){eW(e,t,n),o(t=>({...t,[e]:{preferredVersionName:n}}))}}),[t])]}();return(0,r.jsx)(eY.Provider,{value:n,children:t})}function eQ(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:eA,t=eB(e),[n,r]=function(){let e=(0,a.useContext)(eY);if(!e)throw new c.i6("DocsPreferredVersionContextProvider");return e}(),{preferredVersionName:o}=n[e],i=t.versions.find(e=>e.name===o)??null;return{preferredVersion:i,savePreferredVersionName:(0,a.useCallback)(t=>{r.savePreferredVersion(e,t)},[r,e])}}let eX=(e,t)=>void 0!==e&&isSamePath(e,t),eJ=(e,t)=>e.some(e=>(function(e,t){return"link"===e.type?eX(e.href,t):"category"===e.type&&(eX(e.href,t)||eJ(e.items,t))})(e,t));function e0(e){let{activeVersion:t}=eU(e),{preferredVersion:n}=eQ(e),r=eD(eB(e));return(0,a.useMemo)(()=>eH([t,n,r].filter(Boolean)),[t,n,r])}let e1=e=>e.docs.find(t=>t.id===e.mainDocId);function e2(e,t){var n;return t.alternateDocVersions[e.name]??(n=e).docs.find(e=>e.id===n.mainDocId)}let e3={default:eb,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,queryString:o="",...i}=e,{i18n:{currentLocale:l,locales:c,localeConfigs:d}}=(0,en.Z)(),f=(0,e_.l)(),{search:p,hash:h}=(0,s.TH)(),g=[...n,...c.map(e=>{let n=`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`,r=`${n}${p}${h}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:r,target:"_self",autoAddBaseUrl:!1,className:e===l?t?"menu__link--active":"dropdown__link--active":""}}),...a],m=t?(0,u.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[l].label;return(0,r.jsx)(eE,{...i,mobile:t,label:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(eC,{className:eT}),m]}),items:g})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,r.jsx)(eF,{className:n,children:(0,r.jsx)(eI,{})})},dropdown:eE,html:function(e){let{value:t,className:n,mobile:a=!1,isDropdownItem:i=!1}=e;return(0,r.jsx)(i?"li":"div",{className:(0,o.Z)({navbar__item:!a&&!i,"menu__list-item":a},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:o,...i}=e,{activeDoc:l}=eU(o),s=function(e,t){let n=e0(t);return(0,a.useMemo)(()=>{let t=n.flatMap(e=>e.docs),r=t.find(t=>t.id===e);if(!r){if(n.flatMap(e=>e.draftIds).includes(e))return null;throw Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map(e=>e.name).join(", ")}". +Available doc ids are: +- ${eH(t.map(e=>e.id)).join("\n- ")}`)}return r},[e,n])}(t,o),u=l?.path===s?.path;return null===s||s.unlisted&&!u?null:(0,r.jsx)(eb,{exact:!0,...i,isActive:()=>u||!!l?.sidebar&&l.sidebar===s.sidebar,label:n??s.id,to:s.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:o,...i}=e,{activeDoc:l}=eU(o),s=function(e,t){let n=e0(t);return(0,a.useMemo)(()=>{let t=n.flatMap(e=>e.sidebars?Object.entries(e.sidebars):[]),r=t.find(t=>t[0]===e);if(!r)throw Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map(e=>e.name).join(", ")}". +Available sidebar ids are: +- ${t.map(e=>e[0]).join("\n- ")}`);return r[1]},[e,n])}(t,o).link;if(!s)throw Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,r.jsx)(eb,{exact:!0,...i,isActive:()=>l?.sidebar===t,label:n??s.label,to:s.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e,i=e0(a)[0],l=t??i.label,s=n??e1(i).path;return(0,r.jsx)(eb,{...o,label:l,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...l}=e,{search:c,hash:d}=(0,s.TH)(),f=eU(n),p=eB(n).versions,{savePreferredVersionName:h}=eQ(n),g=[...o,...p.map(function(e){let t=e2(e,f);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===f.activeVersion,onClick:()=>h(e.name)}}),...i],m=e0(n)[0],y=t&&g.length>1?(0,u.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):m.label,b=t&&g.length>1?void 0:e2(m,f).path;return g.length<=1?(0,r.jsx)(eb,{...l,mobile:t,label:y,to:b,isActive:a?()=>!1:void 0}):(0,r.jsx)(eE,{...l,mobile:t,label:y,to:b,items:g,isActive:a?()=>!1:void 0})}};function e4(e){var t,n;let{type:a,...o}=e;let i=e3[t=a,n=o,t&&"default"!==t?t:"items"in n?"dropdown":"default"];if(!i)throw Error(`No NavbarItem component found for type "${a}".`);return(0,r.jsx)(i,{...o})}function e9(){let e=z(),t=(0,x.L)().navbar.items;return(0,r.jsx)("ul",{className:"menu__list",children:t.map((t,n)=>(0,a.createElement)(e4,{mobile:!0,...t,onClick:()=>e.toggle(),key:n}))})}function e8(e){return(0,r.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,r.jsx)(u.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function e6(){let e=0===(0,x.L)().navbar.items.length,t=W();return(0,r.jsxs)(r.Fragment,{children:[!e&&(0,r.jsx)(e8,{onClick:()=>t.hide()}),t.content]})}function e5(){let e=z();return(!function(){let e=!(arguments.length>0)||void 0===arguments[0]||arguments[0];(0,a.useEffect)(()=>(document.body.style.overflow=e?"hidden":"visible",()=>{document.body.style.overflow="visible"}),[e])}(e.shown),e.shouldRender)?(0,r.jsx)(V,{header:(0,r.jsx)(ec,{}),primaryMenu:(0,r.jsx)(e9,{}),secondaryMenu:(0,r.jsx)(e6,{})}):null}let e7={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function te(e){return(0,r.jsx)("div",{role:"presentation",...e,className:(0,o.Z)("navbar-sidebar__backdrop",e.className)})}function tt(e){let{children:t}=e,{navbar:{hideOnScroll:n,style:i}}=(0,x.L)(),l=z(),{navbarRef:s,isNavbarVisible:f}=function(e){let[t,n]=(0,a.useState)(e),r=(0,a.useRef)(!1),o=(0,a.useRef)(0),i=(0,a.useCallback)(e=>{null!==e&&(o.current=e.getBoundingClientRect().height)},[]);return!function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],{scrollEventsEnabledRef:n}=function(){let e=(0,a.useContext)(B);if(null==e)throw new c.i6("ScrollControllerProvider");return e}(),r=(0,a.useRef)(U()),o=(0,c.zX)(e);(0,a.useEffect)(()=>{let e=()=>{if(!n.current)return;let e=U();o(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)},[o,n,...t])}((t,a)=>{let{scrollY:i}=t;if(!e)return;if(i<o.current){n(!0);return}if(r.current){r.current=!1;return}let l=a?.scrollY,s=document.documentElement.scrollHeight-o.current,u=window.innerHeight;l&&i>=l?n(!1):i+u<s&&n(!0)}),d(t=>{if(!e)return;let a=t.location.hash;if(a?document.getElementById(a.substring(1)):void 0){r.current=!0,n(!1);return}n(!0)}),{navbarRef:i,isNavbarVisible:t}}(n);return(0,r.jsxs)("nav",{ref:s,"aria-label":(0,u.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.Z)("navbar","navbar--fixed-top",n&&[e7.navbarHideable,!f&&e7.navbarHidden],{"navbar--dark":"dark"===i,"navbar--primary":"primary"===i,"navbar-sidebar--show":l.shown}),children:[t,(0,r.jsx)(te,{onClick:l.toggle}),(0,r.jsx)(e5,{})]})}var tn=n("8365");let tr="errorBoundaryError_a6uf";function ta(e){return(0,r.jsx)("button",{type:"button",...e,children:(0,r.jsx)(u.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function to(e){let{error:t}=e,n=(0,tn.getErrorCausalChain)(t).map(e=>e.message).join("\n\nCause:\n");return(0,r.jsx)("p",{className:tr,children:n})}class ti extends a.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}function tl(e){let{width:t=30,height:n=30,className:a,...o}=e;return(0,r.jsx)("svg",{className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,r.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function ts(){let{toggle:e,shown:t}=z();return(0,r.jsx)("button",{onClick:e,"aria-label":(0,u.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,r.jsx)(tl,{})})}let tu="colorModeToggle_DEke";function tc(e){let{items:t}=e;return(0,r.jsx)(r.Fragment,{children:t.map((e,t)=>(0,r.jsx)(ti,{onError:t=>Error(`A theme navbar item failed to render. +Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config: +${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,r.jsx)(e4,{...e})},t))})}function td(e){let{left:t,right:n}=e;return(0,r.jsxs)("div",{className:"navbar__inner",children:[(0,r.jsx)("div",{className:"navbar__items",children:t}),(0,r.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function tf(){let e=z(),t=(0,x.L)().navbar.items,[n,a]=function(e){function t(e){return(e.position??"right")==="left"}let n=e.filter(t);return[n,e.filter(e=>!t(e))]}(t),o=t.find(e=>"search"===e.type);return(0,r.jsx)(td,{left:(0,r.jsxs)(r.Fragment,{children:[!e.disabled&&(0,r.jsx)(ts,{}),(0,r.jsx)(es,{}),(0,r.jsx)(tc,{items:n})]}),right:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(tc,{items:a}),(0,r.jsx)(J,{className:tu}),!o&&(0,r.jsx)(eF,{children:(0,r.jsx)(eI,{})})]})})}function tp(){return(0,r.jsx)(tt,{children:(0,r.jsx)(tf,{})})}function th(e){let{item:t}=e,{to:n,href:a,label:o,prependBaseUrlToHref:i,...l}=t,s=(0,et.ZP)(n),u=(0,et.ZP)(a,{forcePrependBaseUrl:!0});return(0,r.jsxs)(ee.Z,{className:"footer__link-item",...a?{href:i?u:a}:{to:s},...l,children:[o,a&&!(0,ed.Z)(a)&&(0,r.jsx)(eh,{})]})}function tg(e){let{item:t}=e;return t.html?(0,r.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,r.jsx)("li",{className:"footer__item",children:(0,r.jsx)(th,{item:t})},t.href??t.to)}function tm(e){let{column:t}=e;return(0,r.jsxs)("div",{className:"col footer__col",children:[(0,r.jsx)("div",{className:"footer__title",children:t.title}),(0,r.jsx)("ul",{className:"footer__items clean-list",children:t.items.map((e,t)=>(0,r.jsx)(tg,{item:e},t))})]})}function ty(e){let{columns:t}=e;return(0,r.jsx)("div",{className:"row footer__links",children:t.map((e,t)=>(0,r.jsx)(tm,{column:e},t))})}function tb(){return(0,r.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function tv(e){let{item:t}=e;return t.html?(0,r.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,r.jsx)(th,{item:t})}function tx(e){let{links:t}=e;return(0,r.jsx)("div",{className:"footer__links text--center",children:(0,r.jsx)("div",{className:"footer__links",children:t.map((e,n)=>(0,r.jsxs)(a.Fragment,{children:[(0,r.jsx)(tv,{item:e}),t.length!==n+1&&(0,r.jsx)(tb,{})]},n))})})}function tw(e){let{links:t}=e;return"title"in t[0]?(0,r.jsx)(ty,{columns:t}):(0,r.jsx)(tx,{links:t})}let tk={footerLogoLink:"footerLogoLink_BH7S"};function tS(e){let{logo:t}=e,{withBaseUrl:n}=(0,et.Cg)(),a={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,r.jsx)(eo,{className:(0,o.Z)("footer__logo",t.className),alt:t.alt,sources:a,width:t.width,height:t.height,style:t.style})}function tE(e){let{logo:t}=e;return t.href?(0,r.jsx)(ee.Z,{href:t.href,className:tk.footerLogoLink,target:t.target,children:(0,r.jsx)(tS,{logo:t})}):(0,r.jsx)(tS,{logo:t})}function t_(e){let{copyright:t}=e;return(0,r.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function tC(e){let{style:t,links:n,logo:a,copyright:i}=e;return(0,r.jsx)("footer",{className:(0,o.Z)("footer",{"footer--dark":"dark"===t}),children:(0,r.jsxs)("div",{className:"container container-fluid",children:[n,(a||i)&&(0,r.jsxs)("div",{className:"footer__bottom text--center",children:[a&&(0,r.jsx)("div",{className:"margin-bottom--sm",children:a}),i]})]})})}let tT=a.memo(function(){let{footer:e}=(0,x.L)();if(!e)return null;let{copyright:t,links:n,logo:a,style:o}=e;return(0,r.jsx)(tC,{style:o,links:n&&n.length>0&&(0,r.jsx)(tw,{links:n}),logo:a&&(0,r.jsx)(tE,{logo:a}),copyright:t&&(0,r.jsx)(t_,{copyright:t})})}),tN=(0,c.Qc)([G.S,function(e){let{children:t}=e,n=function(){let{announcementBar:e}=(0,x.L)(),t=(0,w.Z)(),[n,r]=(0,a.useState)(()=>!!t&&_());(0,a.useEffect)(()=>{r(_())},[]);let o=(0,a.useCallback)(()=>{C(!0),r(!0)},[]);return(0,a.useEffect)(()=>{if(!e)return;let{id:t}=e,n=E.get();"annoucement-bar"===n&&(n="announcement-bar");let a=t!==n;E.set(t),a&&C(!1),(a||!_())&&r(!1)},[e]),(0,a.useMemo)(()=>({isActive:!!e&&!n,close:o}),[e,n,o])}();return(0,r.jsx)(T.Provider,{value:n,children:t})},function(e){let{children:t}=e,n=function(){let e=(0,a.useRef)(!0);return(0,a.useMemo)(()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}}),[])}();return(0,r.jsx)(B.Provider,{value:n,children:t})},function(e){let{children:t}=e;return(0,r.jsx)(eK,{children:t})},l.VC,function(e){let{children:t}=e;return(0,r.jsx)(I.n2,{children:(0,r.jsx)(D,{children:(0,r.jsx)(Z,{children:t})})})}]);function tA(e){let{children:t}=e;return(0,r.jsx)(tN,{children:t})}var tO=n("4403");function tP(e){let{error:t,tryAgain:n}=e;return(0,r.jsx)("main",{className:"container margin-vert--xl",children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(tO.Z,{as:"h1",className:"hero__title",children:(0,r.jsx)(u.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,r.jsx)("div",{className:"margin-vert--lg",children:(0,r.jsx)(ta,{onClick:n,className:"button button--primary shadow--lw"})}),(0,r.jsx)("hr",{}),(0,r.jsx)("div",{className:"margin-vert--md",children:(0,r.jsx)(to,{error:t})})]})})})}let tj="mainWrapper_z2l0";function tL(e){let{children:t,noFooter:n,wrapperClassName:a,title:s,description:u}=e;return(0,y.t)(),(0,r.jsxs)(tA,{children:[(0,r.jsx)(l.d,{title:s,description:u}),(0,r.jsx)(v,{}),(0,r.jsx)(R,{}),(0,r.jsx)(tp,{}),(0,r.jsx)("div",{id:f,className:(0,o.Z)(m.k.wrapper.main,tj,a),children:(0,r.jsx)(i.Z,{fallback:e=>(0,r.jsx)(tP,{...e}),children:t})}),!n&&(0,r.jsx)(tT,{})]})}},4315:function(e,t,n){"use strict";n.d(t,{Z:function(){return o}});var r=n(5893);n(7294);var a=n(4819);function o(e){let{locale:t,version:n,tag:o}=e;return(0,r.jsxs)(a.Z,{children:[t&&(0,r.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,r.jsx)("meta",{name:"docusaurus_version",content:n}),o&&(0,r.jsx)("meta",{name:"docusaurus_tag",content:o}),t&&(0,r.jsx)("meta",{name:"docsearch:language",content:t}),n&&(0,r.jsx)("meta",{name:"docsearch:version",content:n}),o&&(0,r.jsx)("meta",{name:"docsearch:docusaurus_tag",content:o})]})}},1276:function(e,t,n){"use strict";n.d(t,{z:()=>p,u:()=>l});var r=n("5893"),a=n("7294"),o=n("7565"),i=n("2000");function l(e){let{initialState:t}=e,[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)(()=>{r(e=>!e)},[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}let s={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function c(e,t){let n=t?s:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function d(e){let{as:t="div",collapsed:n,children:i,animation:l,onCollapseTransitionEnd:d,className:f,disableSSRStyle:p}=e,h=(0,a.useRef)(null);return!function(e){let{collapsibleRef:t,collapsed:n,animation:r}=e,o=(0,a.useRef)(!1);(0,a.useEffect)(()=>{let e=t.current;function a(){let t=function(){let t=e.scrollHeight,n=r?.duration??function(e){if(window.matchMedia("(prefers-reduced-motion: reduce)").matches)return 1;let t=e/36;return Math.round((4+15*t**.25+t/5)*10)}(t),a=r?.easing??"ease-in-out";return{transition:`height ${n}ms ${a}`,height:`${t}px`}}();e.style.transition=t.transition,e.style.height=t.height}if(!o.current){c(e,n),o.current=!0;return}return e.style.willChange="height",function(){let t=requestAnimationFrame(()=>{n?(a(),requestAnimationFrame(()=>{e.style.height=s.height,e.style.overflow=s.overflow})):(e.style.display="block",requestAnimationFrame(()=>{a()}))});return()=>cancelAnimationFrame(t)}()},[t,n,r])}({collapsibleRef:h,collapsed:n,animation:l}),(0,r.jsx)(t,{ref:h,style:p?void 0:function(e){if(!o.Z.canUseDOM)return e?s:u}(n),onTransitionEnd:e=>{if("height"===e.propertyName)c(h.current,n),d?.(n)},className:f,children:i})}function f(e){let{collapsed:t,...n}=e,[o,l]=(0,a.useState)(!t),[s,u]=(0,a.useState)(t);return(0,i.Z)(()=>{!t&&l(!0)},[t]),(0,i.Z)(()=>{o&&u(t)},[o,t]),o?(0,r.jsx)(d,{...n,collapsed:s}):null}function p(e){let{lazy:t,...n}=e;return(0,r.jsx)(t?f:d,{...n})}},4239:function(e,t,n){"use strict";n.d(t,{I:function(){return y},S:function(){return m}});var r=n(5893),a=n(7294),o=n(7565),i=n(5346),l=n(6009),s=n(140);let u=a.createContext(void 0),c="theme",d=(0,l.WA)(c),f={light:"light",dark:"dark"},p=e=>e===f.dark?f.dark:f.light,h=e=>o.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e),g=e=>{d.set(p(e))};function m(e){let{children:t}=e,n=function(){let{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[r,o]=(0,a.useState)(h(e));(0,a.useEffect)(()=>{t&&d.del()},[t]);let i=(0,a.useCallback)(function(t){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},{persist:a=!0}=r;t?(o(t),a&&g(t)):(n?o(window.matchMedia("(prefers-color-scheme: dark)").matches?f.dark:f.light):o(e),d.del())},[n,e]);(0,a.useEffect)(()=>{document.documentElement.setAttribute("data-theme",p(r))},[r]),(0,a.useEffect)(()=>{if(t)return;let e=e=>{if(e.key!==c)return;let t=d.get();null!==t&&i(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[t,i]);let l=(0,a.useRef)(!1);return(0,a.useEffect)(()=>{if(t&&!n)return;let e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{if(window.matchMedia("print").matches||l.current){l.current=window.matchMedia("print").matches;return}i(null)};return e.addListener(r),()=>e.removeListener(r)},[i,t,n]),(0,a.useMemo)(()=>({colorMode:r,setColorMode:i,get isDarkTheme(){return r===f.dark},setLightTheme(){i(f.light)},setDarkTheme(){i(f.dark)}}),[r,i])}();return(0,r.jsx)(u.Provider,{value:n,children:t})}function y(){let e=(0,a.useContext)(u);if(null==e)throw new i.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},1179:function(e,t,n){"use strict";n.d(t,{HY:function(){return s},Zo:function(){return u},n2:function(){return l}});var r=n(5893),a=n(7294),o=n(5346);let i=a.createContext(null);function l(e){let{children:t}=e,n=(0,a.useState)({component:null,props:null});return(0,r.jsx)(i.Provider,{value:n,children:t})}function s(){let e=(0,a.useContext)(i);if(!e)throw new o.i6("NavbarSecondaryMenuContentProvider");return e[0]}function u(e){let{component:t,props:n}=e,r=(0,a.useContext)(i);if(!r)throw new o.i6("NavbarSecondaryMenuContentProvider");let[,l]=r,s=(0,o.Ql)(n);return(0,a.useEffect)(()=>{l({component:t,props:s})},[l,t,s]),(0,a.useEffect)(()=>()=>l({component:null,props:null}),[l]),null}},6959:function(e,t,n){"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n("7294");let a="navigation-with-keyboard";function o(){(0,r.useEffect)(()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}},[])}},4704:function(e,t,n){"use strict";n.d(t,{i:function(){return i}});var r=n(7294),a=n(7565);let o={desktop:"desktop",mobile:"mobile"};function i(){let{desktopBreakpoint:e=996}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},[t,n]=(0,r.useState)(()=>"ssr");return(0,r.useEffect)(()=>{function t(){n(function(e){if(!a.Z.canUseDOM)throw Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?o.desktop:o.mobile}(e))}return t(),window.addEventListener("resize",t),()=>{window.removeEventListener("resize",t)}},[e]),t}},4681:function(e,t,n){"use strict";n.d(t,{k:function(){return r}});let r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",blogAuthorsListPage:"blog-authors-list-page",blogAuthorsPostsPage:"blog-authors-posts-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",draftBanner:"theme-draft-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},2743:function(e,t,n){"use strict";n.d(t,{FG:()=>f,d:()=>c,VC:()=>p});var r=n("5893"),a=n("7294"),o=n("7026"),i=n("4819"),l=n("8312"),s=n("4757"),u=n("2933");function c(e){let{title:t,description:n,keywords:a,image:o,children:l}=e,c=function(e){let{siteConfig:t}=(0,u.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,s.Cg)(),f=o?d(o,{absolute:!0}):void 0;return(0,r.jsxs)(i.Z,{children:[t&&(0,r.jsx)("title",{children:c}),t&&(0,r.jsx)("meta",{property:"og:title",content:c}),n&&(0,r.jsx)("meta",{name:"description",content:n}),n&&(0,r.jsx)("meta",{property:"og:description",content:n}),a&&(0,r.jsx)("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),f&&(0,r.jsx)("meta",{property:"og:image",content:f}),f&&(0,r.jsx)("meta",{name:"twitter:image",content:f}),l]})}let d=a.createContext(void 0);function f(e){let{className:t,children:n}=e,l=a.useContext(d),s=(0,o.Z)(l,t);return(0,r.jsxs)(d.Provider,{value:s,children:[(0,r.jsx)(i.Z,{children:(0,r.jsx)("html",{className:s})}),n]})}function p(e){var t;let{children:n}=e,a=(0,l.Z)();let i=(t=a.plugin.name,`plugin-${t.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`),s=`plugin-id-${a.plugin.id}`;return(0,r.jsx)(f,{className:(0,o.Z)(i,s),children:n})}},5346:function(e,t,n){"use strict";n.d(t,{D9:function(){return l},Qc:function(){return c},Ql:function(){return u},i6:function(){return s},zX:function(){return i}});var r=n(5893),a=n(7294),o=n(2e3);function i(e){let t=(0,a.useRef)(e);return(0,o.Z)(()=>{t.current=e},[e]),(0,a.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.current(...n)},[])}function l(e){let t=(0,a.useRef)();return(0,o.Z)(()=>{t.current=e}),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function u(e){let t=Object.entries(e);return t.sort((e,t)=>e[0].localeCompare(t[0])),(0,a.useMemo)(()=>e,t.flat())}function c(e){return t=>{let{children:n}=t;return(0,r.jsx)(r.Fragment,{children:e.reduceRight((e,t)=>(0,r.jsx)(t,{children:e}),n)})}}},9246:function(e,t,n){"use strict";function r(e,t){let n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}n.d(t,{Mg:function(){return r}}),n(7294),n(4143),n(2933)},6009:function(e,t,n){"use strict";n.d(t,{WA:()=>s}),n("7294");var r=JSON.parse('{"d":"localStorage","u":""}');let a=r.d;function o(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;let o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}let i=!1,l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function s(e,t){var n;let s=(n=e,`${n}${r.u}`);if("undefined"==typeof window)return function(e){function t(){throw Error(`Illegal storage API usage for storage key "${e}". +Docusaurus storage APIs are not supposed to be called on the server-rendering process. +Please only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(s);let u=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:a;if("undefined"==typeof window)throw Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(e){return function(e){!i&&(console.warn(`Docusaurus browser storage is not available. +Possible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.`,e),i=!0)}(e),null}}(t?.persistence);return null===u?l:{get:()=>{try{return u.getItem(s)}catch(e){return console.error(`Docusaurus storage error, can't get key=${s}`,e),null}},set:e=>{try{let t=u.getItem(s);u.setItem(s,e),o({key:s,oldValue:t,newValue:e,storage:u})}catch(t){console.error(`Docusaurus storage error, can't set ${s}=${e}`,t)}},del:()=>{try{let e=u.getItem(s);u.removeItem(s),o({key:s,oldValue:e,newValue:null,storage:u})}catch(e){console.error(`Docusaurus storage error, can't delete key=${s}`,e)}},listen:e=>{try{let t=t=>{t.storageArea===u&&t.key===s&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(e){return console.error(`Docusaurus storage error, can't listen for changes of key=${s}`,e),()=>{}}}}}},8910:function(e,t,n){"use strict";n.d(t,{l:function(){return i}});var r=n(2933),a=n(6550),o=n(8365);function i(){let{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:l}}=(0,r.Z)(),{pathname:s}=(0,a.TH)(),u=(0,o.applyTrailingSlash)(s,{trailingSlash:n,baseUrl:e}),c=l===i?e:e.replace(`/${l}/`,"/"),d=u.replace(e,"");return{createUrl:function(e){var n;let{locale:r,fullyQualified:a}=e;return`${a?t:""}${(n=r)===i?`${c}`:`${c}${n}/`}${d}`}}}},140:function(e,t,n){"use strict";n.d(t,{L:function(){return a}});var r=n(2933);function a(){return(0,r.Z)().siteConfig.themeConfig}},4994:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addTrailingSlash=a,t.default=function(e,t){var n;let{trailingSlash:r,baseUrl:i}=t;if(e.startsWith("#"))return e;if(void 0===r)return e;let[l]=e.split(/[#?]/);let s="/"===l||l===i?l:(n=l,r?a(n):o(n));return e.replace(l,s)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=o;let r=n(8411);function a(e){return e.endsWith("/")?e:`${e}/`}function o(e){return(0,r.removeSuffix)(e,"/")}},4202:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8365:function(e,t,n){"use strict";t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0;let r=n(8395);t.blogPostContainerID="__blog-post-container";var a,o=n(4994);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r.__importDefault(o).default}}),n(8411);var i=n(4202);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return i.getErrorCausalChain}})},8411:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){return""===t?e:e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},5150:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return r}});let r={title:"The Old Speice Guy",tagline:"",favicon:"img/favicon.ico",url:"https://speice.io",baseUrl:"/",organizationName:"bspeice",projectName:"speice.io",onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{docs:!1,blog:{routeBasePath:"/",blogSidebarTitle:"All posts",blogSidebarCount:"ALL",showReadingTime:!0,showLastUpdateTime:!0,feedOptions:{type:["rss","atom"],xslt:!0},onInlineTags:"warn",onInlineAuthors:"warn",onUntruncatedBlogPosts:"warn",remarkPlugins:[null],rehypePlugins:[null]},theme:{customCss:["./src/css/custom.css"]}}]],themeConfig:{navbar:{title:"The Old Speice Guy",logo:{alt:"Sierpinski Gasket",src:"img/logo.svg",srcDark:"img/logo-dark.svg"},items:[{href:"https://github.com/bspeice",position:"right",className:"header-github-link"}],hideOnScroll:!1},footer:{links:[],copyright:"Copyright \xa9 2024 Bradlee Speice",style:"light"},prism:{theme:{plain:{backgroundColor:"hsl(230, 1%, 98%)",color:"hsl(230, 8%, 24%)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(230, 4%, 64%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(230, 8%, 24%)"}},{types:["attr-name","class-name","boolean","constant","number","atrule"],style:{color:"hsl(35, 99%, 36%)"}},{types:["keyword"],style:{color:"hsl(301, 63%, 40%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(5, 74%, 59%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value","punctuation"],style:{color:"hsl(119, 34%, 47%)"}},{types:["variable","operator","function"],style:{color:"hsl(221, 87%, 60%)"}},{types:["url"],style:{color:"hsl(198, 99%, 37%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(230, 8%, 24%)"}}]},darkTheme:{plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},additionalLanguages:["bash","java","julia","nasm"],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!1},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},blog:{sidebar:{groupByYear:!0}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},plugins:["/home/bspeice/Development/speice.io/node_modules/docusaurus-lunr-search/src/index.js"],stylesheets:[{href:"https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css",type:"text/css",integrity:"sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM",crossorigin:"anonymous"}],future:{experimental_faster:{swcJsLoader:!0,swcJsMinimizer:!0,swcHtmlMinimizer:!0,lightningCssMinimizer:!0,mdxCrossCompilerCache:!0,rspackBundler:!0},experimental_storage:{type:"localStorage",namespace:!1},experimental_router:"browser"},baseUrlIssueBanner:!0,onBrokenAnchors:"warn",onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},themes:[],scripts:[],headTags:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{format:"mdx",mermaid:!1,mdx1Compat:{comments:!0,admonitions:!0,headingIds:!0},anchors:{maintainCase:!1}}}},6019:function(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(null,arguments)}n.d(t,{Z:function(){return r}})},5091:function(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>a})},443:function(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n={};for(var r in e)if(({}).hasOwnProperty.call(e,r)){if(t.includes(r))continue;n[r]=e[r]}return n}n.d(t,{Z:function(){return r}})},7026:function(e,t,n){"use strict";n.d(t,{Z:function(){return r}});let r=function(){for(var e,t,n=0,r="",a=arguments.length;n<a;n++)(e=arguments[n])&&(t=function e(t){var n,r,a="";if("string"==typeof t||"number"==typeof t)a+=t;else if("object"==typeof t){if(Array.isArray(t)){var o=t.length;for(n=0;n<o;n++)t[n]&&(r=e(t[n]))&&(a&&(a+=" "),a+=r)}else for(r in t)t[r]&&(a&&(a+=" "),a+=r)}return a}(e))&&(r&&(r+=" "),r+=t);return r}},3229:function(e,t,n){"use strict";let r,a,o,i,l;n.d(t,{p1:function(){return Q},y$:function(){return eD}});var s,u,c,d,f,p,h,g,m,y,b,v,x,w,k,S,E,_,C,T,N,A,O,P,j,L,R=n(7294),I=n(7026),M=Object.create,F=Object.defineProperty,D=Object.defineProperties,z=Object.getOwnPropertyDescriptor,$=Object.getOwnPropertyDescriptors,B=Object.getOwnPropertyNames,U=Object.getOwnPropertySymbols,H=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty,W=Object.prototype.propertyIsEnumerable,V=(e,t,n)=>t in e?F(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,G=(e,t)=>{for(var n in t||(t={}))Z.call(t,n)&&V(e,n,t[n]);if(U)for(var n of U(t))W.call(t,n)&&V(e,n,t[n]);return e},q=(e,t)=>D(e,$(t)),Y=(e,t)=>{var n={};for(var r in e)Z.call(e,r)&&0>t.indexOf(r)&&(n[r]=e[r]);if(null!=e&&U)for(var r of U(e))0>t.indexOf(r)&&W.call(e,r)&&(n[r]=e[r]);return n},K=(e,t,n,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let a of B(t))!Z.call(e,a)&&a!==n&&F(e,a,{get:()=>t[a],enumerable:!(r=z(t,a))||r.enumerable});return e};var Q=(l=null!=(o=(r={"../../node_modules/.pnpm/prismjs@1.29.0_patch_hash=vrxx3pzkik6jpmgpayxfjunetu/node_modules/prismjs/prism.js"(e,t){var n=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var a,o;switch(n=n||{},r.util.type(t)){case"Object":if(n[o=r.util.objId(t)])return n[o];for(var i in a={},n[o]=a,t)t.hasOwnProperty(i)&&(a[i]=e(t[i],n));return a;case"Array":if(n[o=r.util.objId(t)])return n[o];return a=[],n[o]=a,t.forEach(function(t,r){a[r]=e(t,n)}),a;default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var a=e.classList;if(a.contains(t))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var a in t)n[a]=t[a];return n},insertBefore:function(e,t,n,a){var o=(a=a||r.languages)[e],i={};for(var l in o)if(o.hasOwnProperty(l)){if(l==t)for(var s in n)n.hasOwnProperty(s)&&(i[s]=n[s]);n.hasOwnProperty(l)||(i[l]=o[l])}var u=a[e];return a[e]=i,r.languages.DFS(r.languages,function(t,n){n===u&&t!=e&&(this[t]=i)}),i},DFS:function e(t,n,a,o){o=o||{};var i=r.util.objId;for(var l in t)if(t.hasOwnProperty(l)){n.call(t,l,t[l],a||l);var s=t[l],u=r.util.type(s);"Object"!==u||o[i(s)]?"Array"!==u||o[i(s)]||(o[i(s)]=!0,e(s,n,l,o)):(o[i(s)]=!0,e(s,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};if(r.hooks.run("before-tokenize",o),!o.grammar)throw Error('The language "'+o.language+'" has no grammar.');return o.tokens=r.tokenize(o.code,o.grammar),r.hooks.run("after-tokenize",o),a.stringify(r.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var s in n)t[s]=n[s];delete t.rest}var u=new i;return l(u,u.head,e),function e(t,n,i,s,u,c){for(var d in i){if(!!i.hasOwnProperty(d)&&!!i[d]){var f=i[d];f=Array.isArray(f)?f:[f];for(var p=0;p<f.length;++p){if(c&&c.cause==d+","+p)return;var h=f[p],g=h.inside,m=!!h.lookbehind,y=!!h.greedy,b=h.alias;if(y&&!h.pattern.global){var v=h.pattern.toString().match(/[imsuy]*$/)[0];h.pattern=RegExp(h.pattern.source,v+"g")}for(var x=h.pattern||h,w=s.next,k=u;w!==n.tail&&(!c||!(k>=c.reach));k+=w.value.length,w=w.next){;var S,E=w.value;if(n.length>t.length)return;if(!(E instanceof a)){var _=1;if(y){if(!(S=o(x,k,t,m))||S.index>=t.length)break;var C=S.index,T=S.index+S[0].length,N=k;for(N+=w.value.length;C>=N;)N+=(w=w.next).value.length;if(N-=w.value.length,k=N,w.value instanceof a)continue;for(var A=w;A!==n.tail&&(N<T||"string"==typeof A.value);A=A.next)_++,N+=A.value.length;_--,E=t.slice(k,N),S.index-=k}else if(!(S=o(x,0,E,m)))continue;var C=S.index,O=S[0],P=E.slice(0,C),j=E.slice(C+O.length),L=k+E.length;c&&L>c.reach&&(c.reach=L);var R=w.prev;if(P&&(R=l(n,R,P),k+=P.length),function(e,t,n){for(var r=t.next,a=0;a<n&&r!==e.tail;a++)r=r.next;t.next=r,r.prev=t,e.length-=a}(n,R,_),w=l(n,R,new a(d,g?r.tokenize(O,g):O,b,O)),j&&l(n,w,j),_>1){var I={cause:d+","+p,reach:L};e(t,n,i,w.prev,k,I),c&&I.reach>c.reach&&(c.reach=I.reach)}}}}}}}(e,u,t,u.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(u)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(!!n&&!!n.length)for(var a,o=0;a=n[o++];)a(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var a=e.exec(n);if(a&&r&&a[1]){var o=a[1].length;a.index+=o,a[0]=a[0].slice(o)}return a}function i(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}return a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var a="";return t.forEach(function(t){a+=e(t,n)}),a}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(o.classes,i):o.classes.push(i)),r.hooks.run("wrap",o);var l="";for(var s in o.attributes)l+=" "+s+'="'+(o.attributes[s]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+l+">"+o.content+"</"+o.tag+">"},r}();t.exports=n,n.default=n}},function(){return a||(0,r[B(r)[0]])((a={exports:{}}).exports,a),a.exports})())?M(H(o)):{},K(!i&&o&&o.__esModule?l:F(l,"default",{value:o,enumerable:!0}),o));Q.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Q.languages.markup.tag.inside["attr-value"].inside.entity=Q.languages.markup.entity,Q.languages.markup.doctype.inside["internal-subset"].inside=Q.languages.markup,Q.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(Q.languages.markup.tag,"addInlined",{value:function(e,t){var n={},n=(n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Q.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i,{"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}}),t=(n["language-"+t]={pattern:/[\s\S]+/,inside:Q.languages[t]},{});t[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:n},Q.languages.insertBefore("markup","cdata",t)}}),Object.defineProperty(Q.languages.markup.tag,"addAttribute",{value:function(e,t){Q.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:Q.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Q.languages.html=Q.languages.markup,Q.languages.mathml=Q.languages.markup,Q.languages.svg=Q.languages.markup,Q.languages.xml=Q.languages.extend("markup",{}),Q.languages.ssml=Q.languages.xml,Q.languages.atom=Q.languages.xml,Q.languages.rss=Q.languages.xml,s=Q,u={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},d=RegExp((d="(?:[^\\\\-]|"+(c=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/).source+")")+"-"+d),f={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"},s.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:d,inside:{escape:c,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":u,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:c}},"special-escape":u,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":f}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:c,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|<?[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":f}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}},Q.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},Q.languages.javascript=Q.languages.extend("clike",{"class-name":[Q.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Q.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Q.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Q.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Q.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Q.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Q.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Q.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Q.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Q.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Q.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Q.languages.markup&&(Q.languages.markup.tag.addInlined("script","javascript"),Q.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),Q.languages.js=Q.languages.javascript,Q.languages.actionscript=Q.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<<?|>>?>?|[!=]=?)=?|[~?@]/}),Q.languages.actionscript["class-name"].alias="function",delete Q.languages.actionscript.parameter,delete Q.languages.actionscript["literal-property"],Q.languages.markup&&Q.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:Q.languages.markup}}),h=/#(?!\{).+/,g={pattern:/#\{[^}]+\}/,alias:"variable"},(p=Q).languages.coffeescript=p.languages.extend("javascript",{comment:h,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:g}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),p.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:h,interpolation:g}}}),p.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:p.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:g}}]}),p.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete p.languages.coffeescript["template-string"],p.languages.coffee=p.languages.coffeescript,Object.defineProperty(y=(m=Q).languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/},"addSupport",{value:function(e,t){(e="string"==typeof e?[e]:e).forEach(function(e){var n=function(e){e.inside||(e.inside={}),e.inside.rest=t},r="doc-comment";if(a=m.languages[e]){var a,o=a[r];if((o=o||(a=m.languages.insertBefore(e,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[r])instanceof RegExp&&(o=a[r]={pattern:o}),Array.isArray(o))for(var i=0,l=o.length;i<l;i++)o[i]instanceof RegExp&&(o[i]={pattern:o[i]}),n(o[i]);else n(o)}})}}),y.addSupport(["java","javascript","php"],y),v=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/,(v=((b=Q).languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+v.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+v.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+v.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+v.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:v,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},b.languages.css.atrule.inside.rest=b.languages.css,b.languages.markup))&&(v.tag.addInlined("style","css"),v.tag.addAttribute("style","css")),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,t=(e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+t.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[t,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}}),{pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0}),n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,number:n})}(Q),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ ]+"+t.source+")?|"+t.source+"(?:[ ]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source}),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){return t=(t||"").replace(/m/g,"")+"m",RegExp(/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,function(){return r}).replace(/<<value>>/g,function(){return e}),t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,function(){return r})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,function(){return r}).replace(/<<key>>/g,function(){return"(?:"+a+"|"+o+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Q),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,function(){return t}),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,function(){return r}),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source,i=(e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(t){["url","bold","italic","strike","code-snippet"].forEach(function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])})}),e.hooks.add("after-tokenize",function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var a,o=t[n];"code"!==o.type?e(o.content):(a=o.content[1],o=o.content[3],a&&o&&"code-language"===a.type&&"code-block"===o.type&&"string"==typeof a.content&&(a=a.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),a="language-"+(a=(/[a-z][\w-]*/i.exec(a)||[""])[0].toLowerCase()),o.alias?"string"==typeof o.alias?o.alias=[o.alias,a]:o.alias.push(a):o.alias=[a]))}}(e.tokens)}),e.hooks.add("wrap",function(t){if("code-block"===t.type){for(var n,r="",a=0,o=t.classes.length;a<o;a++){var u=t.classes[a],u=/language-(.+)/.exec(u);if(u){r=u[1];break}}var c,d=e.languages[r];d?t.content=e.highlight(n=(n=(n=t.content).replace(i,"")).replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,function(e,t){return"#"===(t=t.toLowerCase())[0]?s("x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1))):l[t]||e}),d,r):r&&"none"!==r&&e.plugins.autoloader&&(c="md-"+new Date().valueOf()+"-"+Math.floor(1e16*Math.random()),t.attributes.id=c,e.plugins.autoloader.loadLanguages(r,function(){var t=document.getElementById(c);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[r],r))}))}}),RegExp(e.languages.markup.tag.pattern.source,"gi")),l={amp:"&",lt:"<",gt:">",quot:'"'},s=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(Q),Q.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:Q.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},Q.hooks.add("after-tokenize",function(e){if("graphql"===e.language)for(var t=e.tokens.filter(function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type}),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var a=[];if(d(["definition-mutation","punctuation"])&&"("===function(e){return t[n+e]}(1).content){n+=2;var o=f(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var i=function(e){return t[n+e]}(0);"variable"===i.type&&(p(i,"variable-input"),a.push(i.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===function(e){return t[n+e]}(0).content&&(n++,p(function(e){return t[n+e]}(0),"property-mutation"),0<a.length)){var l=f(/^\{$/,/^\}$/);if(-1!==l)for(var s=n;s<l;s++){var u=t[s];"variable"===u.type&&0<=a.indexOf(u.content)&&p(u,"variable-input")}}}}function c(e){return t[n+e]}function d(e,r){r=r||0;for(var a=0;a<e.length;a++){var o=t[n+(a+r)];if(!o||o.type!==e[a])return}return 1}function f(e,r){for(var a=1,o=n;o<t.length;o++){var i=t[o],l=i.content;if("punctuation"===i.type&&"string"==typeof l){if(e.test(l))a++;else if(r.test(l)&&0==--a)return o}}return -1}function p(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}}),Q.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function l(t,n,r){return t={code:t,grammar:n,language:r},e.hooks.run("before-tokenize",t),t.tokens=e.tokenize(t.code,t.grammar),e.hooks.run("after-tokenize",t),t.tokens}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var s={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};e.hooks.add("after-tokenize",function(t){t.language in s&&function t(n){for(var i=0,s=n.length;i<s;i++){var u,c,d,f=n[i];"string"!=typeof f&&(Array.isArray(u=f.content)?"template-string"===f.type?(f=u[1],3===u.length&&"string"!=typeof f&&"embedded-code"===f.type&&(c=function e(t){return"string"==typeof t?t:Array.isArray(t)?t.map(e).join(""):e(t.content)}(f),f=Array.isArray(f=f.alias)?f[0]:f,d=e.languages[f])&&(u[1]=function(t,n,i){var s=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),u=0,c={},s=l(s.map(function(e){if("string"==typeof e)return e;for(var n,r,e=e.content;-1!==t.indexOf((r=u++,n="___"+i.toUpperCase()+"_"+r+"___")););return c[n]=e,n}).join(""),n,i),d=Object.keys(c);return u=0,function t(n){for(var o=0;o<n.length;o++){if(u>=d.length)return;var i,s,f,p,h,g,m,y=n[o];"string"==typeof y||"string"==typeof y.content?(i=d[u],-1!==(m=(g="string"==typeof y?y:y.content).indexOf(i))&&(++u,s=g.substring(0,m),h=c[i],f=void 0,(p={})["interpolation-punctuation"]=a,3===(p=e.tokenize(h,p)).length&&((f=[1,1]).push.apply(f,l(p[1],e.languages.javascript,"javascript")),p.splice.apply(p,f)),f=new e.Token("interpolation",p,r.alias,h),p=g.substring(m+i.length),h=[],s&&h.push(s),h.push(f),p&&(t(g=[p]),h.push.apply(h,g)),"string"==typeof y?(n.splice.apply(n,[o,1].concat(h)),o+=h.length-1):y.content=h)):Array.isArray(m=y.content)?t(m):t([m])}}(s),new e.Token(i,s,"language-"+i,t)}(c,d,f))):t(u):"string"!=typeof u&&t([u]))}}(t.tokens)})}(Q),(x=Q).languages.typescript=x.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),x.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete x.languages.typescript.parameter,delete x.languages.typescript["literal-property"],w=x.languages.extend("typescript",{}),delete w["class-name"],x.languages.typescript["class-name"].inside=w,x.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:w}}}}),x.languages.ts=x.languages.typescript,S=(k=Q).languages.javascript,_="(@(?:arg|argument|param|property)\\s+(?:"+(E=/\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})+\}/.source)+"\\s+)?)",k.languages.jsdoc=k.languages.extend("javadoclike",{parameter:{pattern:RegExp(_+/(?:(?!\s)[$\w\xA0-\uFFFF.])+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),k.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(_+/\[(?:(?!\s)[$\w\xA0-\uFFFF.])+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:S,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp(/(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\s+(?:<TYPE>\s+)?)[A-Z]\w*(?:\.[A-Z]\w*)*/.source.replace(/<TYPE>/g,function(){return E})),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+E),lookbehind:!0,inside:{string:S.string,number:S.number,boolean:S.boolean,keyword:k.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:S,alias:"language-javascript"}}}}),k.languages.javadoclike.addSupport("javascript",k.languages.jsdoc),(C=Q).languages.flow=C.languages.extend("javascript",{}),C.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Bb]oolean|Function|[Nn]umber|[Ss]tring|[Ss]ymbol|any|mixed|null|void)\b/,alias:"class-name"}]}),C.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete C.languages.flow.parameter,C.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(C.languages.flow.keyword)||(C.languages.flow.keyword=[C.languages.flow.keyword]),C.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:Class|declare|opaque|type)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:Diff|Enum|Exact|Keys|ObjMap|PropertyType|Record|Shape|Subtype|Supertype|await)\b(?!\$)/,lookbehind:!0}),Q.languages.n4js=Q.languages.extend("javascript",{keyword:/\b(?:Array|any|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),Q.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),Q.languages.n4jsd=Q.languages.n4js,function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source}),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var a=n[r],o=e.languages.javascript[a],a=(o="RegExp"===e.util.type(o)?e.languages.javascript[a]={pattern:o}:o).inside||{};(o.inside=a)["maybe-class-name"]=/^[A-Z][\s\S]*/}}(Q),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return RegExp(e=e.replace(/<S>/g,function(){return n}).replace(/<BRACES>/g,function(){return r}).replace(/<SPREAD>/g,function(){return a}),t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""};e.hooks.add("after-tokenize",function(t){"jsx"!==t.language&&"tsx"!==t.language||function t(n){for(var r=[],a=0;a<n.length;a++){var o=n[a],l=!1;"string"!=typeof o&&("tag"===o.type&&o.content[0]&&"tag"===o.content[0].type?"</"===o.content[0].content[0].content?0<r.length&&r[r.length-1].tagName===i(o.content[0].content[1])&&r.pop():"/>"!==o.content[o.content.length-1].content&&r.push({tagName:i(o.content[0].content[1]),openedBraces:0}):0<r.length&&"punctuation"===o.type&&"{"===o.content?r[r.length-1].openedBraces++:0<r.length&&0<r[r.length-1].openedBraces&&"punctuation"===o.type&&"}"===o.content?r[r.length-1].openedBraces--:l=!0),(l||"string"==typeof o)&&0<r.length&&0===r[r.length-1].openedBraces&&(l=i(o),a<n.length-1&&("string"==typeof n[a+1]||"plain-text"===n[a+1].type)&&(l+=i(n[a+1]),n.splice(a+1,1)),0<a&&("string"==typeof n[a-1]||"plain-text"===n[a-1].type)&&(l=i(n[a-1])+l,n.splice(a-1,1),a--),n[a]=new e.Token("plain-text",l,null,l)),o.content&&"string"!=typeof o.content&&t(o.content)}}(t.tokens)})}(Q),N=(T=Q).util.clone(T.languages.typescript),(N=(T.languages.tsx=T.languages.extend("jsx",N),delete T.languages.tsx.parameter,delete T.languages.tsx["literal-property"],T.languages.tsx.tag)).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+N.pattern.source+")",N.pattern.flags),N.lookbehind=!0,Q.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+/(?:elseif|if)\b/.source+"(?:[ ]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Q.languages.swift["string-literal"].forEach(function(e){e.inside.interpolation.inside=Q.languages.swift}),(A=Q).languages.kotlin=A.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete A.languages.kotlin["class-name"],O={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:A.languages.kotlin}},A.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:O},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:O},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete A.languages.kotlin.string,A.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),A.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),A.languages.kt=A.languages.kotlin,A.languages.kts=A.languages.kotlin,Q.languages.c=Q.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Q.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Q.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Q.languages.c.string],char:Q.languages.c.char,comment:Q.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Q.languages.c}}}}),Q.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Q.languages.c.boolean,Q.languages.objectivec=Q.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete Q.languages.objectivec["class-name"],Q.languages.objc=Q.languages.objectivec,Q.languages.reason=Q.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),Q.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete Q.languages.reason.function,function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,function(){return t});t=t.replace(/<self>/g,function(){return/[^\s\S]/.source}),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Q),Q.languages.go=Q.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Q.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Q.languages.go["class-name"],P=Q,j=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,L=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,function(){return j.source}),P.languages.cpp=P.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,function(){return j.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:j,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),P.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,function(){return L})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),P.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:P.languages.cpp}}}}),P.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),P.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:P.languages.extend("cpp",{})}}),P.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},P.languages.cpp["base-clause"]),Q.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Q.languages.python["string-interpolation"].inside.interpolation.inside.rest=Q.languages.python,Q.languages.py=Q.languages.python,Q.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Q.languages.webmanifest=Q.languages.json;((e,t)=>{for(var n in t)F(e,n,{get:t[n],enumerable:!0})})({},{dracula:()=>X,duotoneDark:()=>J,duotoneLight:()=>ee,github:()=>et,gruvboxMaterialDark:()=>eC,gruvboxMaterialLight:()=>eT,jettwaveDark:()=>ek,jettwaveLight:()=>eS,nightOwl:()=>en,nightOwlLight:()=>er,oceanicNext:()=>eh,okaidia:()=>eg,oneDark:()=>eE,oneLight:()=>e_,palenight:()=>em,shadesOfPurple:()=>ey,synthwave84:()=>eb,ultramin:()=>ev,vsDark:()=>ex,vsLight:()=>ew});var X={plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},J={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},ee={plain:{backgroundColor:"#faf8f5",color:"#728fcb"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#b6ad9a"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#063289"}},{types:["property","function"],style:{color:"#b29762"}},{types:["tag-id","selector","atrule-id"],style:{color:"#2d2006"}},{types:["attr-name"],style:{color:"#896724"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule"],style:{color:"#728fcb"}},{types:["placeholder","variable"],style:{color:"#93abdc"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#896724"}}]},et={plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},en={plain:{color:"#d6deeb",backgroundColor:"#011627"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(99, 119, 119)",fontStyle:"italic"}},{types:["string","url"],style:{color:"rgb(173, 219, 103)"}},{types:["variable"],style:{color:"rgb(214, 222, 235)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation"],style:{color:"rgb(199, 146, 234)"}},{types:["selector","doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(255, 203, 139)"}},{types:["tag","operator","keyword"],style:{color:"rgb(127, 219, 202)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["property"],style:{color:"rgb(128, 203, 196)"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}}]},er={plain:{color:"#403f53",backgroundColor:"#FBFBFB"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(72, 118, 214)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(152, 159, 177)",fontStyle:"italic"}},{types:["string","builtin","char","constant","url"],style:{color:"rgb(72, 118, 214)"}},{types:["variable"],style:{color:"rgb(201, 103, 101)"}},{types:["number"],style:{color:"rgb(170, 9, 130)"}},{types:["punctuation"],style:{color:"rgb(153, 76, 195)"}},{types:["function","selector","doctype"],style:{color:"rgb(153, 76, 195)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(17, 17, 17)"}},{types:["tag"],style:{color:"rgb(153, 76, 195)"}},{types:["operator","property","keyword","namespace"],style:{color:"rgb(12, 150, 155)"}},{types:["boolean"],style:{color:"rgb(188, 84, 84)"}}]},ea="#D8DEE9",eo="#999999",ei="#c5a5c5",el="#5a9bcf",es="#8dc891",eu="#d7deea",ec="#ff8b50",ed="#fc929e",ef="#79b6f2",ep="#FAC863",eh={plain:{backgroundColor:"#282c34",color:"#ffffff"},styles:[{types:["attr-name"],style:{color:ei}},{types:["attr-value"],style:{color:es}},{types:["comment","block-comment","prolog","doctype","cdata","shebang"],style:{color:eo}},{types:["property","number","function-name","constant","symbol","deleted"],style:{color:el}},{types:["boolean"],style:{color:ec}},{types:["tag"],style:{color:ed}},{types:["string"],style:{color:es}},{types:["punctuation"],style:{color:es}},{types:["selector","char","builtin","inserted"],style:{color:ea}},{types:["function"],style:{color:ef}},{types:["operator","entity","url","variable"],style:{color:eu}},{types:["keyword"],style:{color:ei}},{types:["atrule","class-name"],style:{color:ep}},{types:["important"],style:{fontWeight:"400"}},{types:["bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}}]},eg={plain:{color:"#f8f8f2",backgroundColor:"#272822"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"#f92672",fontStyle:"italic"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"#8292a2",fontStyle:"italic"}},{types:["string","url"],style:{color:"#a6e22e"}},{types:["variable"],style:{color:"#f8f8f2"}},{types:["number"],style:{color:"#ae81ff"}},{types:["builtin","char","constant","function","class-name"],style:{color:"#e6db74"}},{types:["punctuation"],style:{color:"#f8f8f2"}},{types:["selector","doctype"],style:{color:"#a6e22e",fontStyle:"italic"}},{types:["tag","operator","keyword"],style:{color:"#66d9ef"}},{types:["boolean"],style:{color:"#ae81ff"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)",opacity:.7}},{types:["tag","property"],style:{color:"#f92672"}},{types:["attr-name"],style:{color:"#a6e22e !important"}},{types:["doctype"],style:{color:"#8292a2"}},{types:["rule"],style:{color:"#e6db74"}}]},em={plain:{color:"#bfc7d5",backgroundColor:"#292d3e"},styles:[{types:["comment"],style:{color:"rgb(105, 112, 152)",fontStyle:"italic"}},{types:["string","inserted"],style:{color:"rgb(195, 232, 141)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation","selector"],style:{color:"rgb(199, 146, 234)"}},{types:["variable"],style:{color:"rgb(191, 199, 213)"}},{types:["class-name","attr-name"],style:{color:"rgb(255, 203, 107)"}},{types:["tag","deleted"],style:{color:"rgb(255, 85, 114)"}},{types:["operator"],style:{color:"rgb(137, 221, 255)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["keyword"],style:{fontStyle:"italic"}},{types:["doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}},{types:["url"],style:{color:"rgb(221, 221, 221)"}}]},ey={plain:{color:"#9EFEFF",backgroundColor:"#2D2A55"},styles:[{types:["changed"],style:{color:"rgb(255, 238, 128)"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)"}},{types:["comment"],style:{color:"rgb(179, 98, 255)",fontStyle:"italic"}},{types:["punctuation"],style:{color:"rgb(255, 255, 255)"}},{types:["constant"],style:{color:"rgb(255, 98, 140)"}},{types:["string","url"],style:{color:"rgb(165, 255, 144)"}},{types:["variable"],style:{color:"rgb(255, 238, 128)"}},{types:["number","boolean"],style:{color:"rgb(255, 98, 140)"}},{types:["attr-name"],style:{color:"rgb(255, 180, 84)"}},{types:["keyword","operator","property","namespace","tag","selector","doctype"],style:{color:"rgb(255, 157, 0)"}},{types:["builtin","char","constant","function","class-name"],style:{color:"rgb(250, 208, 0)"}}]},eb={plain:{backgroundColor:"linear-gradient(to bottom, #2a2139 75%, #34294f)",backgroundImage:"#34294f",color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"},styles:[{types:["comment","block-comment","prolog","doctype","cdata"],style:{color:"#495495",fontStyle:"italic"}},{types:["punctuation"],style:{color:"#ccc"}},{types:["tag","attr-name","namespace","number","unit","hexcode","deleted"],style:{color:"#e2777a"}},{types:["property","selector"],style:{color:"#72f1b8",textShadow:"0 0 2px #100c0f, 0 0 10px #257c5575, 0 0 35px #21272475"}},{types:["function-name"],style:{color:"#6196cc"}},{types:["boolean","selector-id","function"],style:{color:"#fdfdfd",textShadow:"0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975, 0 0 8px #03edf975"}},{types:["class-name","maybe-class-name","builtin"],style:{color:"#fff5f6",textShadow:"0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75, 0 0 25px #fc1f2c75"}},{types:["constant","symbol"],style:{color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"}},{types:["important","atrule","keyword","selector-class"],style:{color:"#f4eee4",textShadow:"0 0 2px #393a33, 0 0 8px #f39f0575, 0 0 2px #f39f0575"}},{types:["string","char","attr-value","regex","variable"],style:{color:"#f87c32"}},{types:["parameter"],style:{fontStyle:"italic"}},{types:["entity","url"],style:{color:"#67cdcc"}},{types:["operator"],style:{color:"ffffffee"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["entity"],style:{cursor:"help"}},{types:["inserted"],style:{color:"green"}}]},ev={plain:{color:"#282a2e",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(197, 200, 198)"}},{types:["string","number","builtin","variable"],style:{color:"rgb(150, 152, 150)"}},{types:["class-name","function","tag","attr-name"],style:{color:"rgb(40, 42, 46)"}}]},ex={plain:{color:"#9CDCFE",backgroundColor:"#1E1E1E"},styles:[{types:["prolog"],style:{color:"rgb(0, 0, 128)"}},{types:["comment"],style:{color:"rgb(106, 153, 85)"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"rgb(86, 156, 214)"}},{types:["number","inserted"],style:{color:"rgb(181, 206, 168)"}},{types:["constant"],style:{color:"rgb(100, 102, 149)"}},{types:["attr-name","variable"],style:{color:"rgb(156, 220, 254)"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"rgb(206, 145, 120)"}},{types:["selector"],style:{color:"rgb(215, 186, 125)"}},{types:["tag"],style:{color:"rgb(78, 201, 176)"}},{types:["tag"],languages:["markup"],style:{color:"rgb(86, 156, 214)"}},{types:["punctuation","operator"],style:{color:"rgb(212, 212, 212)"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"rgb(220, 220, 170)"}},{types:["class-name"],style:{color:"rgb(78, 201, 176)"}},{types:["char"],style:{color:"rgb(209, 105, 105)"}}]},ew={plain:{color:"#000000",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(0, 128, 0)"}},{types:["builtin"],style:{color:"rgb(0, 112, 193)"}},{types:["number","variable","inserted"],style:{color:"rgb(9, 134, 88)"}},{types:["operator"],style:{color:"rgb(0, 0, 0)"}},{types:["constant","char"],style:{color:"rgb(129, 31, 63)"}},{types:["tag"],style:{color:"rgb(128, 0, 0)"}},{types:["attr-name"],style:{color:"rgb(255, 0, 0)"}},{types:["deleted","string"],style:{color:"rgb(163, 21, 21)"}},{types:["changed","punctuation"],style:{color:"rgb(4, 81, 165)"}},{types:["function","keyword"],style:{color:"rgb(0, 0, 255)"}},{types:["class-name"],style:{color:"rgb(38, 127, 153)"}}]},ek={plain:{color:"#f8fafc",backgroundColor:"#011627"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#569CD6"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#f8fafc"}},{types:["attr-name","variable"],style:{color:"#9CDCFE"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#cbd5e1"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#D4D4D4"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#7dd3fc"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},eS={plain:{color:"#0f172a",backgroundColor:"#f1f5f9"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#0c4a6e"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#0f172a"}},{types:["attr-name","variable"],style:{color:"#0c4a6e"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#64748b"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#475569"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#0e7490"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},eE={plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},e_={plain:{backgroundColor:"hsl(230, 1%, 98%)",color:"hsl(230, 8%, 24%)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(230, 4%, 64%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(230, 8%, 24%)"}},{types:["attr-name","class-name","boolean","constant","number","atrule"],style:{color:"hsl(35, 99%, 36%)"}},{types:["keyword"],style:{color:"hsl(301, 63%, 40%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(5, 74%, 59%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value","punctuation"],style:{color:"hsl(119, 34%, 47%)"}},{types:["variable","operator","function"],style:{color:"hsl(221, 87%, 60%)"}},{types:["url"],style:{color:"hsl(198, 99%, 37%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(230, 8%, 24%)"}}]},eC={plain:{color:"#ebdbb2",backgroundColor:"#292828"},styles:[{types:["imports","class-name","maybe-class-name","constant","doctype","builtin","function"],style:{color:"#d8a657"}},{types:["property-access"],style:{color:"#7daea3"}},{types:["tag"],style:{color:"#e78a4e"}},{types:["attr-name","char","url","regex"],style:{color:"#a9b665"}},{types:["attr-value","string"],style:{color:"#89b482"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#ea6962"}},{types:["entity","number","symbol"],style:{color:"#d3869b"}}]},eT={plain:{color:"#654735",backgroundColor:"#f9f5d7"},styles:[{types:["delimiter","boolean","keyword","selector","important","atrule","property","variable","deleted"],style:{color:"#af2528"}},{types:["imports","class-name","maybe-class-name","constant","doctype","builtin"],style:{color:"#b4730e"}},{types:["string","attr-value"],style:{color:"#477a5b"}},{types:["property-access"],style:{color:"#266b79"}},{types:["function","attr-name","char","url"],style:{color:"#72761e"}},{types:["tag"],style:{color:"#b94c07"}},{types:["comment","prolog","cdata","operator","inserted"],style:{color:"#a89984"}},{types:["entity","number","symbol"],style:{color:"#924f79"}}]},eN=(e,t)=>{let{plain:n}=e,r=e.styles.reduce((e,n)=>{let{languages:r,style:a}=n;return r&&!r.includes(t)?e:(n.types.forEach(t=>{let n=G(G({},e[t]),a);e[t]=n}),e)},{});return r.root=n,r.plain=q(G({},n),{backgroundColor:void 0}),r},eA=(e,t)=>{let[n,r]=(0,R.useState)(eN(t,e)),a=(0,R.useRef)(),o=(0,R.useRef)();return(0,R.useEffect)(()=>{(t!==a.current||e!==o.current)&&(a.current=t,o.current=e,r(eN(t,e)))},[e,t]),n},eO=e=>(0,R.useCallback)(t=>{var{className:n,style:r,line:a}=t;let o=q(G({},Y(t,["className","style","line"])),{className:(0,I.Z)("token-line",n)});return"object"==typeof e&&"plain"in e&&(o.style=e.plain),"object"==typeof r&&(o.style=G(G({},o.style||{}),r)),o},[e]),eP=e=>{let t=(0,R.useCallback)(({types:t,empty:n})=>{if(null!=e){if(1===t.length&&"plain"===t[0])return null!=n?{display:"inline-block"}:void 0;if(1===t.length&&null!=n)return e[t[0]];return Object.assign(null!=n?{display:"inline-block"}:{},...t.map(t=>e[t]))}},[e]);return(0,R.useCallback)(e=>{var{token:n,className:r,style:a}=e;let o=q(G({},Y(e,["token","className","style"])),{className:(0,I.Z)("token",...n.types,r),children:n.content,style:t(n)});return null!=a&&(o.style=G(G({},o.style||{}),a)),o},[t])},ej=/\r\n|\r|\n/,eL=e=>{0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},eR=(e,t)=>{let n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},eI=e=>{let t=[[]],n=[e],r=[0],a=[e.length],o=0,i=0,l=[],s=[l];for(;i>-1;){for(;(o=r[i]++)<a[i];){let e;let u=t[i],c=n[i][o];if("string"==typeof c?(u=i>0?u:["plain"],e=c):(u=eR(u,c.type),c.alias&&(u=eR(u,c.alias)),e=c.content),"string"!=typeof e){i++,t.push(u),n.push(e),r.push(0),a.push(e.length);continue}let d=e.split(ej),f=d.length;l.push({types:u,content:d[0]});for(let e=1;e<f;e++)eL(l),s.push(l=[]),l.push({types:u,content:d[e]})}i--,t.pop(),n.pop(),r.pop(),a.pop()}return eL(l),s},eM=({prism:e,code:t,grammar:n,language:r})=>{let a=(0,R.useRef)(e);return(0,R.useMemo)(()=>{if(null==n)return eI([t]);let e={code:t,grammar:n,language:r,tokens:[]};return a.current.hooks.run("before-tokenize",e),e.tokens=a.current.tokenize(t,n),a.current.hooks.run("after-tokenize",e),eI(e.tokens)},[t,n,r])},eF=({children:e,language:t,code:n,theme:r,prism:a})=>{let o=t.toLowerCase(),i=eA(o,r),l=eO(i),s=eP(i),u=a.languages[o];return e({tokens:eM({prism:a,language:o,code:n,grammar:u}),className:`prism-code language-${o}`,style:null!=i?i.root:{},getLineProps:l,getTokenProps:s})},eD=e=>(0,R.createElement)(eF,q(G({},e),{prism:e.prism||Q,theme:e.theme||ex,code:e.code,language:e.language}))},1835:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});var r="Invariant failed";function a(e,t){var n;if(!e)throw Error(r)}},8395:function(e,t,n){"use strict";n.r(t),n.d(t,{__addDisposableResource:function(){return I},__assign:function(){return o},__asyncDelegator:function(){return _},__asyncGenerator:function(){return E},__asyncValues:function(){return C},__await:function(){return S},__awaiter:function(){return h},__classPrivateFieldGet:function(){return j},__classPrivateFieldIn:function(){return R},__classPrivateFieldSet:function(){return L},__createBinding:function(){return m},__decorate:function(){return l},__disposeResources:function(){return F},__esDecorate:function(){return u},__exportStar:function(){return y},__extends:function(){return a},__generator:function(){return g},__importDefault:function(){return P},__importStar:function(){return O},__makeTemplateObject:function(){return T},__metadata:function(){return p},__param:function(){return s},__propKey:function(){return d},__read:function(){return v},__rest:function(){return i},__rewriteRelativeImportExtension:function(){return D},__runInitializers:function(){return c},__setFunctionName:function(){return f},__spread:function(){return x},__spreadArray:function(){return k},__spreadArrays:function(){return w},__values:function(){return b},default:function(){return z}});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function a(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var o=function(){return(o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var a in t=arguments[n],t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e}).apply(this,arguments)};function i(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&0>t.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var a=0,r=Object.getOwnPropertySymbols(e);a<r.length;a++)0>t.indexOf(r[a])&&Object.prototype.propertyIsEnumerable.call(e,r[a])&&(n[r[a]]=e[r[a]]);return n}function l(e,t,n,r){var a,o=arguments.length,i=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,n,r);else for(var l=e.length-1;l>=0;l--)(a=e[l])&&(i=(o<3?a(i):o>3?a(t,n,i):a(t,n))||i);return o>3&&i&&Object.defineProperty(t,n,i),i}function s(e,t){return function(n,r){t(n,r,e)}}function u(e,t,n,r,a,o){function i(e){if(void 0!==e&&"function"!=typeof e)throw TypeError("Function expected");return e}for(var l=r.kind,s="getter"===l?"get":"setter"===l?"set":"value",u=!t&&e?r.static?e:e.prototype:null,c=t||(u?Object.getOwnPropertyDescriptor(u,r.name):{}),d,f=!1,p=n.length-1;p>=0;p--){var h={};for(var g in r)h[g]="access"===g?{}:r[g];for(var g in r.access)h.access[g]=r.access[g];h.addInitializer=function(e){if(f)throw TypeError("Cannot add initializers after decoration has completed");o.push(i(e||null))};var m=(0,n[p])("accessor"===l?{get:c.get,set:c.set}:c[s],h);if("accessor"===l){if(void 0===m)continue;if(null===m||"object"!=typeof m)throw TypeError("Object expected");(d=i(m.get))&&(c.get=d),(d=i(m.set))&&(c.set=d),(d=i(m.init))&&a.unshift(d)}else(d=i(m))&&("field"===l?a.unshift(d):c[s]=d)}u&&Object.defineProperty(u,r.name,c),f=!0}function c(e,t,n){for(var r=arguments.length>2,a=0;a<t.length;a++)n=r?t[a].call(e,n):t[a].call(e);return r?n:void 0}function d(e){return"symbol"==typeof e?e:"".concat(e)}function f(e,t,n){return"symbol"==typeof t&&(t=t.description?"[".concat(t.description,"]"):""),Object.defineProperty(e,"name",{configurable:!0,value:n?"".concat(n," ",t):t})}function p(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function h(e,t,n,r){return new(n||(n=Promise))(function(a,o){function i(e){try{s(r.next(e))}catch(e){o(e)}}function l(e){try{s(r.throw(e))}catch(e){o(e)}}function s(e){var t;e.done?a(e.value):((t=e.value)instanceof n?t:new n(function(e){e(t)})).then(i,l)}s((r=r.apply(e,t||[])).next())})}function g(e,t){var n,r,a,o={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=l(0),i.throw=l(1),i.return=l(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function l(l){return function(s){return function(l){if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(o=0)),o;)try{if(n=1,r&&(a=2&l[0]?r.return:l[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,l[1])).done)return a;switch(r=0,a&&(l=[2&l[0],a.value]),l[0]){case 0:case 1:a=l;break;case 4:return o.label++,{value:l[1],done:!1};case 5:o.label++,r=l[1],l=[0];continue;case 7:l=o.ops.pop(),o.trys.pop();continue;default:if(!(a=(a=o.trys).length>0&&a[a.length-1])&&(6===l[0]||2===l[0])){o=0;continue}if(3===l[0]&&(!a||l[1]>a[0]&&l[1]<a[3])){o.label=l[1];break}if(6===l[0]&&o.label<a[1]){o.label=a[1],a=l;break}if(a&&o.label<a[2]){o.label=a[2],o.ops.push(l);break}a[2]&&o.ops.pop(),o.trys.pop();continue}l=t.call(e,o)}catch(e){l=[6,e],r=0}finally{n=a=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}([l,s])}}}var m=Object.create?function(e,t,n,r){void 0===r&&(r=n);var a=Object.getOwnPropertyDescriptor(t,n);(!a||("get"in a?!t.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,a)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]};function y(e,t){for(var n in e)"default"!==n&&!Object.prototype.hasOwnProperty.call(t,n)&&m(t,e,n)}function b(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function v(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,a,o=n.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)i.push(r.value)}catch(e){a={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(a)throw a.error}}return i}function x(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(v(arguments[t]));return e}function w(){for(var e=0,t=0,n=arguments.length;t<n;t++)e+=arguments[t].length;for(var r=Array(e),a=0,t=0;t<n;t++)for(var o=arguments[t],i=0,l=o.length;i<l;i++,a++)r[a]=o[i];return r}function k(e,t,n){if(n||2==arguments.length)for(var r,a=0,o=t.length;a<o;a++)(r||!(a in t))&&(!r&&(r=Array.prototype.slice.call(t,0,a)),r[a]=t[a]);return e.concat(r||Array.prototype.slice.call(t))}function S(e){return this instanceof S?(this.v=e,this):new S(e)}function E(e,t,n){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var r,a=n.apply(e,t||[]),o=[];return r=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),i("next"),i("throw"),i("return",function(e){return function(t){return Promise.resolve(t).then(e,u)}}),r[Symbol.asyncIterator]=function(){return this},r;function i(e,t){a[e]&&(r[e]=function(t){return new Promise(function(n,r){o.push([e,t,n,r])>1||l(e,t)})},t&&(r[e]=t(r[e])))}function l(e,t){try{(function(e){e.value instanceof S?Promise.resolve(e.value.v).then(s,u):c(o[0][2],e)})(a[e](t))}catch(e){c(o[0][3],e)}}function s(e){l("next",e)}function u(e){l("throw",e)}function c(e,t){e(t),o.shift(),o.length&&l(o[0][0],o[0][1])}}function _(e){var t,n;return t={},r("next"),r("throw",function(e){throw e}),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,a){t[r]=e[r]?function(t){return(n=!n)?{value:S(e[r](t)),done:!1}:a?a(t):t}:a}}function C(e){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=b(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise(function(r,a){(function(e,t,n,r){Promise.resolve(r).then(function(t){e({value:t,done:n})},t)})(r,a,(t=e[n](t)).done,t.value)})}}}function T(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var N=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},A=function(e){return(A=Object.getOwnPropertyNames||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[t.length]=n);return t})(e)};function O(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n=A(e),r=0;r<n.length;r++)"default"!==n[r]&&m(t,e,n[r]);return N(t,e),t}function P(e){return e&&e.__esModule?e:{default:e}}function j(e,t,n,r){if("a"===n&&!r)throw TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!r:!t.has(e))throw TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?r:"a"===n?r.call(e):r?r.value:t.get(e)}function L(e,t,n,r,a){if("m"===r)throw TypeError("Private method is not writable");if("a"===r&&!a)throw TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!a:!t.has(e))throw TypeError("Cannot write private member to an object whose class did not declare it");return"a"===r?a.call(e,n):a?a.value=n:t.set(e,n),n}function R(e,t){if(null===t||"object"!=typeof t&&"function"!=typeof t)throw TypeError("Cannot use 'in' operator on non-object");return"function"==typeof e?t===e:e.has(t)}function I(e,t,n){if(null!=t){var r,a;if("object"!=typeof t&&"function"!=typeof t)throw TypeError("Object expected.");if(n){if(!Symbol.asyncDispose)throw TypeError("Symbol.asyncDispose is not defined.");r=t[Symbol.asyncDispose]}if(void 0===r){if(!Symbol.dispose)throw TypeError("Symbol.dispose is not defined.");r=t[Symbol.dispose],n&&(a=r)}if("function"!=typeof r)throw TypeError("Object not disposable.");a&&(r=function(){try{a.call(this)}catch(e){return Promise.reject(e)}}),e.stack.push({value:t,dispose:r,async:n})}else n&&e.stack.push({async:!0});return t}var M="function"==typeof SuppressedError?SuppressedError:function(e,t,n){var r=Error(n);return r.name="SuppressedError",r.error=e,r.suppressed=t,r};function F(e){function t(t){e.error=e.hasError?new M(t,e.error,"An error was suppressed during disposal."):t,e.hasError=!0}var n,r=0;return function a(){for(;n=e.stack.pop();)try{if(!n.async&&1===r)return r=0,e.stack.push(n),Promise.resolve().then(a);if(n.dispose){var o=n.dispose.call(n.value);if(n.async)return r|=2,Promise.resolve(o).then(a,function(e){return t(e),a()})}else r|=1}catch(e){t(e)}if(1===r)return e.hasError?Promise.reject(e.error):Promise.resolve();if(e.hasError)throw e.error}()}function D(e,t){return"string"==typeof e&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(e,n,r,a,o){return n?t?".jsx":".js":!r||a&&o?r+a+"."+o.toLowerCase()+"js":e}):e}let z={__extends:a,__assign:o,__rest:i,__decorate:l,__param:s,__esDecorate:u,__runInitializers:c,__propKey:d,__setFunctionName:f,__metadata:p,__awaiter:h,__generator:g,__createBinding:m,__exportStar:y,__values:b,__read:v,__spread:x,__spreadArrays:w,__spreadArray:k,__await:S,__asyncGenerator:E,__asyncDelegator:_,__asyncValues:C,__makeTemplateObject:T,__importStar:O,__importDefault:P,__classPrivateFieldGet:j,__classPrivateFieldSet:L,__classPrivateFieldIn:R,__addDisposableResource:I,__disposeResources:F,__rewriteRelativeImportExtension:D}},2627:function(e){"use strict";e.exports={}},7138:function(e){"use strict";e.exports=JSON.parse('{"/2011/11/webpack-industrial-complex-1d7":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"1e5192b9"},"/2015/11/autocallable-259":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"1806d708"},"/2015/11/welcome-fd8":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"818287cf"},"/2015/12/testing-cramer-e37":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d085497a"},"/2016/01/cloudy-in-seattle-72a":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3cafba32"},"/2016/01/complaining-about-the-weather-598":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"92079dc1"},"/2016/02/guaranteed-money-maker-911":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"fd7e7e63"},"/2016/02/profitability-using-the-investment-formula-47f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"35b21e3d"},"/2016/03/predicting-santander-customer-happiness-906":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"962a4168"},"/2016/03/tweet-like-me-e83":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"72c73938"},"/2016/04/tick-tock-a99":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"b08f0f32"},"/2016/05/the-unfair-casino-11e":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"5f602fa1"},"/2016/06/event-studies-and-earnings-releases-d88":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"4c2b0735"},"/2016/10/rustic-repodcasting-0a7":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"1803684d"},"/2016/11/pca-audio-compression-31c":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"cd68b6a4"},"/2018/01/captains-cookbook-part-1-555":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"ef7aa1ca"},"/2018/01/captains-cookbook-part-2-98a":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"71d18034"},"/2018/05/hello-98e":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"b537349a"},"/2018/06/dateutil-parser-to-rust-63f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"16c8da5a"},"/2018/09/isomorphic-apps-cc3":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3d0fb9fd"},"/2018/09/primitives-in-rust-are-weird-ead":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"130b4a4b"},"/2018/10/case-study-optimization-062":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"f8fee0f7"},"/2018/12/allocation-safety-1ae":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"c97f4488"},"/2018/12/what-small-business-really-means-71f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3a2ddf2f"},"/2019/02/08/compiler-optimizations-a2d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"d185f613"},"/2019/02/a-heaping-helping-b4d":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"761aff6b"},"/2019/02/stacking-up-1cc":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"85b3a5ed"},"/2019/02/summary-194":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"e37dfb5c"},"/2019/02/the-whole-world-ccd":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"88eed8c4"},"/2019/02/understanding-allocations-in-rust-e0a":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"94d32f6c"},"/2019/05/making-bread-3d0":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"77bf0009"},"/2019/06/high-performance-systems-46f":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"3aab746c"},"/2019/09/binary-format-shootout-6d5":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"39c8d8a0"},"/2019/12/release-the-gil-8c2":{"__comp":"ccc49370","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","content":"0fb9ce37"},"/archive-51a":{"__comp":"9e4087bc","__context":{"plugin":"36994c47"},"__props":"b266de79"},"/authors-498":{"__comp":"621db11d","__context":{"data":{"blogMetadata":"acecf23e"},"plugin":"36994c47"},"sidebar":"814f3328","__props":"3f9ae9f6"},"/feed.xml-eda":{"__comp":"868a7989","__context":{"plugin":"a7456010"},"config":"5e9f5e1a"},"/page/2-e79":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"d280b035"},{"content":"76b3b3f5"},{"content":"975a028b"},{"content":"db76ea4b"},{"content":"522b09ee"},{"content":"6fa48b14"},{"content":"78d2eb38"},{"content":"724b3f70"},{"content":"4dbec139"},{"content":"ed9b7162"}],"__props":"aea41ef6"},"/page/3-92e":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"857496c7"},{"content":"b16509ac"},{"content":"e62372be"},{"content":"c32740fe"},{"content":"b5b60058"},{"content":"b5d84c45"},{"content":"1b190668"},{"content":"7ba60abf"},{"content":"319b187a"},{"content":"1d2da633"}],"__props":"33496f92"},"/page/4-0bb":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"f2eb9457"},{"content":"47f41a37"},{"content":"89fbf712"},{"content":"1fe257c0"}],"__props":"de854ad9"},"/-e81":{"__comp":"a6aa9e1f","__context":{"plugin":"36994c47"},"sidebar":"814f3328","items":[{"content":"de863535"},{"content":"dca2e11d"},{"content":"1f1953c8"},{"content":"2062e753"},{"content":"4cf7e30f"},{"content":"84329d6a"},{"content":"8fedb115"},{"content":"d7ab2b33"},{"content":"a14a666c"},{"content":"e0aaf982"}],"__props":"1a1424c7"}}')}},function(e){e.O(0,["6212"],function(){return e(e.s="3426")}),e.O()}]); \ No newline at end of file diff --git a/assets/js/runtime~main.751b419d.js b/assets/js/runtime~main.751b419d.js new file mode 100644 index 0000000..bd4f601 --- /dev/null +++ b/assets/js/runtime~main.751b419d.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,f,c,d,t,r,n,b={},o={};function u(e){var a=o[e];if(void 0!==a)return a.exports;var f=o[e]={id:e,loaded:!1,exports:{}};return b[e].call(f.exports,f,f.exports,u),f.loaded=!0,f.exports}u.m=b,u.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(a,{a:a}),a},a=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},u.t=function(f,c){if(1&c&&(f=this(f)),8&c||"object"==typeof f&&f&&(4&c&&f.__esModule||16&c&&"function"==typeof f.then))return f;var d=Object.create(null);u.r(d);var t={};e=e||[null,a({}),a([]),a(a)];for(var r=2&c&&f;"object"==typeof r&&!~e.indexOf(r);r=a(r))Object.getOwnPropertyNames(r).forEach(function(e){t[e]=function(){return f[e]}});return t.default=function(){return f},u.d(d,t),d},u.d=function(e,a){for(var f in a)u.o(a,f)&&!u.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},u.f={},u.e=function(e){return Promise.all(Object.keys(u.f).reduce(function(a,f){return u.f[f](e,a),a},[]))},u.hmd=function(e){return!(e=Object.create(e)).children&&(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},u.u=function(e){return"assets/js/"+(({1e3:"a14a666c",106:"814f3328",1225:"b266de79",1408:"cd68b6a4",1446:"4cf7e30f",1511:"6fa48b14",156:"39c8d8a0",1652:"88eed8c4",1672:"3aab746c",1680:"33496f92",1874:"85b3a5ed",2410:"1f1953c8",2433:"84329d6a",2628:"b16509ac",2792:"36994c47",294:"130b4a4b",2998:"ccc49370",302:"962a4168",3241:"1806d708",3533:"ed9b7162",3837:"1fe257c0",3956:"e37dfb5c",4384:"3d0fb9fd",4558:"71d18034",4593:"8fedb115",4595:"aea41ef6",4718:"4c2b0735",4760:"f8fee0f7",4794:"89fbf712",4809:"319b187a",4833:"35b21e3d",4844:"3a2ddf2f",5095:"818287cf",5168:"857496c7",5229:"1b190668",5373:"1d2da633",5407:"d185f613",5478:"975a028b",5523:"b5d84c45",5644:"1e5192b9",5747:"724b3f70",5810:"522b09ee",5969:"868a7989",6078:"b537349a",6138:"db76ea4b",6240:"77bf0009",6267:"3cafba32",6424:"dca2e11d",6781:"e62372be",6992:"c32740fe",7073:"47f41a37",7109:"3f9ae9f6",7120:"d280b035",7293:"9e4087bc",7365:"a7456010",7366:"761aff6b",7580:"94d32f6c",7624:"1803684d",7627:"acecf23e",7702:"7ba60abf",7848:"0fb9ce37",7953:"4dbec139",8276:"de863535",832:"ef7aa1ca",8345:"5f602fa1",8514:"a6aa9e1f",8704:"d085497a",8770:"2062e753",8863:"f2eb9457",8868:"fd7e7e63",8977:"78d2eb38",8987:"76b3b3f5",8998:"e0aaf982",9127:"d7ab2b33",9363:"b08f0f32",9366:"92079dc1",9437:"c97f4488",95:"16c8da5a",9658:"72c73938",9763:"1a1424c7",9798:"b5b60058",9854:"621db11d",9994:"de854ad9"})[e]||e)+"."+({1e3:"bfdacafa",106:"1f5daeee",1225:"ae25f078",1408:"371cb0e3",1446:"9d25ceb5",1511:"90d2bd8d",156:"ee5aa2e0",1652:"1f2da266",1672:"9a48ca86",1680:"dec736d4",1874:"c46f1e8b",2061:"3bbdbc04",2410:"5837c39b",2433:"ef47a922",2519:"06ba1bd0",2628:"cc76897d",2792:"0c1ebe43",294:"8e30fd10",2998:"f10e1762",302:"a5498250",3241:"22f71128",3533:"911627e7",3837:"d2e59b40",3956:"04d97c35",4294:"a7567dcb",4384:"94683b2b",4558:"0eabaf41",4593:"e520b846",4595:"9227fb2a",4718:"497a037f",4760:"90b05631",4794:"0cbe55d4",4809:"06669ed5",4833:"3e3cc712",4844:"21bbad76",5095:"09f82d49",5168:"71360a70",5229:"1a035f32",5373:"f724f156",5407:"d18d8259",5478:"b8fcc2ff",5523:"bfcf3ca8",5601:"f9142a81",5644:"9888c924",5747:"bf6a608e",5810:"b6dc382a",5969:"8d7c3544",6078:"fd272082",6138:"9758d9ce",6240:"fdc32348",6267:"27890503",6424:"209b089a",6472:"40189ba2",6781:"2024c2a5",6992:"fac8281f",7073:"e28a1f98",7109:"2800ab67",7120:"762e2b8a",7293:"7ce15d2c",7365:"f1672167",7366:"101e026d",7580:"bca1abd5",7624:"778a092f",7627:"31db30f2",7702:"8ef0d9fb",7848:"ec625f5c",7953:"aa429c61",8276:"9c2d8ada",832:"f98a4c92",8345:"12465c04",8514:"1b78d77e",8704:"41eaf6d0",8770:"bee6da1d",8863:"6fac4cda",8868:"09b6c6e9",8977:"6ac70e04",8987:"c2e17148",8998:"98e12c9e",9127:"2a9efd2a",9363:"4de38c21",9366:"4088067f",9437:"7aeaa095",95:"6e786399",9555:"2cb431fa",9658:"10945791",9763:"9077c1c0",9798:"690e82eb",9854:"329bb35b",9990:"f91a94a2",9994:"70027cd9"})[e]+".js"},u.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),u.o=function(e,a){return Object.prototype.hasOwnProperty.call(e,a)},f={},c="speice-io:",u.l=function(e,a,d,t){if(f[e]){f[e].push(a);return}if(void 0!==d){for(var r,n,b=document.getElementsByTagName("script"),o=0;o<b.length;o++){var i=b[o];if(i.getAttribute("src")==e||i.getAttribute("data-webpack")==c+d){r=i;break}}}!r&&(n=!0,(r=document.createElement("script")).charset="utf-8",r.timeout=120,u.nc&&r.setAttribute("nonce",u.nc),r.setAttribute("data-webpack",c+d),r.src=e),f[e]=[a];var l=function(a,c){r.onerror=r.onload=null,clearTimeout(s);var d=f[e];if(delete f[e],r.parentNode&&r.parentNode.removeChild(r),d&&d.forEach(function(e){return e(c)}),a)return a(c)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=l.bind(null,r.onerror),r.onload=l.bind(null,r.onload),n&&document.head.appendChild(r)},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d=[],u.O=function(e,a,f,c){if(a){c=c||0;for(var t=d.length;t>0&&d[t-1][2]>c;t--)d[t]=d[t-1];d[t]=[a,f,c];return}for(var r=1/0,t=0;t<d.length;t++){for(var a=d[t][0],f=d[t][1],c=d[t][2],n=!0,b=0;b<a.length;b++)(!1&c||r>=c)&&Object.keys(u.O).every(function(e){return u.O[e](a[b])})?a.splice(b--,1):(n=!1,c<r&&(r=c));if(n){d.splice(t--,1);var o=f();void 0!==o&&(e=o)}}return e},u.p="/",u.rv=function(){return"1.0.14"},u.gca=function(e){return e=({"16c8da5a":"95","814f3328":"106","39c8d8a0":"156","130b4a4b":"294","962a4168":"302",ef7aa1ca:"832",a14a666c:"1000",b266de79:"1225",cd68b6a4:"1408","4cf7e30f":"1446","6fa48b14":"1511","88eed8c4":"1652","3aab746c":"1672","33496f92":"1680","85b3a5ed":"1874","1f1953c8":"2410","84329d6a":"2433",b16509ac:"2628","36994c47":"2792",ccc49370:"2998","1806d708":"3241",ed9b7162:"3533","1fe257c0":"3837",e37dfb5c:"3956","3d0fb9fd":"4384","71d18034":"4558","8fedb115":"4593",aea41ef6:"4595","4c2b0735":"4718",f8fee0f7:"4760","89fbf712":"4794","319b187a":"4809","35b21e3d":"4833","3a2ddf2f":"4844","818287cf":"5095","857496c7":"5168","1b190668":"5229","1d2da633":"5373",d185f613:"5407","975a028b":"5478",b5d84c45:"5523","1e5192b9":"5644","724b3f70":"5747","522b09ee":"5810","868a7989":"5969",b537349a:"6078",db76ea4b:"6138","77bf0009":"6240","3cafba32":"6267",dca2e11d:"6424",e62372be:"6781",c32740fe:"6992","47f41a37":"7073","3f9ae9f6":"7109",d280b035:"7120","9e4087bc":"7293",a7456010:"7365","761aff6b":"7366","94d32f6c":"7580","1803684d":"7624",acecf23e:"7627","7ba60abf":"7702","0fb9ce37":"7848","4dbec139":"7953",de863535:"8276","5f602fa1":"8345",a6aa9e1f:"8514",d085497a:"8704","2062e753":"8770",f2eb9457:"8863",fd7e7e63:"8868","78d2eb38":"8977","76b3b3f5":"8987",e0aaf982:"8998",d7ab2b33:"9127",b08f0f32:"9363","92079dc1":"9366",c97f4488:"9437","72c73938":"9658","1a1424c7":"9763",b5b60058:"9798","621db11d":"9854",de854ad9:"9994"})[e]||e,u.p+u.u(e)},t={2580:0,6212:0},u.f.j=function(e,a){var f=u.o(t,e)?t[e]:void 0;if(0!==f){if(f)a.push(f[2]);else if(/^(2580|6212)$/.test(e))t[e]=0;else{var c=new Promise(function(a,c){f=t[e]=[a,c]});a.push(f[2]=c);var d=u.p+u.u(e),r=Error();u.l(d,function(a){if(u.o(t,e)&&(0!==(f=t[e])&&(t[e]=void 0),f)){var c=a&&("load"===a.type?"missing":a.type),d=a&&a.target&&a.target.src;r.message="Loading chunk "+e+" failed.\n("+c+": "+d+")",r.name="ChunkLoadError",r.type=c,r.request=d,f[1](r)}},"chunk-"+e,e)}}},u.O.j=function(e){return 0===t[e]},r=function(e,a){var f=a[0],c=a[1],d=a[2],r,n,b=0;if(f.some(function(e){return 0!==t[e]})){for(r in c)u.o(c,r)&&(u.m[r]=c[r]);if(d)var o=d(u)}for(e&&e(a);b<f.length;b++)n=f[b],u.o(t,n)&&t[n]&&t[n][0](),t[n]=0;return u.O(o)},(n=self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n))})(); \ No newline at end of file diff --git a/assets/medias/1-bc356a416dae6236d2e366a42bee2cd3.wav b/assets/medias/1-bc356a416dae6236d2e366a42bee2cd3.wav new file mode 100644 index 0000000..e85ba39 Binary files /dev/null and b/assets/medias/1-bc356a416dae6236d2e366a42bee2cd3.wav differ diff --git a/assets/medias/2-bc356a416dae6236d2e366a42bee2cd3.wav b/assets/medias/2-bc356a416dae6236d2e366a42bee2cd3.wav new file mode 100644 index 0000000..e85ba39 Binary files /dev/null and b/assets/medias/2-bc356a416dae6236d2e366a42bee2cd3.wav differ diff --git a/assets/medias/3-e8092f56b531e18a0d335c0f391b46b9.wav b/assets/medias/3-e8092f56b531e18a0d335c0f391b46b9.wav new file mode 100644 index 0000000..52ac8c8 Binary files /dev/null and b/assets/medias/3-e8092f56b531e18a0d335c0f391b46b9.wav differ diff --git a/assets/medias/4-90047e615651067970475dc7f117aceb.wav b/assets/medias/4-90047e615651067970475dc7f117aceb.wav new file mode 100644 index 0000000..0aa398c Binary files /dev/null and b/assets/medias/4-90047e615651067970475dc7f117aceb.wav differ diff --git a/assets/medias/5-896767515da7b5a0fe46e9a205c1130f.wav b/assets/medias/5-896767515da7b5a0fe46e9a205c1130f.wav new file mode 100644 index 0000000..d708c5d Binary files /dev/null and b/assets/medias/5-896767515da7b5a0fe46e9a205c1130f.wav differ diff --git a/assets/medias/6-756ec27a28b4fa02181f43ed9061f0b3.wav b/assets/medias/6-756ec27a28b4fa02181f43ed9061f0b3.wav new file mode 100644 index 0000000..28967e4 Binary files /dev/null and b/assets/medias/6-756ec27a28b4fa02181f43ed9061f0b3.wav differ diff --git a/atom.css b/atom.css new file mode 100644 index 0000000..d2fc20b --- /dev/null +++ b/atom.css @@ -0,0 +1,75 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +main { + flex: 1 0 auto; + width: 100%; + margin: 2rem auto; + max-width: 800px; + /* stylelint-disable-next-line font-family-name-quotes */ + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell; +} + +.info { + display: block; + margin: 2rem 0; + padding: 1.6rem 2.4rem; + border: 1px solid dodgerblue; + border-left-width: 0.5rem; + border-radius: 0.4rem; + background-color: #edf5ff; +} + +a { + color: #005aff; + text-decoration: none; +} + +h1 { + text-wrap: balance; + font-size: 3.4rem; + font-weight: 800; + margin-bottom: 2rem; + display: flex; + align-items: center; +} + +h1 .rss-icon { + height: 3.2rem; + width: 3.2rem; + margin-right: 1rem; +} + +h2 { + font-size: 2.2rem; + font-weight: 700; + margin-bottom: 0.2rem; +} + +h3 { + font-size: 1.8rem; + font-weight: 700; + margin-bottom: 0.1rem; +} + +.blog-description { + font-size: 1.4rem; + margin-bottom: 0.6rem; +} + +.blog-post-date { + font-size: 1rem; + line-height: 1.4rem; + font-style: italic; + color: #797b7e; +} + +.blog-post-description { + font-size: 1rem; + line-height: 1.4rem; + color: #434349; +} diff --git a/atom.xml b/atom.xml new file mode 100644 index 0000000..60cc5ff --- /dev/null +++ b/atom.xml @@ -0,0 +1,2242 @@ +<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?> +<feed xmlns="http://www.w3.org/2005/Atom"> + <id>https://speice.io/</id> + <title>The Old Speice Guy Blog + 2022-11-20T12:00:00.000Z + https://github.com/jpmonette/feed + + The Old Speice Guy Blog + https://speice.io/img/favicon.ico + + <![CDATA[The webpack industrial complex]]> + https://speice.io/2011/11/webpack-industrial-complex + + 2022-11-20T12:00:00.000Z + + This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).

+

The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.

+

Starting strong

+

The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser."

+

Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an onEvent handler and a function easy.

+

Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical."

+

Continuing on

+

Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?

+

The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API was missing. After searching out Github issues and (unsuccessfully) tweaking the .tsconfig settings, I settled on installing a package and moving on.

+

The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use new URL(<local path>, import.meta.url) and it worked! Well, kind of:

+

Browser error

+

That file has the audio processor code, so why does it get served with Content-Type: video/mp2t?

+

Floundering about

+

Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to just use JavaScript and stuck by the original TypeScript requirement.

+

I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package.

+

I tried three different CRA tools - react-app-rewired, craco, customize-react-app - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well.

+

I tried changing the webpack configuration: using new loaders, setting asset rules, even changing how webpack detects worker resources. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up.

+

I tried so many application frameworks. Next.js looked like a good candidate, but added its own bespoke webpack complexity to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work.

+

Learning and reflecting

+

I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned.

+

For myself:

+
    +
  • I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work
  • +
  • I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts
  • +
+

For the tools:

+
    +
  • Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity
  • +
  • Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaks
  • +
  • There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it
  • +
+

In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Release the GIL]]> + https://speice.io/2019/12/release-the-gil + + 2019-12-14T12:00:00.000Z + + Complaining about the Global Interpreter Lock +(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision +made before multi-core CPU's were widely available, but the fact that it's still around indicates +that it generally works Good +Enough. Besides, there are simple and effective +workarounds; it's not hard to start a +new process and use message passing to +synchronize code running in parallel.

+

Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of +asynchronicity and M:N threading, Python seems lacking. The ideal scenario is to take advantage of +both Python's productivity and the modern CPU's parallel capabilities.

+

Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes +Python a nice language to start with. Bear in mind: these are just the tools, no claim is made about +whether it's a good idea to use them. Very often, unlocking the GIL is an +XY problem; you want application performance, and the +GIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at +the expense of project complexity; messing with the GIL is ultimately messing with Python's memory +model.

+
%load_ext Cython
from numba import jit

N = 1_000_000_000
+

Cython

+

Put simply, Cython is a programming language that looks a lot like Python, +gets transpiled to C/C++, and integrates +well with the CPython API. It's great for building Python +wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And +when it comes to managing the GIL, there are two special features:

+
    +
  • The nogil +function annotation +asserts that a Cython function is safe to use without the GIL, and compilation will fail if it +interacts with Python in an unsafe manner
  • +
  • The with nogil +context manager +explicitly unlocks the CPython GIL while active
  • +
+

Whenever Cython code runs inside a with nogil block on a separate thread, the Python interpreter +is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that +demonstrates this principle in action:

+
%%cython

# Annotating a function with `nogil` indicates only that it is safe
# to call in a `with nogil` block. It *does not* release the GIL.
cdef unsigned long fibonacci(unsigned long n) nogil:
if n <= 1:
return n

cdef unsigned long a = 0, b = 1, c = 0

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


def cython_nogil(unsigned long n):
# Explicitly release the GIL while running `fibonacci`
with nogil:
value = fibonacci(n)

return value


def cython_gil(unsigned long n):
# Because the GIL is not explicitly released, it implicitly
# remains acquired when running the `fibonacci` function
return fibonacci(n)
+

First, let's time how long it takes Cython to calculate the billionth Fibonacci number:

+
%%time
_ = cython_gil(N);
+
+

CPU times: user 365 ms, sys: 0 ns, total: 365 ms +Wall time: 372 ms

+
+
%%time
_ = cython_nogil(N);
+
+

CPU times: user 381 ms, sys: 0 ns, total: 381 ms +Wall time: 388 ms

+
+

Both versions (with and without GIL) take effectively the same amount of time to run. Even when +running this calculation in parallel on separate threads, it is expected that the run time will +double because only one thread can be active at a time:

+
%%time
from threading import Thread

# Create the two threads to run on
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
# Start the threads
t1.start(); t2.start()
# Wait for the threads to finish
t1.join(); t2.join()
+
+

CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms +Wall time: 645 ms

+
+

However, if the first thread releases the GIL, the second thread is free to acquire it and run in +parallel:

+
%%time

t1 = Thread(target=cython_nogil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 717 ms, sys: 372 µs, total: 718 ms +Wall time: 358 ms

+
+

Because user time represents the sum of processing time on all threads, it doesn't change much. +The "wall time" has been cut roughly in half +because each function is running simultaneously.

+

Keep in mind that the order in which threads are started makes a difference!

+
%%time

# Note that the GIL-locked version is started first
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 667 ms, sys: 0 ns, total: 667 ms +Wall time: 672 ms

+
+

Even though the second thread releases the GIL while running, it can't start until the first has +completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads.

+

Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the +interpreter, not just the thread attempting the unlock:

+
%%cython

cdef int cython_recurse(int n) nogil:
if n <= 0:
return 0

with nogil:
return cython_recurse(n - 1)

cython_recurse(2)
+
+

Fatal Python error: PyEval_SaveThread: NULL tstate

Thread 0x00007f499effd700 (most recent call first): +File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run +File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner +File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap

+
+

In practice, avoiding this issue is simple. First, nogil functions probably shouldn't contain +with nogil blocks. Second, Cython can +conditionally acquire/release +the GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for +external C code +contains more detail on how to safely manage the GIL.

+

To conclude: use Cython's nogil annotation to assert that functions are safe for calling when the +GIL is unlocked, and with nogil to actually unlock the GIL and run those functions.

+

Numba

+

Like Cython, Numba is a "compiled Python." Where Cython works by +compiling a Python-like language to C/C++, Numba compiles Python bytecode directly to machine code +at runtime. Behavior is controlled with a special @jit decorator; calling a decorated function +first compiles it to machine code before running. Calling the function a second time re-uses that +machine code unless the argument types have changed.

+

Numba works best when a nopython=True argument is added to the @jit decorator; functions +compiled in nopython mode +avoid the CPython API and have performance comparable to C. Further, adding nogil=True to the +@jit decorator unlocks the GIL while that function is running. Note that nogil and nopython +are separate arguments; while it is necessary for code to be compiled in nopython mode in order to +release the lock, the GIL will remain locked if nogil=False (the default).

+

Let's repeat the same experiment, this time using Numba instead of Cython:

+
# The `int` type annotation is only for humans and is ignored
# by Numba.
@jit(nopython=True, nogil=True)
def numba_nogil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Run using `nopython` mode to receive a performance boost,
# but GIL remains locked due to `nogil=False` by default.
@jit(nopython=True)
def numba_gil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Call each function once to force compilation; we don't want
# the timing statistics to include how long it takes to compile.
numba_nogil(N)
numba_gil(N);
+

We'll perform the same tests as above; first, figure out how long it takes the function to run:

+
%%time
_ = numba_gil(N)
+
+

CPU times: user 253 ms, sys: 258 µs, total: 253 ms +Wall time: 251 ms

+
+

Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be +effectively identical after compilation. +

When running two GIL-locked threads, the result (as expected) takes around twice as long to compute:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms +Wall time: 541 ms

+
+

But if the GIL-unlocking thread starts first, both threads run in parallel:

+
%%time
t1 = Thread(target=numba_nogil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms +Wall time: 279 ms

+
+

Just like Cython, starting the GIL-locked thread first leads to poor performance:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 524 ms, sys: 0 ns, total: 524 ms +Wall time: 522 ms

+
+

Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; +recursively calling @jit(nogil=True) functions is perfectly safe:

+
from numba import jit

@jit(nopython=True, nogil=True)
def numba_recurse(n: int) -> int:
if n <= 0:
return 0

return numba_recurse(n - 1)

numba_recurse(2);
+

Conclusion

+

Before finishing, it's important to address pain points that will show up if these techniques are +used in a more realistic project:

+

First, code running in a GIL-free context will likely also need non-trivial data structures; +GIL-free functions aren't useful if they're constantly interacting with Python objects whose access +requires the GIL. Cython provides +extension types and Numba +provides a @jitclass decorator to +address this need.

+

Second, building and distributing applications that make use of Cython/Numba can be complicated. +Cython packages require running the compiler, (potentially) linking/packaging external dependencies, +and distributing a binary wheel. Numba is generally simpler because the code being distributed is +pure Python, but can be tricky since errors aren't detected until runtime.

+

Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba +provide tools to directly manage the GIL when appropriate. This enables true parallelism (not just +concurrency) that is impossible in vanilla Python.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Binary format shootout]]> + https://speice.io/2019/09/binary-format-shootout + + 2019-09-28T12:00:00.000Z + + I've found that in many personal projects, +analysis paralysis is particularly deadly. +Making good decisions in the beginning avoids pain and suffering later; if extra research prevents +future problems, I'm happy to continue procrastinating researching indefinitely.

+

So let's say you're in need of a binary serialization format. Data will be going over the network, +not just in memory, so having a schema document and code generation is a must. Performance is +crucial, so formats that support zero-copy de/serialization are given priority. And the more +languages supported, the better; I use Rust, but can't predict what other languages this could +interact with.

+

Given these requirements, the candidates I could find were:

+
    +
  1. Cap'n Proto has been around the longest, and is the most established
  2. +
  3. Flatbuffers is the newest, and claims to have a simpler +encoding
  4. +
  5. Simple Binary Encoding has the simplest +encoding, but the Rust implementation is unmaintained
  6. +
+

Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably +fast, and polyglot support. But how do you actually pick one? It's impossible to know what issues +will follow that choice, so I tend to avoid commitment until the last possible moment.

+

Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a +small proof-of-concept system in each format and pit them against each other. All code can be found +in the repository for this post.

+

We'll discuss more in detail, but a quick preview of the results:

+
    +
  • Cap'n Proto: Theoretically performs incredibly well, the implementation had issues
  • +
  • Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises
  • +
  • SBE: Best median and worst-case performance, but the message structure has a limited feature set
  • +
+

Prologue: Binary Parsing with Nom

+

Our benchmark system will be a simple data processor; given depth-of-book market data from +IEX, serialize each message into the schema +format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. +This test isn't complex, but is representative of the project I need a binary format for.

+

But before we make it to that point, we have to actually read in the market data. To do so, I'm +using a library called nom. Version 5.0 was recently released and +brought some big changes, so this was an opportunity to build a non-trivial program and get +familiar.

+

If you don't already know about nom, it's a "parser generator". By combining different smaller +parsers, you can assemble a parser to handle complex structures without writing tedious code by +hand. For example, when parsing +PCAP files:

+
   0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
0 | Block Type = 0x00000006 |
+---------------------------------------------------------------+
4 | Block Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Interface ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 | Timestamp (High) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 | Timestamp (Low) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 | Captured Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 | Packet Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet Data |
| ... |
+

...you can build a parser in nom that looks like +this:

+
const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];
pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> {
let (
remaining,
(
block_type,
block_len,
interface_id,
timestamp_high,
timestamp_low,
captured_len,
packet_len,
),
) = tuple((
tag(ENHANCED_PACKET),
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
))(input)?;

let (remaining, packet_data) = take(captured_len)(remaining)?;
Ok((remaining, packet_data))
}
+

While this example isn't too interesting, more complex formats (like IEX market data) are where +nom really shines.

+

Ultimately, because the nom code in this shootout was the same for all formats, we're not too +interested in its performance. Still, it's worth mentioning that building the market data parser was +actually fun; I didn't have to write tons of boring code by hand.

+

Cap'n Proto

+

Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried +because of how long it has supported Rust (thanks to dwrensha for +maintaining the Rust port since +2014!). However, I had a ton +of performance concerns once I started using it.

+

To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the +heap to hold the message content, but because builders +can't be re-used, we have to allocate a +new buffer for every single message. I was able to work around this with a +special builder +that could re-use the buffer, but it required reading through Cap'n Proto's +benchmarks +to find an example, and used +std::mem::transmute to bypass Rust's borrow +checker.

+

The process of reading messages was better, but still had issues. Cap'n Proto has two message +encodings: a "packed" representation, and an +"unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into +before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't +able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n +Proto shines; its main selling point is that there's no decoding step. +However, accomplishing zero-copy deserialization required code in the private API +(since fixed), and we allocate a vector on +every read for the segment table.

+

In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too +many issues for me to feel comfortable using it long-term.

+

Flatbuffers

+

This is the new kid on the block. After a +first attempt didn't pan out, official support +was recently launched. Flatbuffers intends to +address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The +difference is that Flatbuffers claims to have a simpler wire format and +more flexibility.

+

On the whole, I enjoyed using Flatbuffers; the tooling is +nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, +there were still some issues.

+

First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats +like the following:

+
table Message {
symbol: string;
}
table MultiMessage {
messages:[Message];
}
+

We want to create a MultiMessage which contains a vector of Message, and each Message itself +contains a vector (the string type). I was able to work around this by +caching Message elements +in a SmallVec before building the final MultiMessage, but it was a painful process that I +believe contributed to poor serialization performance.

+

Second, streaming support in Flatbuffers seems to be something of an +afterthought. Where Cap'n Proto in Rust handles +reading messages from a stream as part of the API, Flatbuffers just sticks a u32 at the front of +each message to indicate the size. Not specifically a problem, but calculating message size without +that tag is nigh on impossible.

+

Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform +well.

+

Simple Binary Encoding

+

Support for SBE was added by the author of one of my favorite +Rust blog posts. +I've talked previously about how important +variance is in high-performance systems, so it was encouraging to read about a format that +directly addressed my +concerns. SBE has by far the simplest binary format, but it does make some tradeoffs.

+

Both Cap'n Proto and Flatbuffers use message offsets +to handle variable-length data, unions, and various +other features. In contrast, messages in SBE are essentially +just structs; +variable-length data is supported, but there's no union type.

+

As mentioned in the beginning, the Rust port of SBE works well, but is +essentially unmaintained. +However, if you don't need union types, and can accept that schemas are XML documents, it's still +worth using. SBE's implementation had the best streaming support of all formats I tested, and +doesn't trigger allocation during de/serialization.

+

Results

+

After building a test harness +for +each +format, it was +time to actually take them for a spin. I used +this script to run +the benchmarks, and the raw results are +here. All data reported +below is the average of 10 runs on a single day of IEX data. Results were validated to make sure +that each format parsed the data correctly.

+

Serialization

+

This test measures, on a +per-message basis, +how long it takes to serialize the IEX message into the desired format and write to a pre-allocated +buffer.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed413ns1751ns2943ns14.80s
Cap'n Proto Unpacked273ns1828ns2836ns10.65s
Flatbuffers355ns2185ns3497ns14.31s
SBE91ns1535ns2423ns3.91s
+

Deserialization

+

This test measures, on a +per-message basis, +how long it takes to read the previously-serialized message and perform some basic aggregation. The +aggregation code is the same for each format, so any performance differences are due solely to the +format implementation.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed539ns1216ns2599ns18.92s
Cap'n Proto Unpacked366ns737ns1583ns12.32s
Flatbuffers173ns421ns1007ns6.00s
SBE116ns286ns659ns4.05s
+

Conclusion

+

Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" +type isn't important to me, I can be confident that SBE best addresses my needs.

+

While SBE was the fastest in terms of both median and worst-case performance, its worst case +performance was proportionately far higher than any other format. It seems to be that +de/serialization time scales with message size, but I'll need to do some more research to understand +what exactly is going on.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[On building high performance systems]]> + https://speice.io/2019/06/high-performance-systems + + 2019-07-01T12:00:00.000Z + + Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is +made up of people who have access to secret techniques mortal developers could only dream of. There +had to be some secret art that could only be learned if one had an appropriately tragic backstory.

+

Kung Fu fight

+
+

How I assumed HFT people learn their secret techniques

+
+

How else do you explain people working on systems that complete the round trip of market data in to +orders out (a.k.a. tick-to-trade) consistently within +750-800 nanoseconds? In roughly the time it takes a +computer to access +main memory 8 times, +trading systems are capable of reading the market data packets, deciding what orders to send, doing +risk checks, creating new packets for exchange-specific protocols, and putting those packets on the +wire.

+

Having now worked in the trading industry, I can confirm the developers aren't super-human; I've +made some simple mistakes at the very least. Instead, what shows up in public discussions is that +philosophy, not technique, separates high-performance systems from everything else. +Performance-critical systems don't rely on "this one cool C++ optimization trick" to make code fast +(though micro-optimizations have their place); there's a lot more to worry about than just the code +written for the project.

+

The framework I'd propose is this: If you want to build high-performance systems, focus first on +reducing performance variance (reducing the gap between the fastest and slowest runs of the same +code), and only look at average latency once variance is at an acceptable level.

+

Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20 +seconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes +a full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a +week is the same in each situation, but you're painfully aware of that minute when it happens. When +it comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds +doesn't mean much if there's a 100ms difference between your fastest and slowest runs. When +performance matters, you need to respond quickly every time, not just in aggregate. +High-performance systems should first optimize for time variance. Once you're consistent at the time +scale you care about, then focus on improving average time.

+

This focus on variance shows up all the time in industry too (emphasis added in all quotes below):

+
    +
  • +

    In marketing materials for +NASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability +is highlighted in addition to instantaneous metrics:

    +
    +

    Able to consistently sustain an order rate of over 100,000 orders per second at sub-40 +microsecond average latency

    +
    +
  • +
  • +

    The Aeron message bus has this to say about performance:

    +
    +

    Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and +most predictable latency possible of any messaging system

    +
    +
  • +
  • +

    The company PolySync, which is working on autonomous vehicles, +mentions why they picked their +specific messaging format:

    +
    +

    In general, high performance is almost always desirable for serialization. But in the world of +autonomous vehicles, steady timing performance is even more important than peak throughput. +This is because safe operation is sensitive to timing outliers. Nobody wants the system that +decides when to slam on the brakes to occasionally take 100 times longer than usual to encode +its commands.

    +
    +
  • +
  • +

    Solarflare, which makes highly-specialized network hardware, points out +variance (jitter) as a big concern for +electronic trading:

    +
    +

    The high stakes world of electronic trading, investment banks, market makers, hedge funds and +exchanges demand the lowest possible latency and jitter while utilizing the highest +bandwidth and return on their investment.

    +
    +
  • +
+

And to further clarify: we're not discussing total run-time, but variance of total run-time. There +are situations where it's not reasonably possible to make things faster, and you'd much rather be +consistent. For example, trading firms use +wireless networks because +the speed of light through air is faster than through fiber-optic cables. There's still at absolute +minimum a ~33.76 millisecond delay required to send data between, +say, +Chicago and Tokyo. +If a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a +trade occurs, there's a physical limit to how long that will take. In this situation, the focus is +on keeping variance of additional processing to a minimum, since speed of light is the limiting +factor.

+

So how does one go about looking for and eliminating performance variance? To tell the truth, I +don't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep +understanding of the entire technology stack, and (B) actually measuring system performance (though +(C) watching a lot of CppCon videos for +inspiration never hurt). Even then, every project cares about performance to a different degree; you +may need to build an entire +replica production system to +accurately benchmark at nanosecond precision, or you may be content to simply +avoid garbage collection in +your Java code.

+

Even though everyone has different needs, there are still common things to look for when trying to +isolate and eliminate variance. In no particular order, these are my focus areas when thinking about +high-performance systems:

+

Update 2019-09-21: Added notes on isolcpus and systemd affinity.

+

Language-specific

+

Garbage Collection: How often does garbage collection happen? When is it triggered? What are the +impacts?

+
    +
  • In Python, individual objects are collected +if the reference count reaches 0, and each generation is collected if +num_alloc - num_dealloc > gc_threshold whenever an allocation happens. The GIL is acquired for +the duration of generational collection.
  • +
  • Java has +many +different +collection +algorithms +to choose from, each with different characteristics. The default algorithms (Parallel GC in Java +8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms +(ZGC and +Shenandoah) are designed to keep "stop the +world" to a minimum by doing collection work in parallel.
  • +
+

Allocation: Every language has a different way of interacting with "heap" memory, but the +principle is the same: running the allocator to allocate/deallocate memory takes time that can often +be put to better use. Understanding when your language interacts with the allocator is crucial, and +not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java +does (meaning potential GC pauses). Take time to understand heap behavior (I made a +a guide for Rust), and look into alternative +allocators (jemalloc, +tcmalloc) that might run faster than the +operating system default.

+

Data Layout: How your data is arranged in memory matters; +data-oriented design and +cache locality can have huge +impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have +guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't +make. Cachegrind and kernel +perf counters are both great for understanding +how performance relates to memory layout.

+

Just-In-Time Compilation: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are +great because they optimize your program for how it's actually being used, rather than how a +compiler expects it to be used. However, there's a variance problem if the program stops executing +while waiting for translation from VM bytecode to native code. As a remedy, many languages support +ahead-of-time compilation in addition to the JIT versions +(CoreRT in C# and GraalVM in Java). +On the other hand, LLVM supports +Profile Guided Optimization, +which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing +apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT +compiler kicked in.

+

Programming Tricks: These won't make or break performance, but can be useful in specific +circumstances. For example, C++ can use +templates instead of branches +in critical sections.

+

Kernel

+

Code you wrote is almost certainly not the only code running on your hardware. There are many ways +the operating system interacts with your program, from interrupts to system calls, that are +important to watch for. These are written from a Linux perspective, but Windows does typically have +equivalent functionality.

+

Scheduling: The kernel is normally free to schedule any process on any core, so it's important +to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, +limit the CPU cores that non-critical processes are allowed to run on by excluding cores from +scheduling +(isolcpus +kernel command-line option), or by setting the init process CPU affinity +(systemd example). Second, set critical processes +to run on the isolated cores by setting the +processor affinity using +taskset. Finally, use +NO_HZ or +chrt to disable scheduling interrupts. Turning off +hyper-threading is also likely beneficial.

+

System calls: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long +the I/O operation takes, these all trigger expensive +system calls (syscalls). To handle these, the CPU must +context switch to the kernel, let the kernel +operation complete, then context switch back to your program. We'd rather keep these +to a minimum (see +timestamp 18:20). Strace is your friend for understanding when +and where syscalls happen.

+

Signal Handling: Far less likely to be an issue, but signals do trigger a context switch if your +code has a handler registered. This will be highly dependent on the application, but you can +block signals +if it's an issue.

+

Interrupts: System interrupts are how devices connected to your computer notify the CPU that +something has happened. The CPU will then choose a processor core to pause and context switch to the +OS to handle the interrupt. Make sure that +SMP affinity is +set so that interrupts are handled on a CPU core not running the program you care about.

+

NUMA: While NUMA is good at making +multi-cell systems transparent, there are variance implications; if the kernel moves a process +across nodes, future memory accesses must wait for the controller on the original node. Use +numactl to handle memory-/cpu-cell pinning so this doesn't +happen.

+

Hardware

+

CPU Pipelining/Speculation: Speculative execution in modern processors gave us vulnerabilities +like Spectre, but it also gave us performance improvements like +branch prediction. And if the CPU mis-speculates +your code, there's variance associated with rewind and replay. While the compiler knows a lot about +how your CPU pipelines instructions, code can be +structured to help the branch +predictor.

+

Paging: For most systems, virtual memory is incredible. Applications live in their own worlds, +and the CPU/MMU figures out the details. +However, there's a variance penalty associated with memory paging and caching; if you access more +memory pages than the TLB can store, +you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an +issue, but using huge pages can +reduce TLB burdens. Alternately, running applications in a hypervisor like +Jailhouse allows one to skip virtual memory entirely, but +this is probably more work than the benefits are worth.

+

Network Interfaces: When more than one computer is involved, variance can go up dramatically. +Tuning kernel +network parameters may be +helpful, but modern systems more frequently opt to skip the kernel altogether with a technique +called kernel bypass. This typically requires +specialized hardware and drivers, but even industries like +telecom are +finding the benefits.

+

Networks

+

Routing: There's a reason financial firms are willing to pay +millions of euros +for rights to a small plot of land - having a straight-line connection from point A to point B means +the path their data takes is the shortest possible. In contrast, there are currently 6 computers in +between me and Google, but that may change at any moment if my ISP realizes a +more efficient route is available. Whether +it's using +research-quality equipment +for shortwave radio, or just making sure there's no data inadvertently going between data centers, +routing matters.

+

Protocol: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, +and congestion control all built in. But these attributes make the most sense when networking +infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the +setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may +make sense in these contexts as it avoids the chatter needed to track connection state, and +gap-fill +strategies +can handle the rest.

+

Switching: Many routers/switches handle packets using "store-and-forward" behavior: wait for the +whole packet, validate checksums, and then send to the next device. In variance terms, the time +needed to move data between two nodes is proportional to the size of that data; the switch must +"store" all data before it can calculate checksums and "forward" to the next node. With +"cut-through" +designs, switches will begin forwarding data as soon as they know where the destination is, +checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter +the size.

+

Final Thoughts

+

High-performance systems, regardless of industry, are not magical. They do require extreme precision +and attention to detail, but they're designed, built, and operated by regular people, using a lot of +tools that are publicly available. Interested in seeing how context switching affects performance of +your benchmarks? taskset should be installed in all modern Linux distributions, and can be used to +make sure the OS never migrates your process. Curious how often garbage collection triggers during a +crucial operation? Your language of choice will typically expose details of its operations +(Python, +Java). +Want to know how hard your program is stressing the TLB? Use perf record and look for +dtlb_load_misses.miss_causes_a_walk.

+

Two final guiding questions, then: first, before attempting to apply some of the technology above to +your own systems, can you first identify +where/when you care about "high-performance"? As an +example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable +effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are +they being designed in a way that's actually helpful? Tools like +Criterion (also in +Rust) and Google's +Benchmark output not only average run time, but variance as +well; your benchmarking environment is subject to the same concerns your production environment is.

+

Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. +Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate +it; once that's at an acceptable level, then optimize for speed.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Making bread]]> + https://speice.io/2019/05/making-bread + + 2019-05-03T12:00:00.000Z + + Having recently started my "gardening leave" between positions, I have some more personal time +available. I'm planning to stay productive, contributing to some open-source projects, but it also +occurred to me that despite talking about bread pics, this +blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites +and Bytes"?

+

Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on +some lighter material. I recently learned two critically important lessons: first, the temperature +of the dough when you put the yeast in makes a huge difference.

+

Previously, when I wasn't paying attention to dough temperature:

+

Whole weat dough

+

Compared with what happens when I put the dough in the microwave for a defrost cycle because the +water I used wasn't warm enough:

+

White dough

+

I mean, just look at the bubbles!

+

White dough with bubbles

+

After shaping the dough, I've got two loaves ready:

+

Shaped loaves

+

Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from +drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the +bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot +to add the water and learned my second lesson: never add room-temperature water to a glass dish +that's currently at 500 degrees.

+

Shattered glass dish

+

Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected +to be doing during my garden leave.

+

In the end, the bread crust wasn't great, but the bread itself turned out pretty alright:

+

Baked bread

+

I've been writing a lot more during this break, so I'm looking forward to sharing that in the +future. In the mean-time, I'm planning on making a sandwich.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Allocations in Rust: Summary]]> + https://speice.io/2019/02/summary + + 2019-02-09T12:00:00.000Z + + While there's a lot of interesting detail captured in this series, it's often helpful to have a +document that answers some "yes/no" questions. You may not care about what an Iterator looks like +in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust +will prioritize the fastest behavior it can, here are the rules for each memory type:

+

Global Allocation:

+
    +
  • const is a fixed value; the compiler is allowed to copy it wherever useful.
  • +
  • static is a fixed reference; the compiler will guarantee it is unique.
  • +
+

Stack Allocation:

+
    +
  • Everything not using a smart pointer will be allocated on the stack.
  • +
  • Structs, enums, iterators, arrays, and closures are all stack allocated.
  • +
  • Cell types (RefCell) behave like smart pointers, but are stack-allocated.
  • +
  • Inlining (#[inline]) will not affect allocation behavior for better or worse.
  • +
  • Types that are marked Copy are guaranteed to have their contents stack-allocated.
  • +
+

Heap Allocation:

+
    +
  • Smart pointers (Box, Rc, Mutex, etc.) allocate their contents in heap memory.
  • +
  • Collections (HashMap, Vec, String, etc.) allocate their contents in heap memory.
  • +
  • Some smart pointers in the standard library have counterparts in other crates that don't need heap +memory. If possible, use those.
  • +
+

Container Sizes in Rust

+

-- Raph Levien

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Allocations in Rust: Compiler optimizations]]> + https://speice.io/2019/02/08/compiler-optimizations + + 2019-02-08T12:00:00.000Z + + Up to this point, we've been discussing memory usage in the Rust language by focusing on simple +rules that are mostly right for small chunks of code. We've spent time showing how those rules work +themselves out in practice, and become familiar with reading the assembly code needed to see each +memory type (global, stack, heap) in action.

+

Throughout the series so far, we've put a handicap on the code. In the name of consistent and +understandable results, we've asked the compiler to pretty please leave the training wheels on. Now +is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the +Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them +do their job.

+

Similar to +"What Has My Compiler Done For Me Lately?", we're +focusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll +still be looking at assembly code to understand what's going on, but it's important to mention +again: please use automated tools like alloc-counter to +double-check memory behavior if it's something you care about. It's far too easy to mis-read +assembly in large code sections, you should always verify behavior if you care about memory usage.

+

The guiding principal as we move forward is this: optimizing compilers won't produce worse programs +than we started with. There won't be any situations where stack allocations get moved to heap +allocations. There will, however, be an opera of optimization.

+

Update 2019-02-10: When debugging a +related issue, it was discovered that the +original code worked because LLVM optimized out the entire function, rather than just the allocation +segments. The code has been updated with proper use of +read_volatile, and a previous section +on vector capacity has been removed.

+

The Case of the Disappearing Box

+

Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently +short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the +stack instead! The way this interacts with #[inline] attributes is a bit opaque, but the important +part is that LLVM can sometimes do better than the baseline Rust language:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

pub fn cmp(x: u32) {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// The compiler is able to see through the constant `Box`
// and directly compare `x` to 24 - assembly line 73
let y = Box::new(24);
let equals = x == *y;

// This call to drop is eliminated
drop(y);

// Need to mark the comparison result as volatile so that
// LLVM doesn't strip out all the code. If `y` is marked
// volatile instead, allocation will be forced.
unsafe { std::ptr::read_volatile(&equals) };

// Turn off panicking, as there are some deallocations
// when we exit main.
DO_PANIC.store(false, Ordering::SeqCst);
}

fn main() {
cmp(12)
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- Compiler Explorer

+

-- Rust Playground

+

Dr. Array or: how I learned to love the optimizer

+

Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping +out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if +you're not careful, they can make your benchmarks look +impossibly good. In Rust, the +black_box function (implemented in both +libtest and +criterion) will tell the compiler +to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up +running programs that previously caused errors:

+
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

pub fn main() {
// Normally this blows up because we can't reserve size on stack
// for the `EightM` struct. But because the compiler notices we
// never do anything with `_x`, it optimizes out the stack storage
// and the program completes successfully.
let _x = EightM::default();
}
+

-- Compiler Explorer

+

-- Rust Playground

]]>
+
+ + <![CDATA[Allocations in Rust: Dynamic memory]]> + https://speice.io/2019/02/a-heaping-helping + + 2019-02-07T12:00:00.000Z + + Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and +some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how +the language uses dynamic memory (also referred to as the heap) is a system called ownership. +And as the docs mention, ownership +is Rust's most unique feature.

+

The heap is used in two situations; when the compiler is unable to predict either the total size of +memory needed, or how long the memory is needed for, it allocates space in the heap.

+

This happens +pretty frequently; if you want to download the Google home page, you won't know how large it is +until your program runs. And when you're finished with Google, we deallocate the memory so it can be +used to store other webpages. If you're interested in a slightly longer explanation of the heap, +check out +The Stack and the Heap +in Rust's documentation.

+

We won't go into detail on how the heap is managed; the +ownership documentation does a +phenomenal job explaining both the "why" and "how" of memory management. Instead, we're going to +focus on understanding "when" heap allocations occur in Rust.

+

To start off, take a guess for how many allocations happen in the program below:

+
fn main() {}
+

It's obviously a trick question; while no heap allocations occur as a result of that code, the setup +needed to call main does allocate on the heap. Here's a way to show it:

+
#![feature(integer_atomics)]
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicU64, Ordering};

static ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);

struct CountingAllocator;

unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout);
}
}

#[global_allocator]
static A: CountingAllocator = CountingAllocator;

fn main() {
let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst);
println!("There were {} allocations before calling main!", x);
}
+

-- +Rust Playground

+

As of the time of writing, there are five allocations that happen before main is ever called.

+

But when we want to understand more practically where heap allocation happens, we'll follow this +guide:

+
    +
  • Smart pointers hold their contents in the heap
  • +
  • Collections are smart pointers for many objects at a time, and reallocate when they need to grow
  • +
+

Finally, there are two "addendum" issues that are important to address when discussing Rust and the +heap:

+
    +
  • Non-heap alternatives to many standard library types are available.
  • +
  • Special allocators to track memory behavior should be used to benchmark code.
  • +
+

Smart pointers

+

The first thing to note are the "smart pointer" types. When you have data that must outlive the +scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these +types.

+

The term smart pointer comes from C++, and while it's +closely linked to a general design pattern of +"Resource Acquisition Is Initialization", we'll +use it here specifically to describe objects that are responsible for managing ownership of data +allocated on the heap. The smart pointers available in the alloc crate should look mostly +familiar:

+ +

The standard library also defines some smart pointers to manage +heap objects, though more than can be covered here. Some examples are:

+ +

Finally, there is one "gotcha": cell types +(like RefCell) look and behave +similarly, but don't involve heap allocation. The +core::cell docs have more information.

+

When a smart pointer is created, the data it is given is placed in heap memory and the location of +that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to +deallocate that memory (when a Box has +gone out of scope or a reference count +goes to zero), the heap space is reclaimed. We can +prove these types use heap memory by looking at code:

+
use std::rc::Rc;
use std::sync::Arc;
use std::borrow::Cow;

pub fn my_box() {
// Drop at assembly line 1640
Box::new(0);
}

pub fn my_rc() {
// Drop at assembly line 1650
Rc::new(0);
}

pub fn my_arc() {
// Drop at assembly line 1660
Arc::new(0);
}

pub fn my_cow() {
// Drop at assembly line 1672
Cow::from("drop");
}
+

-- Compiler Explorer

+

Collections

+

Collection types use heap memory because their contents have dynamic size; they will request more +memory when needed, and can +release memory when it's +no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In +a way, collections are smart pointers for many objects at a time. Common types that fall under +this umbrella are Vec, +HashMap, and +String (not +str).

+

While collections store the objects they own in heap memory, creating new collections will not +allocate on the heap. This is a bit weird; if we call Vec::new(), the assembly shows a +corresponding call to real_drop_in_place:

+
pub fn my_vec() {
// Drop in place at line 481
Vec::<u8>::new();
}
+

-- Compiler Explorer

+

But because the vector has no elements to manage, no calls to the allocator will ever be dispatched:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// Interesting bit happens here
let x: Vec<u8> = Vec::new();
drop(x);

// Turn panicking back off, some deallocations occur
// after main as well.
DO_PANIC.store(false, Ordering::SeqCst);
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- +Rust Playground

+

Other standard library types follow the same behavior; make sure to check out +HashMap::new(), +and String::new().

+

Heap Alternatives

+

While it is a bit strange to speak of the stack after spending time with the heap, it's worth +pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by +other crates. If you have need of the functionality, but want to avoid allocating, there are +typically alternatives available.

+

When it comes to some standard library smart pointers +(RwLock and +Mutex), stack-based alternatives are +provided in crates like parking_lot and +spin. You can check out +lock_api::RwLock, +lock_api::Mutex, and +spin::Once if you're in need +of synchronization primitives.

+

thread_id may be necessary if you're implementing an allocator +because thread::current().id() uses a +thread_local! structure +that needs heap allocation.

+

Tracing Allocators

+

When writing performance-sensitive code, there's no alternative to measuring your code. If you +didn't write a benchmark, +you don't care about it's performance +You should never rely on your instincts when +a microsecond is an eternity.

+

Similarly, there's great work going on in Rust with allocators that keep track of what they're doing +(like alloc_counter). When it comes to tracking heap +behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard +against future issues.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Allocations in Rust: Fixed memory]]> + https://speice.io/2019/02/stacking-up + + 2019-02-06T12:00:00.000Z + + const and static are perfectly fine, but it's relatively rare that we know at compile-time about +either values or references that will be the same for the duration of our program. Put another way, +it's not often the case that either you or your compiler knows how much memory your entire program +will ever need.

+

However, there are still some optimizations the compiler can do if it knows how much memory +individual functions will need. Specifically, the compiler can make use of "stack" memory (as +opposed to "heap" memory) which can be managed far faster in both the short- and long-term.

+

When requesting memory, the push instruction +can typically complete in 1 or 2 cycles (<1ns +on modern CPUs). Contrast that to heap memory which requires an allocator (specialized +software to track what memory is in use) to reserve space. When you're finished with stack memory, +the pop instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory +fragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have +been used to design allocators:

+ +

But no matter how fast your allocator is, the principle remains: the fastest allocator is the one +you never use. As such, we're not going to discuss how exactly the +push and pop instructions work, but +we'll focus instead on the conditions that enable the Rust compiler to use faster stack-based +allocation for variables.

+

So, how do we know when Rust will or will not use stack allocation for objects we create? +Looking at other languages, it's often easy to delineate between stack and heap. Managed memory +languages (Python, Java, +C#) place +everything on the heap. JIT compilers (PyPy, +HotSpot) may optimize +some heap allocations away, but you should never assume it will happen. C makes things clear with +calls to special functions (like malloc(3)) needed to access +heap memory. Old C++ has the new keyword, though +modern C++/C++11 is more complicated with RAII.

+

For Rust, we can summarize as follows: stack allocation will be used for everything that doesn't +involve "smart pointers" and collections. We'll skip over a precise definition of the term "smart +pointer" for now, and instead discuss what we should watch for to understand when stack and heap +memory regions are used:

+
    +
  1. +

    Stack manipulation instructions (push, pop, and add/sub of the rsp register) indicate +allocation of stack memory:

    +
    pub fn stack_alloc(x: u32) -> u32 {
    // Space for `y` is allocated by subtracting from `rsp`,
    // and then populated
    let y = [1u8, 2, 3, 4];
    // Space for `y` is deallocated by adding back to `rsp`
    x
    }
    +

    -- Compiler Explorer

    +
  2. +
  3. +

    Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch +for call core::ptr::real_drop_in_place, and infer that a heap allocation happened in the recent +past:

    +
    pub fn heap_alloc(x: usize) -> usize {
    // Space for elements in a vector has to be allocated
    // on the heap, and is then de-allocated once the
    // vector goes out of scope
    let y: Vec<u8> = Vec::with_capacity(x);
    x
    }
    +

    -- Compiler Explorer (real_drop_in_place happens on line 1317) +Note: While the +Drop trait is +called for stack-allocated objects, +the Rust standard library only defines Drop implementations for types that involve heap +allocation.

    +
  4. +
  5. +

    If you don't want to inspect the assembly, use a custom allocator that's able to track and alert +when heap allocations occur. Crates like +alloc_counter are designed for exactly this purpose.

    +
  6. +
+

With all that in mind, let's talk about situations in which we're guaranteed to use stack memory:

+
    +
  • Structs are created on the stack.
  • +
  • Function arguments are passed on the stack, meaning the +#[inline] attribute will +not change the memory region used.
  • +
  • Enums and unions are stack-allocated.
  • +
  • Arrays are always stack-allocated.
  • +
  • Closures capture their arguments on the stack.
  • +
  • Generics will use stack allocation, even with dynamic dispatch.
  • +
  • Copy types are guaranteed to be +stack-allocated, and copying them will be done in stack memory.
  • +
  • Iterators in the standard library are +stack-allocated even when iterating over heap-based collections.
  • +
+

Structs

+

The simplest case comes first. When creating vanilla struct objects, we use stack memory to hold +their contents:

+
struct Point {
x: u64,
y: u64,
}

struct Line {
a: Point,
b: Point,
}

pub fn make_line() {
// `origin` is stored in the first 16 bytes of memory
// starting at location `rsp`
let origin = Point { x: 0, y: 0 };
// `point` makes up the next 16 bytes of memory
let point = Point { x: 1, y: 2 };

// When creating `ray`, we just move the content out of
// `origin` and `point` into the next 32 bytes of memory
let ray = Line { a: origin, b: point };
}
+

-- Compiler Explorer

+

Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the +sub rsp, 64 instruction indicates we're still working with the stack.

+

Function arguments

+

Have you ever wondered how functions communicate with each other? Like, once the variables are given +to you, everything's fine. But how do you "give" those variables to another function? How do you get +the results back afterward? The answer: the compiler arranges memory and assembly instructions using +a pre-determined calling convention. This +convention governs the rules around where arguments needed by a function will be located (either in +memory offsets relative to the stack pointer rsp, or in other registers), and where the results +can be found once the function has finished. And when multiple languages agree on what the calling +conventions are, you can do things like having Go call Rust code!

+

Put simply: it's the compiler's job to figure out how to call other functions, and you can assume +that the compiler is good at its job.

+

We can see this in action using a simple example:

+
struct Point {
x: i64,
y: i64,
}

// We use integer division operations to keep
// the assembly clean, understanding the result
// isn't accurate.
fn distance(a: &Point, b: &Point) -> i64 {
// Immediately subtract from `rsp` the bytes needed
// to hold all the intermediate results - this is
// the stack allocation step

// The compiler used the `rdi` and `rsi` registers
// to pass our arguments, so read them in
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

// Do the actual math work
let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared

// Our final result will be stored in the `rax` register
// so that our caller knows where to retrieve it.
// Finally, add back to `rsp` the stack memory that is
// now ready to be used by other functions.
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

As a consequence of function arguments never using heap memory, we can also infer that functions +using the #[inline] attributes also do not heap allocate. But better than inferring, we can look +at the assembly to prove it:

+
struct Point {
x: i64,
y: i64,
}

// Note that there is no `distance` function in the assembly output,
// and the total line count goes from 229 with inlining off
// to 306 with inline on. Even still, no heap allocations occur.
#[inline(always)]
fn distance(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (a.x - b.x) * (a.x - b.x);
let y_pow = (a.y - b.y) * (a.y - b.y);
let squared = x_pow + y_pow;
squared / squared
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

Finally, passing by value (arguments with type +Copy) and passing by reference (either +moving ownership or passing a pointer) may have slightly different layouts in assembly, but will +still use either stack memory or CPU registers:

+
pub struct Point {
x: i64,
y: i64,
}

// Moving values
pub fn distance_moved(a: Point, b: Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}

// Borrowing values has two extra `mov` instructions on lines 21 and 22
pub fn distance_borrowed(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}
+

-- Compiler Explorer

+

Enums

+

If you've ever worried that wrapping your types in +Option or +Result would finally make them +large enough that Rust decides to use heap allocation instead, fear no longer: enum and union +types don't use heap allocation:

+
enum MyEnum {
Small(u8),
Large(u64)
}

struct MyStruct {
x: MyEnum,
y: MyEnum,
}

pub fn enum_compare() {
let x = MyEnum::Small(0);
let y = MyEnum::Large(0);

let z = MyStruct { x, y };

let opt = Option::Some(z);
}
+

-- Compiler Explorer

+

Because the size of an enum is the size of its largest element plus a flag, the compiler can +predict how much memory is used no matter which variant of an enum is currently stored in a +variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great +way to show this in assembly, so I'll instead point you to the +core::mem::size_of +documentation.

+

Arrays

+

The array type is guaranteed to be stack allocated, which is why the array size must be declared. +Interestingly enough, this can be used to cause safe Rust programs to crash:

+
// 256 bytes
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

// 8 kilobytes
#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

// 256 kilobytes
#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

// 8 megabytes - exceeds space typically provided for the stack,
// though the kernel can be instructed to allocate more.
// On Linux, you can check stack size using `ulimit -s`
#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

fn main() {
// Because we already have things in stack memory
// (like the current function call stack), allocating another
// eight megabytes of stack memory crashes the program
let _x = EightM::default();
}
+

-- +Rust Playground

+

There aren't any security implications of this (no memory corruption occurs), but it's good to note +that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to +overflow the stack.

+

Closures

+

Rules for how anonymous functions capture their arguments are typically language-specific. In Java, +Lambda Expressions are +actually objects created on the heap that capture local primitives by copying, and capture local +non-primitives as (final) references. +Python and +JavaScript +both bind everything by reference normally, but Python can also +capture values and JavaScript has +Arrow functions.

+

In Rust, arguments to closures are the same as arguments to other functions; closures are simply +functions that don't have a declared name. Some weird ordering of the stack may be required to +handle them, but it's the compiler's responsiblity to figure that out.

+

Each example below has the same effect, but a different assembly implementation. In the simplest +case, we immediately run a closure returned by another function. Because we don't store a reference +to the closure, the stack memory needed to store the captured values is contiguous:

+
fn my_func() -> impl FnOnce() {
let x = 24;
// Note that this closure in assembly looks exactly like
// any other function; you even use the `call` instruction
// to start running it.
move || { x; }
}

pub fn immediate() {
my_func()();
my_func()();
}
+

-- Compiler Explorer, 25 total assembly instructions

+

If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory +of the original function. Getting the details right is a bit harder, so the instruction count goes +up even though this code is functionally equivalent to our original example:

+
pub fn simple_reference() {
let x = my_func();
let y = my_func();
y();
x();
}
+

-- Compiler Explorer, 55 total assembly instructions

+

Even things like variable order can make a difference in instruction count:

+
pub fn complex() {
let x = my_func();
let y = my_func();
x();
y();
}
+

-- Compiler Explorer, 70 total assembly instructions

+

In every circumstance though, the compiler ensured that no heap allocations were necessary.

+

Generics

+

Traits in Rust come in two broad forms: static dispatch (monomorphization, impl Trait) and dynamic +dispatch (trait objects, dyn Trait). While dynamic dispatch is often associated with trait +objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:

+
trait GetInt {
fn get_int(&self) -> u64;
}

// vtable stored at section L__unnamed_1
struct WhyNotU8 {
x: u8
}
impl GetInt for WhyNotU8 {
fn get_int(&self) -> u64 {
self.x as u64
}
}

// vtable stored at section L__unnamed_2
struct ActualU64 {
x: u64
}
impl GetInt for ActualU64 {
fn get_int(&self) -> u64 {
self.x
}
}

// `&dyn` declares that we want to use dynamic dispatch
// rather than monomorphization, so there is only one
// `retrieve_int` function that shows up in the final assembly.
// If we used generics, there would be one implementation of
// `retrieve_int` for each type that implements `GetInt`.
pub fn retrieve_int(u: &dyn GetInt) {
// In the assembly, we just call an address given to us
// in the `rsi` register and hope that it was set up
// correctly when this function was invoked.
let x = u.get_int();
}

pub fn do_call() {
// Note that even though the vtable for `WhyNotU8` and
// `ActualU64` includes a pointer to
// `core::ptr::real_drop_in_place`, it is never invoked.
let a = WhyNotU8 { x: 0 };
let b = ActualU64 { x: 0 };

retrieve_int(&a);
retrieve_int(&b);
}
+

-- Compiler Explorer

+

It's hard to imagine practical situations where dynamic dispatch would be used for objects that +aren't heap allocated, but it technically can be done.

+

Copy types

+

Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs +go into detail far better than can +be addressed here, so I'll leave them to do the job. From a memory perspective though, their +guideline is reasonable: +if your type can implemement Copy, it should. +While there are potential speed tradeoffs to benchmark when discussing Copy (move semantics for +stack objects vs. copying stack pointers vs. copying stack structs), it's impossible for Copy +to introduce a heap allocation.

+

But why is this the case? Fundamentally, it's because the language controls what Copy means - +"the behavior of Copy is not overloadable" +because it's a marker trait. From there we'll note that a type +can implement Copy +if (and only if) its components implement Copy, and that +no heap-allocated types implement Copy. +Thus, assignments involving heap types are always move semantics, and new heap allocations won't +occur because of implicit operator behavior.

+
#[derive(Clone)]
struct Cloneable {
x: Box<u64>
}

// error[E0204]: the trait `Copy` may not be implemented for this type
#[derive(Copy, Clone)]
struct NotCopyable {
x: Box<u64>
}
+

-- Compiler Explorer

+

Iterators

+

In managed memory languages (like +Java), there's a subtle +difference between these two code samples:

+
public static int sum_for(List<Long> vals) {
long sum = 0;
// Regular for loop
for (int i = 0; i < vals.length; i++) {
sum += vals[i];
}
return sum;
}

public static int sum_foreach(List<Long> vals) {
long sum = 0;
// "Foreach" loop - uses iteration
for (Long l : vals) {
sum += l;
}
return sum;
}
+

In the sum_for function, nothing terribly interesting happens. In sum_foreach, an object of type +Iterator +is allocated on the heap, and will eventually be garbage-collected. This isn't a great design; +iterators are often transient objects that you need during a function and can discard once the +function ends. Sounds exactly like the issue stack-allocated objects address, no?

+

In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in +heap memory, but the iterator itself +(Iter) doesn't need to use the heap. In +each of the examples below we iterate over a collection, but never use heap allocation:

+
use std::collections::HashMap;
// There's a lot of assembly generated, but if you search in the text,
// there are no references to `real_drop_in_place` anywhere.

pub fn sum_vec(x: &Vec<u32>) {
let mut s = 0;
// Basic iteration over vectors doesn't need allocation
for y in x {
s += y;
}
}

pub fn sum_enumerate(x: &Vec<u32>) {
let mut s = 0;
// More complex iterators are just fine too
for (_i, y) in x.iter().enumerate() {
s += y;
}
}

pub fn sum_hm(x: &HashMap<u32, u32>) {
let mut s = 0;
// And it's not just Vec, all types will allocate the iterator
// on stack memory
for y in x.values() {
s += y;
}
}
+

-- Compiler Explorer

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Allocations in Rust: Global memory]]> + https://speice.io/2019/02/the-whole-world + + 2019-02-05T12:00:00.000Z + + The first memory type we'll look at is pretty special: when Rust can prove that a value is fixed +for the life of a program (const), and when a reference is unique for the life of a program +(static as a declaration, not +'static as a +lifetime), we can make use of global memory. This special section of data is embedded directly in +the program binary so that variables are ready to go once the program loads; no additional +computation is necessary.

+

Understanding the value/reference distinction is important for reasons we'll go into below, and +while the +full specification for +these two keywords is available, we'll take a hands-on approach to the topic.

+

const values

+

When a value is guaranteed to be unchanging in your program (where "value" may be scalars, +structs, etc.), you can declare it const. This tells the compiler that it's safe to treat the +value as never changing, and enables some interesting optimizations; not only is there no +initialization cost to creating the value (it is loaded at the same time as the executable parts of +your program), but the compiler can also copy the value around if it speeds up the code.

+

The points we need to address when talking about const are:

+
    +
  • Const values are stored in read-only memory - it's impossible to modify.
  • +
  • Values resulting from calling a const fn are materialized at compile-time.
  • +
  • The compiler may (or may not) copy const values wherever it chooses.
  • +
+

Read-Only

+

The first point is a bit strange - "read-only memory." +The Rust book +mentions in a couple places that using mut with constants is illegal, but it's also important to +demonstrate just how immutable they are. Typically in Rust you can use +interior mutability to modify +things that aren't declared mut. +RefCell provides an example of this +pattern in action:

+
use std::cell::RefCell;

fn my_mutator(cell: &RefCell<u8>) {
// Even though we're given an immutable reference,
// the `replace` method allows us to modify the inner value.
cell.replace(14);
}

fn main() {
let cell = RefCell::new(25);
// Prints out 25
println!("Cell: {:?}", cell);
my_mutator(&cell);
// Prints out 14
println!("Cell: {:?}", cell);
}
+

-- +Rust Playground

+

When const is involved though, interior mutability is impossible:

+
use std::cell::RefCell;

const CELL: RefCell<u8> = RefCell::new(25);

fn my_mutator(cell: &RefCell<u8>) {
cell.replace(14);
}

fn main() {
// First line prints 25 as expected
println!("Cell: {:?}", &CELL);
my_mutator(&CELL);
// Second line *still* prints 25
println!("Cell: {:?}", &CELL);
}
+

-- +Rust Playground

+

And a second example using Once:

+
use std::sync::Once;

const SURPRISE: Once = Once::new();

fn main() {
// This is how `Once` is supposed to be used
SURPRISE.call_once(|| println!("Initializing..."));
// Because `Once` is a `const` value, we never record it
// having been initialized the first time, and this closure
// will also execute.
SURPRISE.call_once(|| println!("Initializing again???"));
}
+

-- +Rust Playground

+

When the +const specification +refers to "rvalues", this +behavior is what they refer to. Clippy will treat this +as an error, but it's still something to be aware of.

+

Initialization

+

The next thing to mention is that const values are loaded into memory as part of your program +binary. Because of this, any const values declared in your program will be "realized" at +compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may +be able to prefetch the value), but that's it.

+
use std::cell::RefCell;

const CELL: RefCell<u32> = RefCell::new(24);

pub fn multiply(value: u32) -> u32 {
// CELL is stored at `.L__unnamed_1`
value * (*CELL.get_mut())
}
+

-- Compiler Explorer

+

The compiler creates one RefCell, uses it everywhere, and never needs to call the RefCell::new +function.

+

Copying

+

If it's helpful though, the compiler can choose to copy const values.

+
const FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// See assembly line 4 for the `mov edi, 1000` instruction
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// See assembly lines 22 and 29 for `mov edi, 1000` instructions
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

In this example, the FACTOR value is turned into the mov edi, 1000 instruction in both the +multiply and multiply_twice functions; the "1000" value is never "stored" anywhere, as it's +small enough to inline into the assembly instructions.

+

Finally, getting the address of a const value is possible, but not guaranteed to be unique +(because the compiler can choose to copy values). I was unable to get non-unique pointers in my +testing (even using different crates), but the specifications are clear enough: don't rely on +pointers to const values being consistent. To be frank, caring about locations for const values +is almost certainly a code smell.

+

static values

+

Static variables are related to const variables, but take a slightly different approach. When we +declare that a reference is unique for the life of a program, you have a static variable +(unrelated to the 'static lifetime). Because of the reference/value distinction with +const/static, static variables behave much more like typical "global" variables.

+

But to understand static, here's what we'll look at:

+
    +
  • static variables are globally unique locations in memory.
  • +
  • Like const, static variables are loaded at the same time as your program being read into +memory.
  • +
  • All static variables must implement the +Sync marker trait.
  • +
  • Interior mutability is safe and acceptable when using static variables.
  • +
+

Memory Uniqueness

+

The single biggest difference between const and static is the guarantees provided about +uniqueness. Where const variables may or may not be copied in code, static variables are +guarantee to be unique. If we take a previous const example and change it to static, the +difference should be clear:

+
static FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

Where previously there were plenty of references to multiplying by 1000, the new +assembly refers to FACTOR as a named memory location instead. No initialization work needs to be +done, but the compiler can no longer prove the value never changes during execution.

+

Initialization

+

Next, let's talk about initialization. The simplest case is initializing static variables with +either scalar or struct notation:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

static MY_STRUCT: MyStruct = MyStruct {
// You can even reference other statics
// declared later
x: MY_VAL
};

static MY_VAL: u32 = 24;

fn main() {
println!("Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

Things can get a bit weirder when using const fn though. In most cases, it just works:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

impl MyStruct {
const fn new() -> MyStruct {
MyStruct { x: 24 }
}
}

static MY_STRUCT: MyStruct = MyStruct::new();

fn main() {
println!("const fn Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

However, there's a caveat: you're currently not allowed to use const fn to initialize static +variables of types that aren't marked Sync. For example, +RefCell::new() is a +const fn, but because +RefCell isn't Sync, you'll +get an error at compile time:

+
use std::cell::RefCell;

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_LOCK: RefCell<u8> = RefCell::new(0);
+

-- +Rust Playground

+

It's likely that this will +change in the future though.

+

The Sync marker

+

Which leads well to the next point: static variable types must implement the +Sync marker. Because they're globally +unique, it must be safe for you to access static variables from any thread at any time. Most +struct definitions automatically implement the Sync trait because they contain only elements +which themselves implement Sync (read more in the +Nomicon). This is why earlier examples could +get away with initializing statics, even though we never included an impl Sync for MyStruct in the +code. To demonstrate this property, Rust refuses to compile our earlier example if we add a +non-Sync element to the struct definition:

+
use std::cell::RefCell;

struct MyStruct {
x: u32,
y: RefCell<u8>,
}

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_STRUCT: MyStruct = MyStruct {
x: 8,
y: RefCell::new(8)
};
+

-- +Rust Playground

+

Interior mutability

+

Finally, while static mut variables are allowed, mutating them is an unsafe operation. If we +want to stay in safe Rust, we can use interior mutability to accomplish similar goals:

+
use std::sync::Once;

// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once
static INIT: Once = Once::new();

fn main() {
// Note that while `INIT` is declared immutable, we're still allowed
// to mutate its interior
INIT.call_once(|| println!("Initializing..."));
// This code won't panic, as the interior of INIT was modified
// as part of the previous `call_once`
INIT.call_once(|| panic!("INIT was called twice!"));
}
+

-- +Rust Playground

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Allocations in Rust: Foreword]]> + https://speice.io/2019/02/understanding-allocations-in-rust + + 2019-02-04T12:00:00.000Z + + There's an alchemy of distilling complex technical topics into articles and videos that change the +way programmers see the tools they interact with on a regular basis. I knew what a linker was, but +there's a staggering amount of complexity in between +the OS and main(). Rust programmers use the +Box type all the time, but there's a +rich history of the Rust language itself wrapped up in +how special it is.

+

In a similar vein, this series attempts to look at code and understand how memory is used; the +complex choreography of operating system, compiler, and program that frees you to focus on +functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the +cognitive burden associated with memory management, but we're going to step into its world for a +while.

+

Let's learn a bit about memory in Rust.

+
+

Rust's three defining features of +Performance, Reliability, and Productivity are all driven to a great +degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, +Python), Rust +doesn't really +garbage collect; instead, it uses an +ownership system to reason about +how long objects will last in your program. In some cases, if the life of an object is fairly +transient, Rust can make use of a very fast region called the "stack." When that's not possible, +Rust uses +dynamic (heap) memory +and the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it +is important to have available.

+

That said, there are specific situations in Rust where you'd never need to worry about the +stack/heap distinction! If you:

+
    +
  1. Never use unsafe
  2. +
  3. Never use #![feature(alloc)] or the alloc crate
  4. +
+

...then it's not possible for you to use dynamic memory!

+

For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited +memory, and the program binary size itself may significantly affect what's available! There's no +operating system able to manage this +"virtual memory" thing, but that's not an issue +because there's only one running application. The +embedonomicon is ever in mind, and +interacting with the "real world" through extra peripherals is accomplished by reading and writing +to specific memory addresses.

+

Most Rust programs find these requirements overly burdensome though. C++ developers would struggle +without access to std::vector (except those +hardcore no-STL people), and Rust developers would struggle without +std::vec. But with the constraints above, +std::vec is actually a part of the +alloc crate, and thus off-limits. Box, +Rc, etc., are also unusable for the same reason.

+

Whether writing code for embedded devices or not, the important thing in both situations is how much +you know before your application starts about what its memory usage will look like. In embedded +devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large +google.com's home page is until you start trying to download it. The +compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code +runs faster when the compiler can guarantee exactly how much memory your program needs while it's +running. This series is all about understanding how the compiler reasons about your program, with an +emphasis on the implications for performance.

+

Now let's address some conditions and caveats before going much further:

+
    +
  • We'll focus on "safe" Rust only; unsafe lets you use platform-specific allocation API's +(malloc) that we'll +ignore.
  • +
  • We'll assume a "debug" build of Rust code (what you get with cargo run and cargo test) and +address (pun intended) release mode at the end (cargo run --release and cargo test --release).
  • +
  • All content will be run using Rust 1.32, as that's the highest currently supported in the +Compiler Exporer. As such, we'll avoid upcoming innovations like +compile-time evaluation of static +that are available in nightly.
  • +
  • Because of the nature of the content, being able to read assembly is helpful. We'll keep it +simple, but I found a +refresher on the push and pop +instructions was helpful while writing +this.
  • +
  • I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are +available, but if there's something said in error it will be corrected expeditiously. Please let +me know at bradlee@speice.io
  • +
+

Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth +repeating:

+
+

Rust does not currently have a rigorously and formally defined memory model.

+

-- the docs

+
]]>
+ + Bradlee Speice + +
+ + <![CDATA[QADAPT - debug_assert! for allocations]]> + https://speice.io/2018/12/allocation-safety + + 2018-12-15T12:00:00.000Z + + I think it's part of the human condition to ignore perfectly good advice when it comes our way. A +bit over a month ago, I was dispensing sage wisdom for the ages:

+
+

I had a really great idea: build a custom allocator that allows you to track your own allocations. +I gave it a shot, but learned very quickly: never write your own allocator.

+

-- me

+
+

I proceeded to ignore it, because we never really learn from our mistakes.

+

There's another part of the human condition that derives joy from seeing things explode.

+

Explosions

+

And that's the part I'm going to focus on.

+

Why an Allocator?

+

So why, after complaining about allocators, would I still want to write one? There are three reasons +for that:

+
    +
  1. Allocation/dropping is slow
  2. +
  3. It's difficult to know exactly when Rust will allocate or drop, especially when using code that +you did not write
  4. +
  5. I want automated tools to verify behavior, instead of inspecting by hand
  6. +
+

When I say "slow," it's important to define the terms. If you're writing web applications, you'll +spend orders of magnitude more time waiting for the database than you will the allocator. However, +there's still plenty of code where micro- or nano-seconds matter; think +finance, +real-time audio, +self-driving cars, and +networking. In these situations it's simply +unacceptable for you to spend time doing things that are not your program, and waiting on the +allocator is not cool.

+

As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. +So, I propose we play a quick trivia game: Does this code invoke the allocator?

+

Example 1

+
fn my_function() {
let v: Vec<u8> = Vec::new();
}
+

No: Rust knows how big the Vec type is, +and reserves a fixed amount of memory on the stack for the v vector. However, if we wanted to +reserve extra space (using Vec::with_capacity) the allocator would get invoked.

+

Example 2

+
fn my_function() {
let v: Box<Vec<u8>> = Box::new(Vec::new());
}
+

Yes: Because Boxes allow us to work with things that are of unknown size, it has to allocate on +the heap. While the Box is unnecessary in this snippet (release builds will optimize out the +allocation), reserving heap space more generally is needed to pass a dynamically sized type to +another function.

+

Example 3

+
fn my_function(v: Vec<u8>) {
v.push(5);
}
+

Maybe: Depending on whether the Vector we were given has space available, we may or may not +allocate. Especially when dealing with code that you did not author, it's difficult to verify that +things behave as you expect them to.

+

Blowing Things Up

+

So, how exactly does QADAPT solve these problems? Whenever an allocation or drop occurs in code +marked allocation-safe, QADAPT triggers a thread panic. We don't want to let the program continue +as if nothing strange happened, we want things to explode.

+

However, you don't want code to panic in production because of circumstances you didn't predict. +Just like debug_assert!, QADAPT will +strip out its own code when building in release mode to guarantee no panics and no performance +impact.

+

Finally, there are three ways to have QADAPT check that your code will not invoke the allocator:

+

Using a procedural macro

+

The easiest method, watch an entire function for allocator invocation:

+
use qadapt::no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

#[no_alloc]
fn push_vec(v: &mut Vec<u8>) {
// This triggers a panic if v.len() == v.capacity()
v.push(5);
}

fn main() {
let v = Vec::with_capacity(1);

// This will *not* trigger a panic
push_vec(&v);

// This *will* trigger a panic
push_vec(&v);
}
+

Using a regular macro

+

For times when you need more precision:

+
use qadapt::assert_no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
let v = Vec::with_capacity(1);

// No allocations here, we already have space reserved
assert_no_alloc!(v.push(5));

// Even though we remove an item, it doesn't trigger a drop
// because it's a scalar. If it were a `Box<_>` type,
// a drop would trigger.
assert_no_alloc!({
v.pop().unwrap();
});
}
+

Using function calls

+

Both the most precise and most tedious:

+
use qadapt::enter_protected;
use qadapt::exit_protected;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
// This triggers an allocation (on non-release builds)
let v = Vec::with_capacity(1);

enter_protected();
// This does not trigger an allocation because we've reserved size
v.push(0);
exit_protected();

// This triggers an allocation because we ran out of size,
// but doesn't panic because we're no longer protected.
v.push(1);
}
+

Caveats

+

It's important to point out that QADAPT code is synchronous, so please be careful when mixing in +asynchronous functions:

+
use futures::future::Future;
use futures::future::ok;

#[no_alloc]
fn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> {
ok(12).and_then(|e| Ok(Vec::with_capacity(e)))
}

fn main() {
// This doesn't trigger a panic because the `and_then` closure
// wasn't run during the function call.
async_capacity();

// Still no panic
assert_no_alloc!(async_capacity());

// This will panic because the allocation happens during `unwrap`
// in the `assert_no_alloc!` macro
assert_no_alloc!(async_capacity().poll().unwrap());
}
+

Conclusion

+

While there's a lot more to writing high-performance code than managing your usage of the allocator, +it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing +what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for +most allocators. Version 1.0 was released today, and you can check it out over at +crates.io or on github.

+

I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will +help guide that. If there are topics you're interested in, let me know in the comments below!

]]>
+ + Bradlee Speice + +
+ + <![CDATA[More "what companies really mean"]]> + https://speice.io/2018/12/what-small-business-really-means + + 2018-12-04T12:00:00.000Z + + I recently stumbled across a phenomenal small article entitled +What Startups Really Mean By "Why Should We Hire You?". +Having been interviewed by smaller companies (though not exactly startups), the questions and +subtexts are the same. There's often a question behind the question that you're actually trying to +answer, and I wish I spotted the nuance earlier in my career.

+

Let me also make note of one more question/euphemism I've come across:

+

How do you feel about production support?

+

Translation: We're a fairly small team, and when things break on an evening/weekend/Christmas +Day, can we call on you to be there?

+

I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're +incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning +that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make +it out the door before the zombie apocalypse.

+

Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people +who either enjoy that, or play along nicely enough that our systems keep working.

+

Small teams have no such luck. If you're interviewing at a small company, especially as a "data +scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the +most inopportune moments.

+

Terrible-but-popular answers include: It's a part of the job, and I'm happy to contribute.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[A case study in heaptrack]]> + https://speice.io/2018/10/case-study-optimization + + 2018-10-08T12:00:00.000Z + + I remember early in my career someone joking that:

+
+

Programmers have it too easy these days. They should learn to develop in low memory environments +and be more efficient.

+
+

...though it's not like the first code I wrote was for a +graphing calculator +packing a whole 24KB of RAM.

+

But the principle remains: be efficient with the resources you have, because +what Intel giveth, Microsoft taketh away.

+

My professional work is focused on this kind of efficiency; low-latency financial markets demand +that you understand at a deep level exactly what your code is doing. As I continue experimenting +with Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's +flexibility for the times I pretend to have a garbage collector, and flexibility for the times that +I really care about how memory is used.

+

This post is a (small) case study in how I went from the former to the latter. And ultimately, it's +intended to be a starting toolkit to empower analysis of your own code.

+

Curiosity

+

When I first started building the dtparse crate, my intention was to mirror as closely as possible +the equivalent Python library. Python, as you may know, is garbage collected. Very +rarely is memory usage considered in Python, and I likewise wasn't paying too much attention when +dtparse was first being built.

+

This lackadaisical approach to memory works well enough, and I'm not planning on making dtparse +hyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the +advent of Rust 1.28 and the +Global Allocator trait, I had a really +great idea: build a custom allocator that allows you to track your own allocations. That way, you +can do things like writing tests for both correct results and correct memory usage. I gave it a +shot, but learned very quickly: never write your own allocator. It went from "fun +weekend project" to "I have literally no idea what my computer is doing" at breakneck speed.

+

Instead, I'll highlight a separate path I took to make sense of my memory usage: heaptrack.

+

Turning on the System Allocator

+

This is the hardest part of the post. Because Rust uses +its own allocator by default, +heaptrack is unable to properly record unmodified Rust code. To remedy this, we'll make use of the +#[global_allocator] attribute.

+

Specifically, in lib.rs or main.rs, add this:

+
use std::alloc::System;

#[global_allocator]
static GLOBAL: System = System;
+

...and that's it. Everything else comes essentially for free.

+

Running heaptrack

+

Assuming you've installed heaptrack (Homebrew in Mac, package manager +in Linux, ??? in Windows), all that's left is to fire up your application:

+
heaptrack my_application
+

It's that easy. After the program finishes, you'll see a file in your local directory with a name +like heaptrack.my_appplication.XXXX.gz. If you load that up in heaptrack_gui, you'll see +something like this:

+

heaptrack

+
+

And even these pretty colors:

+

pretty colors

+

Reading Flamegraphs

+

To make sense of our memory usage, we're going to focus on that last picture - it's called a +"flamegraph". These charts are typically used to +show how much time your program spends executing each function, but they're used here to show how +much memory was allocated during those functions instead.

+

For example, we can see that all executions happened during the main function:

+

allocations in main

+

...and within that, all allocations happened during dtparse::parse:

+

allocations in dtparse

+

...and within that, allocations happened in two different places:

+

allocations in parseinfo

+

Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue: +what the heck is the Default thing doing?

+

pretty colors

+

Optimizing dtparse

+

See, I knew that there were some allocations during calls to dtparse::parse, but I was totally +wrong about where the bulk of allocations occurred in my program. Let me post the code and see if +you can spot the mistake:

+
/// Main entry point for using `dtparse`.
pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> {
let res = Parser::default().parse(
timestr, None, None, false, false,
None, false,
&HashMap::new(),
)?;

Ok((res.0, res.1))
}
+
+

dtparse

+
+
+

Because Parser::parse requires a mutable reference to itself, I have to create a new +Parser::default every time it receives a string. This is excessive! We'd rather have an immutable +parser that can be re-used, and avoid allocating memory in the first place.

+

Armed with that information, I put some time in to +make the parser immutable. +Now that I can re-use the same parser over and over, the allocations disappear:

+

allocations cleaned up

+

In total, we went from requiring 2 MB of memory in +version 1.0.2:

+

memory before

+

All the way down to 300KB in version 1.0.3:

+

memory after

+

Conclusion

+

In the end, you don't need to write a custom allocator to be efficient with memory, great tools +already exist to help you understand what your program is doing.

+

Use them.

+

Given that Moore's Law is +dead, we've all got to do +our part to take back what Microsoft stole.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Isomorphic desktop apps with Rust]]> + https://speice.io/2018/09/isomorphic-apps + + 2018-09-15T12:00:00.000Z + + I both despise Javascript and am stunned by its success doing some really cool things. It's +this duality that's +led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I +bootstrap a simple desktop application.

+

See, as much as +Webassembly isn't trying to replace Javascript, +I want Javascript gone. There are plenty of people who don't share my views, and they are +probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think +it's hilarious that the +language specification +dramatically outpaces anyone's +actual implementation. The answer to this +conundrum is of course to recompile code from newer versions of the language to older versions of +the same language before running. At least Babel is a nice tongue-in-cheek reference.

+

Yet for as much hate as Electron receives, it does a stunningly good job at solving a really hard +problem: how the hell do I put a button on the screen and react when the user clicks it? GUI +programming is hard, straight up. But if browsers are already able to run everywhere, why don't we +take advantage of someone else solving the hard problems for us? I don't like that I have to use +Javascript for it, but I really don't feel inclined to whip out good ol' wxWidgets.

+

Now there are other native solutions (libui-rs, conrod, oh hey wxWdidgets again!), but +those also have their own issues with distribution, styling, etc. With Electron, I can +yarn create electron-app my-app and just get going, knowing that packaging/upgrades/etc. are built +in.

+

My question is: given recent innovations with WASM, are we Electron yet?

+

No, not really.

+

Instead, what would it take to get to a point where we can skip Javascript in Electron apps?

+

Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There +may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to +try and organize what I did manage to discover.

+

I should also mention that the content and things I'm talking about here are not intended to be +prescriptive, but more "if someone else is interested, what do we already know doesn't work?" I +expect everything in this post to be obsolete within two months. Even over the course of writing +this, a separate blog post had +to be modified because upstream changes broke a +Rust tool the post tried to use. The post +ultimately +got updated, but +all this happened within the span of a week. Things are moving quickly.

+

I'll also note that we're going to skip asm.js and emscripten. Truth be told, I couldn't get +either of these to output anything, and so I'm just going to say +here be dragons. Everything I'm discussing here +uses the wasm32-unknown-unknown target.

+

The code that I did get running is available +over here. Feel free to use it as a starting point, +but I'm mostly including the link as a reference for the things that were attempted.

+

An Example Running Application

+

So, I did technically get a running application:

+

Electron app using WASM

+

...which you can also try out if you want:

+
git clone https://github.com/speice-io/isomorphic-rust.git
cd isomorphic_rust/percy
yarn install && yarn start
+

...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly +there to prove this is possible in the first place. And that's something to be proud of! There's a +huge amount of engineering that went into showing a window with the text "It's alive!".

+

There's also a lot of usability issues that prevent me from recommending anyone try Electron and +WASM apps at the moment, and I think that's the more important thing to discuss.

+

Issue the First: Complicated Toolchains

+

I quickly established that wasm-bindgen was necessary to "link" my Rust code to Javascript. At +that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM +blob. To keep things simple, the goal was to package everything using webpack so that I could just +load a bundle.js file on the page. That decision was to be the last thing that kinda worked in +this process.

+

The first issue +I ran into +while attempting to bundle everything via webpack is a detail in the WASM spec:

+
+

This function accepts a Response object, or a promise for one, and ... [if > it] does not match +the application/wasm MIME type, the returned promise will be rejected with a TypeError;

+

WebAssembly - Additional Web Embedding API

+
+

Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the +web this isn't a huge issue, as the server can set MIME types when delivering the blob. With +Electron, you're resolving things with a file:// URL and thus can't control the MIME type:

+

TypeError: Incorrect response MIME type. Expected &#39;application/wasm&#39;.

+

There are a couple of solutions depending on how far into the deep end you care to venture:

+
    +
  • Embed a static file server in your Electron application
  • +
  • Use a custom protocol and custom protocol handler
  • +
  • Host your WASM blob on a website that you resolve at runtime
  • +
+

But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. +Instead, my workaround was to +open a PR with webpack and use regex to remove +calls to instantiateStreaming in the +build script:

+
cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
# Have to use --mode=development so we can patch out the call to instantiateStreaming
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \
sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js"
+

Once that lands, the +build process +becomes much simpler:

+

cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js"
+

But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via +wasm-bindgen and webpack), we still have to make an Electron app. For this purpose I used a +starter app from Electron Forge, and then a +prestart script +to actually handle starting the application.

+

The +final toolchain +looks something like this:

+
    +
  • yarn start triggers the prestart script
  • +
  • prestart checks for missing tools (wasm-bindgen-cli, etc.) and then: +
      +
    • Uses cargo to compile the Rust code into WASM
    • +
    • Uses wasm-bindgen to link the WASM blob into a Javascript file with exported symbols
    • +
    • Uses webpack to bundle the page start script with the Javascript we just generated +
        +
      • Uses babel under the hood to compile the wasm-bindgen code down from ES6 into something +browser-compatible
      • +
      +
    • +
    +
  • +
  • The start script runs an Electron Forge handler to do some sanity checks
  • +
  • Electron actually starts
  • +
+

...which is complicated. I think more work needs to be done to either build a high-quality starter +app that can manage these steps, or another tool that "just handles" the complexity of linking a +compiled WASM file into something the Electron browser can run.

+

Issue the Second: WASM tools in Rust

+

For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only +bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that +leads to a fragmented ecosystem. Here's what I can recommend as a starting point:

+

Don't check in your Cargo.lock files to version control. If there's a disagreement between the +version of wasm-bindgen-cli you have installed and the wasm-bindgen you're compiling with in +Cargo.lock, you get a nasty error:

+
it looks like the Rust project used to create this wasm file was linked against
a different version of wasm-bindgen than this binary:

rust wasm file: 0.2.21
this binary: 0.2.17

Currently the bindgen format is unstable enough that these two version must
exactly match, so it's required that these two version are kept in sync by
either updating the wasm-bindgen dependency or this binary.
+

Not that I ever managed to run into this myself (coughs nervously).

+

There are two projects attempting to be "application frameworks": percy and yew. Between those, +I managed to get two +examples running +using percy, but was unable to get an +example running with yew because +of issues with "missing modules" during the webpack step:

+
ERROR in ./dist/electron_yew_wasm_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist'
@ ./dist/electron_yew_wasm_bg.wasm
@ ./dist/electron_yew_wasm.js
@ ./dist/app.js
@ ./dist/app_loader.js
+

If you want to work with the browser APIs directly, your choices are percy-webapis or stdweb (or +eventually web-sys). See above for my percy examples, but when I tried +an example with stdweb, I was +unable to get it running:

+
ERROR in ./dist/stdweb_electron_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist'
@ ./dist/stdweb_electron_bg.wasm
@ ./dist/stdweb_electron.js
@ ./dist/app_loader.js
+

At this point I'm pretty convinced that stdweb is causing issues for yew as well, but can't +prove it.

+

I did also get a minimal example +running that doesn't depend on any tools besides wasm-bindgen. However, it requires manually +writing "extern C" blocks for everything you need from the browser. Es no bueno.

+

Finally, from a tools and platform view, there are two up-and-coming packages that should be +mentioned: js-sys and web-sys. Their purpose is to be fundamental building blocks that exposes +the browser's APIs to Rust. If you're interested in building an app framework from scratch, these +should give you the most flexibility. I didn't touch either in my research, though I expect them to +be essential long-term.

+

So there's a lot in play from the Rust side of things, and it's just going to take some time to +figure out what works and what doesn't.

+

Issue the Third: Known Unknowns

+

Alright, so after I managed to get an application started, I stopped there. It was a good deal of +effort to chain together even a proof of concept, and at this point I'd rather learn Typescript +than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...

+

The important point I want to make is that there's a lot unknown about how any of this holds up +outside proofs of concept. Things I didn't attempt:

+
    +
  • Testing
  • +
  • Packaging
  • +
  • Updates
  • +
  • Literally anything related to why I wanted to use Electron in the first place
  • +
+

What it Would Take

+

Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and +WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an +application in production a couple months from now. But at the moment, I'm personally going to stay +away.

+

Let's finish with a wishlist then - here are the things that I think need to happen before +Electron/WASM/Rust can become a thing:

+
    +
  • Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet +(#7983)
  • +
  • Browser API libraries (web-sys and stdweb) need to make sure they can support running in +Electron (see module error above)
  • +
  • Projects need to stabilize. There's talk of stdweb being turned into a Rust API +on top of web-sys, and percy +moving to web-sys, both of which are big changes
  • +
  • wasm-bindgen is great, but still in the "move fast and break things" phase
  • +
  • A good "boilerplate" app would dramatically simplify the start-up costs; +electron-react-boilerplate comes to +mind as a good project to imitate
  • +
  • More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm +doing
  • +
]]>
+ + Bradlee Speice + +
+ + <![CDATA[Primitives in Rust are weird (and cool)]]> + https://speice.io/2018/09/primitives-in-rust-are-weird + + 2018-09-01T12:00:00.000Z + + I wrote a really small Rust program a while back because I was curious. I was 100% convinced it +couldn't possibly run:

+
fn main() {
println!("{}", 8.to_string())
}
+

And to my complete befuddlement, it compiled, ran, and produced a completely sensible output.

+

The reason I was so surprised has to do with how Rust treats a special category of things I'm going to +call primitives. In the current version of the Rust book, you'll see them referred to as +scalars, and in older versions they'll be called primitives, but +we're going to stick with the name primitive for the time being. Explaining why this program is so +cool requires talking about a number of other programming languages, and keeping a consistent +terminology makes things easier.

+

You've been warned: this is going to be a tedious post about a relatively minor issue that +involves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking +about with assembly.

+

Defining primitives (Java)

+

The reason I'm using the name primitive comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special +name for some specific types of values:

+
+
bool    char    byte
short int long
float double
+
+

They are referred to as primitives. And relative to the other bits of Java, +they have two unique features. First, they don't have to worry about the +billion-dollar mistake; +primitives in Java can never be null. Second: they can't have instance methods. +Remember that Rust program from earlier? Java has no idea what to do with it:

+
class Main {
public static void main(String[] args) {
int x = 8;
System.out.println(x.toString()); // Triggers a compiler error
}
}
+

The error is:

+
Main.java:5: error: int cannot be dereferenced
System.out.println(x.toString());
^
1 error
+

Specifically, Java's Object +and things that inherit from it are pointers under the hood, and we have to dereference them before +the fields and methods they define can be used. In contrast, primitive types are just values - +there's nothing to be dereferenced. In memory, they're just a sequence of bits.

+

If we really want, we can turn the int into an +Integer and then dereference +it, but it's a bit wasteful:

+
class Main {
public static void main(String[] args) {
int x = 8;
Integer y = Integer.valueOf(x);
System.out.println(y.toString());
}
}
+

This creates the variable y of type Integer (which inherits Object), and at run time we +dereference y to locate the toString() function and call it. Rust obviously handles things a bit +differently, but we have to dig into the low-level details to see it in action.

+

Low Level Handling of Primitives (C)

+

We first need to build a foundation for reading and understanding the assembly code the final answer +requires. Let's begin with showing how the C language (and your computer) thinks about "primitive" +values in memory:

+
void my_function(int num) {}

int main() {
int x = 8;
my_function(x);
}
+

The compiler explorer gives us an easy way of showing off the +assembly-level code that's generated: whose output has been lightly +edited

+
main:
push rbp
mov rbp, rsp
sub rsp, 16

; We assign the value `8` to `x` here
mov DWORD PTR [rbp-4], 8

; And copy the bits making up `x` to a location
; `my_function` can access (`edi`)
mov eax, DWORD PTR [rbp-4]
mov edi, eax

; Call `my_function` and give it control
call my_function

mov eax, 0
leave
ret

my_function:
push rbp
mov rbp, rsp

; Copy the bits out of the pre-determined location (`edi`)
; to somewhere we can use
mov DWORD PTR [rbp-4], edi
nop

pop rbp
ret
+

At a really low level of memory, we're copying bits around using the mov instruction; +nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C +to Rust:

+
fn my_function(x: i32) {}

fn main() {
let x = 8;
my_function(x)
}
+

And the assembly generated when we stick it in the +compiler explorer: again, lightly +edited

+
example::main:
push rax

; Look familiar? We're copying bits to a location for `my_function`
; The compiler just optimizes out holding `x` in memory
mov edi, 8

; Call `my_function` and give it control
call example::my_function

pop rax
ret

example::my_function:
sub rsp, 4

; And copying those bits again, just like in C
mov dword ptr [rsp], edi

add rsp, 4
ret
+

The generated Rust assembly is functionally pretty close to the C assembly: When working with +primitives, we're just dealing with bits in memory.

+

In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to +dereference. So what exactly is going on with this .to_string() function call?

+

impl primitive (and Python)

+

Now it's time to reveal my trap card show the revelation that tied all this +together: Rust has implementations for its primitive types. That's right, impl blocks aren't +only for structs and traits, primitives get them too. Don't believe me? Check out +u32, +f64 and +char as examples.

+

But the really interesting bit is how Rust turns those impl blocks into assembly. Let's break out +the compiler explorer once again:

+
pub fn main() {
8.to_string()
}
+

And the interesting bits in the assembly: heavily trimmed down

+
example::main:
sub rsp, 24
mov rdi, rsp
lea rax, [rip + .Lbyte_str.u]
mov rsi, rax

; Cool stuff right here
call <T as alloc::string::ToString>::to_string@PLT

mov rdi, rsp
call core::ptr::drop_in_place
add rsp, 24
ret
+

Now, this assembly is a bit more complicated, but here's the big revelation: we're calling +to_string() as a function that exists all on its own, and giving it the instance of 8. Instead +of thinking of the value 8 as an instance of u32 and then peeking in to find the location of the +function we want to call (like Java), we have a function that exists outside of the instance and +just give that function the value 8.

+

This is an incredibly technical detail, but the interesting idea I had was this: if to_string() +is a static function, can I refer to the unbound function and give it an instance?

+

Better explained in code (and a compiler explorer link because I +seriously love this thing):

+
struct MyVal {
x: u32
}

impl MyVal {
fn to_string(&self) -> String {
self.x.to_string()
}
}

pub fn main() {
let my_val = MyVal { x: 8 };

// THESE ARE THE SAME
my_val.to_string();
MyVal::to_string(&my_val);
}
+

Rust is totally fine "binding" the function call to the instance, and also as a static.

+

MIND == BLOWN.

+

Python does the same thing where I can both call functions bound to their instances and also call as +an unbound function where I give it the instance:

+
class MyClass():
x = 24

def my_function(self):
print(self.x)

m = MyClass()

m.my_function()
MyClass.my_function(m)
+

And Python tries to make you think that primitives can have instance methods...

+
>>> dir(8)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__',
...
'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__',
...]

>>> # Theoretically `8.__str__()` should exist, but:

>>> 8.__str__()
File "<stdin>", line 1
8.__str__()
^
SyntaxError: invalid syntax

>>> # It will run if we assign it first though:
>>> x = 8
>>> x.__str__()
'8'
+

...but in practice it's a bit complicated.

+

So while Python handles binding instance methods in a way similar to Rust, it's still not able to +run the example we started with.

+

Conclusion

+

This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor +details like primitives leads to really cool effects. Primitives are optimized like C in how they +have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python +(like both instance and late binding).

+

And when you put it together, there are areas where Rust does cool things nobody else can; as a +quirky feature of Rust's type system, 8.to_string() is actually valid code.

+

Now go forth and fool your friends into thinking you know assembly. This is all I've got.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[What I learned porting dateutil to Rust]]> + https://speice.io/2018/06/dateutil-parser-to-rust + + 2018-06-25T12:00:00.000Z + + I've mostly been a lurker in Rust for a while, making a couple small contributions here and there. +So launching dtparse feels like nice step towards becoming a +functioning member of society. But not too much, because then you know people start asking you to +pay bills, and ain't nobody got time for that.

+

But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you +what to do with your life (but you should totally keep reading).

+

Slow down, what?

+

OK, fine, I guess I should start with why someone would do this.

+

Dateutil is a Python library for handling dates. The +standard library support for time in Python is kinda dope, but there are a lot of extras that go +into making it useful beyond just the datetime +module. dateutil.parser specifically is code to take all the super-weird time formats people come +up with and turn them into something actually useful.

+

Date/time parsing, it turns out, is just like everything else involving +computers and +time: it +feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people +suck and this is why +we can't we have nice things. But +alas, we'll try and make contemporary art out of the rubble and give it a pretentious name like +Time.

+

A gravel mound

+
+

Time

+
+

What makes dateutil.parser great is that there's single function with a single argument that +drives what programmers interact with: +parse(timestr). +It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can +possibly do to make sense of your input" value. It doesn't expect much of you.

+

And now it's in Rust.

+

Lost in Translation

+

Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm +admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can +actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better +experiences than +this guy +who attempted the same thing for D. These are the actual take-aways:

+

When transcribing code, stay as close to the original library as possible. I'm talking about +using the same variable names, same access patterns, the whole shebang. It's way too easy to make a +couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference +manual for verbatim what your code should be means that you don't spend that long debugging +complicated logic, you're more looking for typos.

+

Also, don't use nice Rust things like enums. While +one time it worked out OK for me, +I also managed to shoot myself in the foot a couple times because dateutil stores AM/PM as a +boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In +general, writing nice code should not be a first-pass priority when you're just trying to recreate +the same functionality.

+

Exceptions are a pain. Make peace with it. Python code is just allowed to skip stack frames. So +when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out +he's not quite right, and I'm OK with that. And while +dateutil is pretty well-behaved about not skipping multiple stack frames, +130-line try-catch blocks +take a while to verify.

+

As another Python quirk, be very careful about +long nested if-elif-else blocks. +I used to think that Python's whitespace was just there to get you to format your code correctly. I +think that no longer. It's way too easy to close a block too early and have incredibly weird issues +in the logic. Make sure you use an editor that displays indentation levels so you can keep things +straight.

+

Rust macros are not free. I originally had the +main test body +wrapped up in a macro using pyo3. It took two minutes to compile. +After +moving things to a function +compile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code +to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually +functions that need to be liberated, man.

+

Finally, I really miss list comprehensions and dictionary comprehensions. As a quick comparison, +see +this dateutil code +and +the implementation in Rust. +I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be +added through macros or syntax extensions. Either way, they're expressive, save typing, and are +super-readable. Let's get more of that.

+

Using a young language

+

Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On +more than one occasion though, I've had issues navigating the Rust ecosystem.

+

What I'll call the "canonical library" is still being built. In Python, if you need datetime +parsing, you use dateutil. If you want decimal types, it's already in the +standard library. While I might've gotten away +with f64, dateutil uses decimals, and I wanted to follow the principle of staying as close to +the original library as possible. Thus began my quest to find a decimal library in Rust. What I +quickly found was summarized in a comment:

+
+

Writing a BigDecimal is easy. Writing a good BigDecimal is hard.

+

-cmr

+
+

In practice, this means that there are at least 4 +different +implementations available. +And that's a lot of decisions to worry about when all I'm thinking is "why can't +calendar reform be a thing" and I'm forced to dig +through a couple +different +threads to figure out if the library I'm look at is dead +or just stable.

+

And even when the "canonical library" exists, there's no guarantees that it will be well-maintained. +Chrono is the de facto date/time library in Rust, and just +released version 0.4.4 like two days ago. Meanwhile, +chrono-tz appears to be dead in the water even though +there are people happy to help maintain it. I +know relatively little about it, but it appears that most of the release process is automated; +keeping that up to date should be a no-brainer.

+

Trial Maintenance Policy

+

Specifically given "maintenance" being an +oft-discussed +issue, I'm going to try out the following policy to keep things moving on dtparse:

+
    +
  1. +

    Issues/PRs needing maintainer feedback will be updated at least weekly. I want to make sure +nobody's blocking on me.

    +
  2. +
  3. +

    To keep issues/PRs needing contributor feedback moving, I'm going to (kindly) ask the +contributor to check in after two weeks, and close the issue without resolution if I hear nothing +back after a month.

    +
  4. +
+

The second point I think has the potential to be a bit controversial, so I'm happy to receive +feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm +running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And +second: I don't mind keeping those requests going indefinitely. I just want to try and balance +keeping things moving with giving people the necessary time they need.

+

I should also note that I'm still getting some best practices in place - CONTRIBUTING and +CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are +perfect.

+

Roadmap and Conclusion

+

So if I've now built a dateutil-compatible parser, we're done, right? Of course not! That's not +nearly ambitious enough.

+

Ultimately, I'd love to have a library that's capable of parsing everything the Linux date command +can do (and not date on OSX, because seriously, BSD coreutils are the worst). I know Rust has a +coreutils rewrite going on, and dtparse would potentially be an interesting candidate since it +doesn't bring in a lot of extra dependencies. humantime +could help pick up some of the (current) slack in dtparse, so maybe we can share and care with each +other?

+

All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month +on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going +to take it hard.

+

And in the mean time, I'm looking forward to building more. Onwards.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Hello!]]> + https://speice.io/2018/05/hello + + 2018-05-28T12:00:00.000Z + + I'll do what I can to keep this short, there's plenty of other things we both should be doing right +now.

+

If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you +covered:

+

Saturday Bread

+

And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven.

+

Okay, just one:

+

Bread as rock

+

Thanks, and keep it amazing.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Captain's Cookbook: Practical usage]]> + https://speice.io/2018/01/captains-cookbook-part-2 + + 2018-01-16T13:00:00.000Z + + A look at more practical usages of Cap'N Proto

+

Part 1 of this series took a look at a basic starting project +with Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty +basic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's +some documentation surrounding practical usage of the library.

+

As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps +here. Our current example is going to build on +the code we wrote there; after the deserialization step, we'll try and send the point_reader to a separate thread +for verification.

+

I'm going to walk through the attempts as I made them and my thinking throughout. +If you want to skip to the final project, check out the code available here

+

Attempt 1: Move the reference

+

As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from
// somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// By using `point_reader` inside the new thread, we're hoping that Rust can
// safely move the reference and invalidate the original thread's usage.
// Since the original thread doesn't use `point_reader` again, this should
// be safe, right?
let handle = std::thread:spawn(move || {

assert_eq!(point_reader.get_x(), 12);

assert_eq!(point_reader.get_y(), 14);
});

handle.join().unwrap()
}
+

Well, the Rust compiler doesn't really like this. We get four distinct errors back:

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`                                                                                                                
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating. +Pay attention to the text that keeps on getting repeated though: XYZ cannot be sent between threads safely.

+

This is a bit frustrating: we own the buffer from which all the content was derived, and we don't have any +unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility +of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust +preventing us from doing something that really should be legal?

+

This is what is known as fighting the borrow checker. +Let our crusade begin.

+

Attempt 2: Put the Reader in a Box

+

The Box type allows us to convert a pointer we have +(in our case the point_reader) into an "owned" value, which should be easier to send across threads. +Our next attempt looks something like this:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content
// from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

let boxed_reader = Box::new(point_reader);

// Now that the reader is `Box`ed, we've proven ownership, and Rust can
// move the ownership to the new thread, right?
let handle = std::thread::spawn(move || {

assert_eq!(boxed_reader.get_x(), 12);

assert_eq!(boxed_reader.get_y(), 14);
});

handle.join().unwrap();
}
+

Spoiler alert: still doesn't work. Same errors still show up.

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`                       
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Let's be a little bit smarter about the exceptions this time though. What is that +std::marker::Send thing the compiler keeps telling us about?

+

The documentation is pretty clear; Send is used to denote:

+
+

Types that can be transferred across thread boundaries.

+
+

In our case, we are seeing the error messages for two reasons:

+
    +
  1. +

    Pointers (*const u8) are not safe to send across thread boundaries. While we're nice in our code +making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make +that assumption, and so complains that we're not using this in a safe manner.

    +
  2. +
  3. +

    The point_capnp::point::Reader type is itself not safe to send across threads because it doesn't +implement the Send trait. Which is to say, the things that make up a Reader are themselves not thread-safe, +so the Reader is also not thread-safe.

    +
  4. +
+

So, how are we to actually transfer a parsed Cap'N Proto message between threads?

+

Attempt 3: The TypedReader

+

The TypedReader is a new API implemented in the Cap'N Proto Rust code. +We're interested in it here for two reasons:

+
    +
  1. +

    It allows us to define an object where the object owns the underlying data. In previous attempts, +the current context owned the data, but the Reader itself had no such control.

    +
  2. +
  3. +

    We can compose the TypedReader using objects that are safe to Send across threads, guaranteeing +that we can transfer parsed messages across threads.

    +
  4. +
+

The actual type info for the TypedReader +is a bit complex. And to be honest, I'm still really not sure what the whole point of the +PhantomData thing is either. +My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto +message represents. That is, technically the only thing we're storing is the untyped binary message; +PhantomData just enforces the principle that the binary represents some specific object that has been parsed.

+

Either way, we can carefully construct something which is safe to move between threads:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> =
capnp::message::TypedReader::new(deserialized);

// Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message
// (which is 'static lifetime), this is now safe
let handle = std::thread::spawn(move || {

// The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader
// object from it
let point_root = point_reader.get().unwrap();

assert_eq!(point_root.get_x(), 12);

assert_eq!(point_root.get_y(), 14);
});

handle.join().unwrap();
}
+

And while we've left Rust to do the dirty work of actually moving the point_reader into the new thread, +we could also use things like mpsc channels to achieve a similar effect.

+

So now we're able to define basic Cap'N Proto messages, and send them all around our programs.

]]>
+ + Bradlee Speice + +
+ + <![CDATA[Captain's Cookbook: Project setup]]> + https://speice.io/2018/01/captains-cookbook-part-1 + + 2018-01-16T12:00:00.000Z + + A basic introduction to getting started with Cap'N Proto.

+

I've been working a lot with Cap'N Proto recently with Rust, but there's a real dearth of information +on how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's +fantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going.

+

So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with Protobuf +and FlatBuffers, but is better compared with FlatBuffers. The whole point behind it +is to define a schema language and serialization format such that:

+
    +
  1. Applications that do not share the same base programming language can communicate
  2. +
  3. The data and schema you use can naturally evolve over time as your needs change
  4. +
+

Accompanying this are typically code generators that take the schemas you define for your application and give you back +code for different languages to get data to and from that schema.

+

Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way +as is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.

+

We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some +examples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects. +If you want to follow along, feel free. If not, I've posted the final result +for reference.

+

Step 1: Installing capnp

+

The capnp binary itself is needed for taking the schema files you write and turning them into a format that can be used by the +code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed.

+

I'll refer you to Cap'N Proto's installation instructions here. As a quick TLDR though:

+
    +
  • Linux users will likely have a binary shipped by their package manager - On Ubuntu, apt install capnproto is enough
  • +
  • OS X users can use Homebrew as an easy install path. Just brew install capnp
  • +
  • Windows users are a bit more complicated. If you're using Chocolatey, there's a package available. If that doesn't work however, you need to download a release zip and make sure that the capnp.exe binary is in your %PATH% environment variable
  • +
+

The way you know you're done with this step is if the following command works in your shell:

+
capnp id
+

Step 2: Starting a Cap'N Proto Rust project

+

After the capnp binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple

+
mkdir capnp_cookbook_1
cd capnp_cookbook_1
cargo init --bin
+

We'll put the following content into Cargo.toml:

+
[package]
name = "capnp_cookbook_1"
version = "0.1.0"
authors = ["Bradlee Speice <bspeice@kcg.com>"]

[build-dependencies]
capnpc = "0.8" # 1

[dependencies]
capnp = "0.8" # 2
+

This sets up:

+
    +
  1. The Rust code generator (CAPNProto Compiler)
  2. +
  3. The Cap'N Proto runtime library (CAPNProto runtime)
  4. +
+

We've now got everything prepared that we need for writing a Cap'N Proto project.

+

Step 3: Writing a basic schema

+

We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure +you get familiar with how to start from a basic project.

+

First, we're going to create a top-level directory for storing the schema files in:

+
# Assuming we're starting from the `capnp_cookbook_1` directory created earlier

mkdir schema
cd schema
+

Now, we're going to put the following content in point.capnp:

+
@0xab555145c708dad2;

struct Point {
x @0 :Int32;
y @1 :Int32;
}
+

Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format.

+

Step 4: Setting up the build process

+

Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using. +This is typically done through a build.rs file to invoke the schema compiler.

+

In the same folder as your Cargo.toml file, please put the following content in build.rs:

+
extern crate capnpc;

fn main() {
::capnpc::CompilerCommand::new()
.src_prefix("schema") // 1
.file("schema/point.capnp") // 2
.run().expect("compiling schema");
}
+

This sets up the protocol compiler (capnpc from earlier) to compile the schema we've built so far.

+
    +
  1. Because Cap'N Proto schema files can re-use types specified in other files, the src_prefix() tells the compiler +where to look for those extra files at.
  2. +
  3. We specify the schema file we're including by hand. In a much larger project, you could presumably build the CompilerCommand +dynamically, but we won't worry too much about that one for now.
  4. +
+

Step 5: Running the build

+

If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code. +Run a cargo build command, and if you don't see cargo complaining, you're doing just fine!

+

So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated +code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives +somewhere in the target/ directory.

+

The long answer is that you're best off running a find command to get the actual file path:

+
# Assuming we're running from the capnp_cookbook_1 project folder
find . -name point_capnp.rs
+

Alternately, if the find command isn't available, the path will look something like:

+
./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs
+

See if there are any paths in your target directory that look similar.

+

Now, the file content looks pretty nasty. I've included an example here +if you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how +the schema we wrote for the "Point" message is tied to the generated code.

+

First, the Cap'N Proto library splits things up into Builder and Reader structs. These are best thought of the same way +Rust separates mut from non-mut code. Builders are mut versions of your message, and Readers are immutable versions.

+

For example, the Builder impl for point defines get_x(), set_x(), get_y(), and set_y() methods. +In comparison, the Reader impl only defines get_x() and get_y() methods.

+

So now we know that there are some get and set methods available for our x and y coordinates; +but what do we actually do with those?

+

Step 6: Making a point

+

So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building +Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code +should go in src/main.rs:

+
// Note that we use `capnp` here, NOT `capnpc`
extern crate capnp;

// We create a module here to define how we are to access the code
// being included.
pub mod point_capnp {
// The environment variable OUT_DIR is set by Cargo, and
// is the location of all the code that was built as part
// of the codegen step.
// point_capnp.rs is the actual file to include
include!(concat!(env!("OUT_DIR"), "/point_capnp.rs"));
}

fn main() {

// The process of building a Cap'N Proto message is a bit tedious.
// We start by creating a generic Builder; it acts as the message
// container that we'll later be filling with content of our `Point`
let mut builder = capnp::message::Builder::new_default();

// Because we need a mutable reference to the `builder` later,
// we fence off this part of the code to allow sequential mutable
// borrows. As I understand it, non-lexical lifetimes:
// https://github.com/rust-lang/rust-roadmap/issues/16
// will make this no longer necessary
{
// And now we can set up the actual message we're trying to create
let mut point_msg = builder.init_root::<point_capnp::point::Builder>();

// Stuff our message with some content
point_msg.set_x(12);

point_msg.set_y(14);
}

// It's now time to serialize our message to binary. Let's set up a buffer for that:
let mut buffer = Vec::new();

// And actually fill that buffer with our data
capnp::serialize::write_message(&mut buffer, &builder).unwrap();

// Finally, let's deserialize the data
let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

// `deserialized` is currently a generic reader; it understands
// the content of the message we gave it (i.e. that there are two
// int32 values) but doesn't really know what they represent (the Point).
// This is where we map the generic data back into our schema.
let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// We can now get our x and y values back, and make sure they match
assert_eq!(point_reader.get_x(), 12);
assert_eq!(point_reader.get_y(), 14);
}
+

And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up +some practical examples of Cap'N Proto in action:

]]>
+ + Bradlee Speice + +
+ \ No newline at end of file diff --git a/atom.xsl b/atom.xsl new file mode 100644 index 0000000..271895c --- /dev/null +++ b/atom.xsl @@ -0,0 +1,92 @@ + + + + + + + + Atom Feed | <xsl:value-of + select="atom:feed/atom:title" + /> + + + +
+
+
+ This is an Atom feed. Subscribe by copying the URL + from the address bar into your newsreader. Visit + About Feeds to learn more + and get started. It’s free. +
+

+
+ + + + + + + + + + +
+ +

+

+ +

+
+

Recent Posts

+
+ +
+

+ +
+ +
+
+
+
+
+ + +
+
diff --git a/authors/index.html b/authors/index.html new file mode 100644 index 0000000..259f7c4 --- /dev/null +++ b/authors/index.html @@ -0,0 +1 @@ +Authors | The Old Speice Guy \ No newline at end of file diff --git a/feed.xml/index.html b/feed.xml/index.html new file mode 100644 index 0000000..79a2913 --- /dev/null +++ b/feed.xml/index.html @@ -0,0 +1 @@ +The Old Speice Guy
\ No newline at end of file diff --git a/img/favicon.ico b/img/favicon.ico new file mode 100644 index 0000000..ab628be Binary files /dev/null and b/img/favicon.ico differ diff --git a/img/logo-dark.svg b/img/logo-dark.svg new file mode 100644 index 0000000..07655cf --- /dev/null +++ b/img/logo-dark.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/logo.svg b/img/logo.svg new file mode 100644 index 0000000..4f9a182 --- /dev/null +++ b/img/logo.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..ebc7cfc --- /dev/null +++ b/index.html @@ -0,0 +1,60 @@ +The Old Speice Guy | The Old Speice Guy

The webpack industrial complex

· 5 min read
Bradlee Speice

This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).

+

The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.

Release the GIL

· 9 min read
Bradlee Speice

Complaining about the Global Interpreter Lock +(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision +made before multi-core CPU's were widely available, but the fact that it's still around indicates +that it generally works Good +Enough. Besides, there are simple and effective +workarounds; it's not hard to start a +new process and use message passing to +synchronize code running in parallel.

+

Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of +asynchronicity and M:N threading, Python seems lacking. The ideal scenario is to take advantage of +both Python's productivity and the modern CPU's parallel capabilities.

Binary format shootout

· 9 min read
Bradlee Speice

I've found that in many personal projects, +analysis paralysis is particularly deadly. +Making good decisions in the beginning avoids pain and suffering later; if extra research prevents +future problems, I'm happy to continue procrastinating researching indefinitely.

+

So let's say you're in need of a binary serialization format. Data will be going over the network, +not just in memory, so having a schema document and code generation is a must. Performance is +crucial, so formats that support zero-copy de/serialization are given priority. And the more +languages supported, the better; I use Rust, but can't predict what other languages this could +interact with.

+

Given these requirements, the candidates I could find were:

On building high performance systems

· 13 min read
Bradlee Speice

Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is +made up of people who have access to secret techniques mortal developers could only dream of. There +had to be some secret art that could only be learned if one had an appropriately tragic backstory.

Making bread

· 2 min read
Bradlee Speice

Having recently started my "gardening leave" between positions, I have some more personal time +available. I'm planning to stay productive, contributing to some open-source projects, but it also +occurred to me that despite talking about bread pics, this +blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites +and Bytes"?

Allocations in Rust: Summary

· 2 min read
Bradlee Speice

While there's a lot of interesting detail captured in this series, it's often helpful to have a +document that answers some "yes/no" questions. You may not care about what an Iterator looks like +in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust +will prioritize the fastest behavior it can, here are the rules for each memory type:

Allocations in Rust: Compiler optimizations

· 4 min read

Up to this point, we've been discussing memory usage in the Rust language by focusing on simple +rules that are mostly right for small chunks of code. We've spent time showing how those rules work +themselves out in practice, and become familiar with reading the assembly code needed to see each +memory type (global, stack, heap) in action.

+

Throughout the series so far, we've put a handicap on the code. In the name of consistent and +understandable results, we've asked the compiler to pretty please leave the training wheels on. Now +is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the +Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them +do their job.

Allocations in Rust: Dynamic memory

· 6 min read
Bradlee Speice

Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and +some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how +the language uses dynamic memory (also referred to as the heap) is a system called ownership. +And as the docs mention, ownership +is Rust's most unique feature.

+

The heap is used in two situations; when the compiler is unable to predict either the total size of +memory needed, or how long the memory is needed for, it allocates space in the heap.

Allocations in Rust: Fixed memory

· 16 min read
Bradlee Speice

const and static are perfectly fine, but it's relatively rare that we know at compile-time about +either values or references that will be the same for the duration of our program. Put another way, +it's not often the case that either you or your compiler knows how much memory your entire program +will ever need.

+

However, there are still some optimizations the compiler can do if it knows how much memory +individual functions will need. Specifically, the compiler can make use of "stack" memory (as +opposed to "heap" memory) which can be managed far faster in both the short- and long-term.

Allocations in Rust: Global memory

· 8 min read
Bradlee Speice

The first memory type we'll look at is pretty special: when Rust can prove that a value is fixed +for the life of a program (const), and when a reference is unique for the life of a program +(static as a declaration, not +'static as a +lifetime), we can make use of global memory. This special section of data is embedded directly in +the program binary so that variables are ready to go once the program loads; no additional +computation is necessary.

+

Understanding the value/reference distinction is important for reasons we'll go into below, and +while the +full specification for +these two keywords is available, we'll take a hands-on approach to the topic.

\ No newline at end of file diff --git a/index.md b/index.md deleted file mode 100644 index 0671507..0000000 --- a/index.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -# Feel free to add content and custom Front Matter to this file. -# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults - -layout: home ---- diff --git a/lunr-index-1731274975527.json b/lunr-index-1731274975527.json new file mode 100644 index 0000000..29c90b3 --- /dev/null +++ b/lunr-index-1731274975527.json @@ -0,0 +1 @@ +{"version":"2.3.9","fields":["title","content","keywords"],"fieldVectors":[["title/0",[0,702.378,1,634.395,2,528.917]],["content/0",[]],["keywords/0",[]],["title/1",[3,309.686,4,1066.856]],["content/1",[3,4.518,5,10.911,6,6.539,7,4.858,8,6.071,9,12.074,10,7.758,11,8.535,12,12.182,13,6.959,14,12.182,15,12.182,16,5.678,17,7.867,18,3.07,19,6.908,20,4.047,21,4.947,22,2.986,23,2.789,24,10.911,25,6.218,26,12.182,27,5.559,28,8.179,29,9.449,30,10.911,31,10.074,32,12.182,33,10.074,34,4.11,35,12.182,36,12.182,37,12.182,38,12.182,39,9.449,40,7.867,41,5.446,42,12.182,43,12.182,44,12.182,45,5.446,46,12.182,47,9.449,48,6.717,49,7.867,50,10.074,51,12.182,52,8.95,53,3.695,54,5.802,55,8.179,56,7.591,57,6.539,58,7.591,59,12.182,60,12.182,61,12.182,62,7.867,63,12.182,64,5.802,65,12.182,66,4.947,67,9.449,68,5.135,69,12.182,70,10.074,71,12.182]],["keywords/1",[]],["title/2",[72,838.449]],["content/2",[9,9.081,18,3.824,21,4.755,22,3.719,25,5.976,31,12.548,73,2.831,74,4.507,75,7.86,76,10.486,77,7.056,78,11.707,79,4.587,80,11.707,81,8.145,82,15.172,83,10.402,84,4.843,85,9.144,86,1.995,87,15.95,88,10.486,89,5.13,90,10.486,91,4.843,92,11.707,93,4.013,94,5.976,95,9.144,96,7.561,97,9.081,98,2.87,99,10.486,100,4.213,101,11.707,102,9.682,103,11.707,104,4.507,105,11.707,106,7.561,107,7.86,108,4.843,109,5.576,110,6.125,111,9.799,112,11.707,113,7.86,114,7.86,115,5.576,116,3.246,117,7.86,118,6.125,119,9.081,120,9.081,121,11.707,122,11.707,123,11.707,124,3.35,125,4.013,126,9.081,127,5.457,128,9.081,129,11.707,130,5.457,131,3.771,132,11.707]],["keywords/2",[]],["title/3",[133,1298.223]],["content/3",[0,12.624,2,5.481,6,5.037,9,7.278,10,4.676,13,4.195,18,2.365,21,6.111,28,8.778,29,10.141,30,13.477,34,4.411,47,7.278,66,3.811,73,2.269,74,3.612,75,6.3,81,5.037,83,7.637,86,1.783,87,13.477,94,4.789,98,3.205,104,5.033,106,6.06,107,6.3,108,3.882,113,6.3,114,6.3,116,2.007,118,6.84,120,7.278,124,2.685,125,3.216,131,3.022,134,3.882,135,3.216,136,8.147,137,4.469,138,6.574,139,8.404,140,4.676,141,5.01,142,4.554,143,5.174,144,7.76,145,2.579,146,9.383,147,5.174,148,6.894,149,5.481,150,9.383,151,9.383,152,6.06,153,3.117,154,4.783,155,9.383,156,5.655,157,10.812,158,5.847,159,5.321,160,4.195,161,7.278,162,4.676,163,9.383,164,5.729,165,9.383,166,7.76,167,3.069,168,13.477,169,8.404,170,7.328,171,9.383,172,7.76,173,6.3,174,6.06,175,8.404,176,8.404,177,9.383,178,8.404,179,3.432,180,6.06,181,7.76,182,9.383,183,12.443,184,4.373,185,2.804,186,12.443,187,6.894,188,4.282,189,8.404,190,2.977,191,4.469,192,8.404,193,6.894,194,9.383,195,5.847,196,9.383,197,9.383,198,5.174,199,9.383,200,9.383,201,5.847,202,7.76,203,7.278,204,8.404,205,9.383,206,4.469,207,9.383,208,2.846,209,6.06,210,7.278,211,5.847,212,2.977,213,9.383,214,9.383,215,4.373,216,1.98]],["keywords/3",[]],["title/4",[217,588.253,218,955.587]],["content/4",[0,10.283,1,6.707,2,5.592,7,3.818,13,4.28,21,5.384,28,6.427,39,10.283,64,4.56,66,3.888,74,3.685,81,7.116,86,1.134,89,4.195,91,3.96,98,2.347,137,4.56,140,4.771,145,1.888,147,5.278,149,10.069,154,3.502,160,4.28,167,3.131,170,4.663,176,11.874,179,3.502,183,7.917,184,4.462,185,3.962,186,12.577,188,4.369,189,8.574,190,3.037,191,4.56,204,8.574,208,4.021,210,10.283,212,3.037,217,7.31,219,4.404,220,13.257,221,7.033,222,4.195,223,4.114,224,9.573,225,9.573,226,9.573,227,9.573,228,7.917,229,4.886,230,9.288,231,8.574,232,7.033,233,2.991,234,9.573,235,9.573,236,7.426,237,9.573,238,9.573,239,3.162,240,9.573,241,7.917,242,6.427,243,7.426,244,8.901,245,1.863,246,5.77,247,8.574,248,9.573,249,6.183,250,4.771,251,8.574,252,4.771,253,7.033,254,9.573,255,7.426,256,3.818,257,9.573,258,9.573,259,8.574,260,6.183,261,5.965,262,6.707,263,10.964,264,9.573,265,3.561,266,6.05,267,7.917,268,9.573,269,6.427,270,9.573,271,9.573,272,9.573,273,6.427,274,9.166,275,3.389,276,5.77,277,5.429,278,9.573,279,6.707,280,8.574,281,7.033,282,5.77,283,9.573,284,8.574,285,6.183,286,5.429,287,9.573,288,7.917,289,3.18,290,9.573,291,9.573,292,6.427,293,7.917,294,6.183,295,8.574,296,8.574,297,7.033,298,8.574,299,5.592,300,4.195]],["keywords/4",[]],["title/5",[301,882.296,302,955.587]],["content/5",[]],["keywords/5",[]],["title/6",[303,642.995,304,371.602]],["content/6",[7,3.711,18,2.345,23,2.13,86,1.54,104,3.582,141,2.864,143,5.13,145,1.835,172,7.694,245,2.914,276,7.833,301,7.694,302,8.333,303,5.607,304,6.446,305,4.867,306,6.976,307,2.951,308,3.23,309,5.607,310,9.304,311,8.333,312,4.251,313,9.304,314,7.217,315,9.674,316,4.077,317,9.027,318,9.304,319,2.982,320,12.996,321,9.304,322,9.304,323,12.996,324,9.549,325,12.996,326,12.996,327,12.996,328,5.811,329,7.694,330,9.304,331,9.304,332,9.304,333,3.582,334,7.694,335,7.694,336,3.849,337,5.607,338,9.304,339,9.304,340,9.304,341,9.304,342,6.518,343,6.836,344,4.246,345,8.099,346,6.564,347,8.483,348,9.304,349,9.304,350,4.431,351,8.394,352,6.836,353,9.471,354,9.106,355,9.304,356,9.304,357,3.645,358,2.281,359,5.434,360,6.009,361,9.304,362,9.304,363,9.304,364,9.304,365,5.695,366,9.304,367,4.531,368,7.694,369,9.106,370,4.994,371,9.304,372,7.217,373,8.333]],["keywords/6",[]],["title/7",[304,371.602,344,486.887]],["content/7",[20,2.926,22,2.159,53,2.672,64,4.195,86,1.723,98,2.159,104,3.391,143,4.857,154,3.222,212,2.794,216,1.859,219,5.768,233,2.752,245,1.714,265,3.277,275,3.118,276,7.537,282,5.309,285,5.689,303,5.309,304,5.064,308,3.108,312,2.881,319,2.983,328,3.938,345,11.129,347,7.607,351,5.689,358,2.159,367,8.141,370,7.805,374,2.52,375,6.472,376,5.309,377,4.02,378,8.808,379,7.889,380,7.284,381,6.233,382,3.222,383,7.889,384,7.284,385,8.808,386,4.29,387,8.808,388,7.889,389,4.39,390,9.188,391,8.808,392,9.762,393,8.808,394,8.808,395,8.808,396,8.808,397,8.808,398,6.832,399,8.808,400,8.808,401,8.808,402,2.926,403,7.889,404,3.451,405,7.284,406,7.284,407,8.808,408,8.808,409,3.169,410,8.808,411,6.383,412,8.761,413,6.171,414,8.808,415,5.145,416,4.105,417,3.222,418,3.391,419,14.539,420,12.505,421,8.808,422,4.728,423,8.808,424,8.808,425,12.505,426,8.808,427,8.808,428,8.808,429,13.023,430,3.577,431,3.86,432,8.808,433,8.808,434,8.808,435,8.808,436,8.808,437,8.808,438,8.808,439,8.808,440,8.808,441,8.808,442,8.808,443,8.808]],["keywords/7",[]],["title/8",[185,318.859,304,371.602]],["content/8",[53,4.333,58,8.902,73,3.454,86,2.036,167,4.673,289,4.746,304,4.976,307,4.532,308,3.551,309,8.61,319,2.808,351,9.227,357,6.732,389,7.12,392,9.592,403,12.796,444,10.009,445,12.796,446,14.286,447,5.315,448,14.286,449,4.602,450,14.286,451,12.038,452,14.286]],["keywords/8",[]],["title/9",[143,499.273,328,404.835,453,486.063]],["content/9",[3,4.821,18,2.869,23,2.606,73,2.753,104,4.383,142,3.966,143,10.082,145,2.246,216,2.403,219,3.782,239,2.715,277,9.418,282,6.862,307,3.612,308,2.83,312,4.873,315,9.622,316,4.989,319,2.783,328,7.425,335,9.416,345,7.094,347,8.689,352,8.365,357,6.507,358,4.071,374,3.257,379,10.198,386,5.545,392,7.644,404,4.461,411,5.811,454,4.71,455,7.977,456,3.966,457,10.198,458,7.094,459,7.741,460,5.545,461,12.277,462,16.608,463,12.322,464,11.385,465,11.385,466,11.385,467,11.385,468,11.385,469,11.385,470,11.385,471,11.385,472,11.385,473,7.977,474,5.956,475,11.385,476,11.385,477,11.385,478,11.385]],["keywords/9",[]],["title/10",[143,499.273,328,404.835,479,905.483]],["content/10",[22,3.1,73,3.058,86,1.499,143,8.789,185,3.78,307,4.012,312,4.137,319,2.869,328,7.127,329,10.46,347,6.617,386,6.16,411,8.136,454,6.594,459,5.895,461,8.491,480,9.292,481,6.455,482,8.861,483,4.551,484,6.304,485,7.881,486,19.288,487,15.94,488,12.647,489,9.292,490,12.647,491,12.647,492,8.168,493,12.647,494,12.647,495,12.647,496,7.881,497,11.328,498,10.46,499,4.268,500,11.328,501,9.292,502,12.647,503,12.647,504,12.647,505,12.647,506,15.94]],["keywords/10",[]],["title/11",[303,545.735,304,315.394,507,634.395]],["content/11",[3,3.616,22,3.054,64,5.933,73,3.012,86,1.476,104,4.796,143,6.869,145,2.457,219,4.138,245,3.373,276,7.508,277,7.064,304,6.037,305,6.517,307,3.952,319,2.862,328,5.569,335,10.302,345,7.762,347,8.26,351,8.045,354,8.728,358,4.249,365,6.918,367,6.067,416,5.806,445,11.158,453,6.687,461,8.364,497,11.158,500,11.158,507,8.728,508,5.685,509,10.302,510,9.663,511,7.762,512,6.687,513,12.457,514,7.508,515,15.788,516,12.457,517,11.158,518,9.152,519,12.457,520,14.141,521,12.457,522,12.457,523,12.457]],["keywords/11",[]],["title/12",[304,371.602,524,371.602]],["content/12",[22,2.89,73,2.851,86,1.806,98,2.89,153,3.917,219,5.063,239,2.812,245,3.287,246,7.106,265,4.386,276,7.106,277,6.687,289,5.063,301,9.751,304,5.883,306,6.329,308,2.931,312,3.857,319,2.894,328,6.815,345,9.498,351,9.844,354,8.261,358,3.737,367,8.227,370,8.182,374,3.374,388,10.561,392,7.916,402,3.917,444,8.261,447,4.386,453,6.329,501,8.663,507,8.261,517,10.561,518,8.663,520,13.653,525,7.615,526,4.703,527,11.791,528,10.561,529,16.89,530,11.791,531,11.791,532,11.791,533,11.791,534,9.146,535,9.146,536,9.146,537,11.791,538,11.791,539,11.791]],["keywords/12",[]],["title/13",[304,371.602,540,882.296]],["content/13",[22,1.816,45,4.929,48,4.084,53,2.247,73,1.791,141,2.28,145,1.461,219,5.431,242,4.973,245,3.459,303,7.937,304,6.659,306,7.069,307,2.35,316,3.246,319,2.896,328,3.312,333,5.07,336,3.064,344,3.381,345,6.87,347,3.876,351,8.505,352,10.718,357,2.902,358,1.816,365,4.832,367,3.608,370,3.976,372,5.746,392,4.973,398,5.746,402,4.846,417,4.033,418,2.852,449,3.551,454,4.561,461,4.973,463,6.126,474,5.768,501,5.443,518,8.101,534,5.746,535,5.746,536,5.746,540,13.52,541,6.126,542,5.19,543,4.514,544,12.064,545,7.408,546,13.52,547,9.118,548,8.552,549,7.408,550,5.746,551,7.408,552,6.635,553,7.408,554,6.645,555,9.676,556,6.635,557,6.635,558,12.064,559,10.891,560,12.064,561,3.453,562,6.126,563,7.408,564,6.126,565,10.891,566,10.891,567,6.126,568,6.126,569,6.126,570,7.408,571,7.408,572,6.126,573,6.126,574,3.608,575,6.126,576,9.118,577,6.126,578,6.126,579,7.408,580,9.118,581,6.126,582,6.126,583,6.126,584,6.126,585,6.126,586,6.126,587,6.126,588,6.126,589,9.118,590,6.126,591,6.126,592,6.126,593,9.118,594,6.126,595,6.126,596,4.245,597,6.126,598,9.118,599,6.126,600,7.408,601,6.126,602,7.408,603,11.025,604,6.126,605,7.025,606,7.408,607,7.408,608,2.622,609,7.408,610,7.408,611,7.408,612,7.408,613,3.312,614,7.408,615,7.408,616,7.408,617,7.408,618,7.408,619,4.973,620,7.408,621,7.408]],["keywords/13",[]],["title/14",[304,273.955,381,392.002,622,610.095,623,265.389]],["content/14",[34,2.031,45,4.207,48,5.189,53,1.826,86,0.713,108,2.49,145,1.187,153,2,156,3.628,185,2.812,219,5.691,242,4.041,245,3.259,246,5.671,276,3.628,303,6.983,304,6.405,306,8.089,307,1.91,308,1.496,312,1.969,316,4.124,317,3.628,319,2.881,328,2.691,333,5.043,336,2.49,345,5.864,347,7.437,351,7.483,352,8.512,357,2.358,358,3.485,365,4.124,367,2.932,370,3.231,372,4.669,381,5.774,389,3,392,4.041,398,4.669,402,4.352,417,3.442,418,4.46,449,4.22,454,2.49,459,2.806,460,7.34,463,4.978,474,7.437,501,4.422,518,6.914,534,4.669,535,4.669,536,4.669,540,4.978,541,4.978,542,4.217,543,5.741,544,15.049,546,15.049,547,7.782,548,4.669,554,3.628,555,9.625,556,5.391,557,5.391,558,10.834,559,7.782,560,10.834,561,2.806,564,4.978,565,9.581,566,9.581,567,11.756,568,4.978,569,4.978,572,7.782,573,7.782,574,2.932,575,4.978,576,7.782,577,4.978,578,4.978,580,7.782,581,4.978,582,4.978,583,4.978,584,4.978,585,4.978,586,4.978,587,4.978,588,4.978,589,7.782,590,4.978,591,4.978,592,4.978,593,7.782,594,4.978,595,4.978,596,3.623,597,4.978,598,7.782,599,4.978,601,4.978,604,4.978,605,6.476,608,3.331,613,2.691,619,4.041,622,10.162,623,3.909,624,1.288,625,2.638,626,3.516,627,3.516,628,4.978,629,6.983,630,2.239,631,6.019,632,6.019,633,9.625,634,7.782,635,2.691,636,6.019,637,3.516,638,3.628,639,6.019,640,6.019,641,6.019,642,4.978,643,11.734,644,3.072,645,6.019,646,6.019,647,5.391,648,5.391,649,8.429,650,6.019,651,9.41,652,6.019,653,6.019,654,6.019,655,6.019,656,6.019,657,6.019,658,6.019,659,6.019,660,6.019,661,6.019,662,6.019,663,6.019]],["keywords/14",[]],["title/15",[304,315.394,622,702.378,623,305.531]],["content/15",[45,4.515,53,2,67,5.116,100,2.373,104,2.539,142,2.297,143,3.637,145,1.992,153,2.191,184,3.074,185,3.019,219,5.195,223,2.834,242,4.428,245,3.418,303,7.397,304,6.521,306,6.588,307,2.092,308,2.51,309,3.975,315,4.26,317,3.975,319,2.928,328,2.949,333,4.725,345,6.293,347,6.421,351,7.927,352,9.018,353,3.852,357,3.957,358,3.635,365,4.426,367,3.212,370,3.54,372,5.116,386,3.212,392,4.428,398,5.116,402,4.569,417,5.031,418,2.539,449,3.953,454,2.728,483,2.373,501,4.846,518,7.42,534,5.116,535,5.116,536,5.116,543,2.261,544,10.15,546,14.776,547,10.15,548,5.116,555,4.846,558,11.374,559,8.352,560,11.374,561,3.074,562,5.454,564,5.454,565,10.15,566,10.15,567,12.262,568,5.454,569,5.454,572,8.352,573,5.454,574,3.212,575,5.454,576,8.352,577,5.454,578,5.454,580,8.352,581,5.454,582,5.454,583,5.454,584,5.454,585,5.454,586,5.454,587,5.454,588,5.454,589,8.352,590,5.454,591,5.454,592,5.454,593,8.352,594,5.454,595,5.454,596,3.888,597,5.454,598,8.352,599,5.454,601,5.454,604,5.454,605,6.721,608,4.345,613,2.949,619,4.428,622,10.669,623,5.003,625,2.89,626,3.852,629,3.975,630,2.454,642,5.454,643,12.319,644,3.366,647,5.907,648,5.907,649,9.046,664,3.975,665,4.11,666,6.595,667,5.454,668,5.116,669,4.621,670,4.846,671,6.595,672,4.621,673,5.907,674,5.454,675,2.539,676,4.846,677,6.595,678,12.273,679,6.595,680,3.074,681,10.1,682,6.595,683,10.1,684,6.595,685,6.595,686,6.595,687,6.595,688,6.595,689,6.595,690,6.595,691,6.595,692,6.595,693,6.595,694,6.595,695,6.595]],["keywords/15",[]],["title/16",[696,1066.856,697,572.688]],["content/16",[]],["keywords/16",[]],["title/17",[698,702.378,699,905.483,700,396.796]],["content/17",[208,5.487,236,10.623,319,2.824,402,4.549,404,5.365,406,11.326,412,11.733,701,9.595,702,9.595,703,10.062,704,11.326,705,12.266,706,9.595,707,10.093,708,10.623,709,10.436,710,10.623,711,10.623,712,10.623,713,10.623,714,10.623,715,13.695,716,13.695,717,12.991,718,10.623,719,13.695,720,5.272,721,3.222,722,13.695,723,7.351,724,13.695]],["keywords/17",[]],["title/18",[402,354.397,411,544.542]],["content/18",[18,3.632,154,5.272,319,2.069,382,5.272,402,5.737,412,12.958,496,8.98,596,5.548,669,10.096,709,11.525,710,11.178,711,11.178,712,11.178,713,11.178,714,11.178,725,4.436,726,4.787,727,14.411,728,14.411,729,12.908,730,14.411,731,14.411,732,14.411,733,14.411,734,14.411]],["keywords/18",[]],["title/19",[411,462.175,703,665.279,735,811.045]],["content/19",[86,1.54,319,2.657,334,10.747,402,5.386,411,6.633,412,11.359,460,6.329,496,8.098,596,6.804,703,13.991,709,10.103,710,10.08,711,10.08,712,10.08,713,10.08,714,10.08,717,10.08,723,6.976,736,12.995,737,12.995,738,12.995,739,9.772,740,12.995,741,7.832,742,9.548,743,8.393,744,5.81,745,8.098,746,12.995,747,12.995,748,9.548,749,10.08,750,12.995,751,12.995,752,12.995,753,12.995,754,12.995,755,12.995,756,12.995,757,12.995,758,12.995,759,12.995]],["keywords/19",[]],["title/20",[411,544.542,704,882.296]],["content/20",[7,2.539,11,4.461,20,2.115,54,3.033,66,2.586,86,0.754,91,2.634,115,3.033,131,4.349,156,5.924,170,4.788,208,2.981,245,1.239,294,8.72,305,3.331,312,2.082,319,2.97,353,7.013,357,3.851,358,3.94,368,5.265,377,2.906,402,5.123,409,5.25,411,3.25,412,10.223,460,3.101,474,3.331,482,4.461,496,3.967,507,4.461,550,7.625,596,2.451,629,3.837,675,4.622,700,5.916,701,9.459,702,6.887,703,7.222,704,12.067,709,8.413,710,7.625,711,7.625,712,7.625,713,7.625,714,7.625,717,4.939,725,1.96,729,5.703,739,3.837,743,4.112,745,6.125,748,9.92,749,4.939,760,5.703,761,3.967,762,6.367,763,6.367,764,2.684,765,5.703,766,2.451,767,6.367,768,6.367,769,6.367,770,6.367,771,6.367,772,6.367,773,6.367,774,6.367,775,2.684,776,12.006,777,6.367,778,9.796,779,6.367,780,13.501,781,6.367,782,6.367,783,6.367,784,4.461,785,6.367,786,9.83,787,4.275,788,6.367,789,5.703,790,6.367,791,6.367,792,6.367,793,5.703,794,3.611,795,13.501,796,9.313,797,3.101,798,2.02,799,3.611,800,6.367,801,3.967,802,3.967,803,6.367,804,12.093,805,9.83,806,9.83,807,5.703,808,5.703,809,4.678,810,5.703,811,7.222,812,9.83,813,12.006,814,6.367,815,12.006,816,6.367,817,9.83,818,9.83,819,14.591,820,4.144,821,6.367,822,3.837,823,5.703,824,6.367,825,8.129,826,3.101,827,3.25,828,4.939,829,6.367,830,9.83,831,9.83,832,6.367,833,2.736,834,6.348,835,6.367,836,6.367,837,5.703,838,6.367,839,12.006,840,6.367,841,6.367,842,6.367,843,6.367,844,6.367,845,6.367,846,4.678,847,6.367,848,6.367,849,6.367,850,6.367,851,4.939,852,6.367,853,6.367,854,6.367,855,9.83,856,6.367,857,6.367,858,9.83,859,6.367,860,6.367,861,6.367,862,5.265,863,6.367,864,6.367,865,6.367,866,6.367,867,6.367,868,6.367,869,6.367,870,6.367]],["keywords/20",[]],["title/21",[871,497.261,872,882.296]],["content/21",[]],["keywords/21",[]],["title/22",[721,163.547,873,510.763,874,317.262,875,695.177,876,695.177]],["content/22",[20,3.407,22,1.65,23,1.541,34,2.271,68,2.837,98,2.514,100,2.421,130,5.792,141,2.072,142,2.344,145,1.327,147,3.711,154,2.462,167,2.201,221,9.131,233,2.103,274,4.056,275,2.382,308,1.673,312,2.201,319,2.984,344,3.071,353,3.931,357,4.018,358,3.046,402,4.97,409,3.69,418,2.591,430,2.733,608,2.382,613,3.009,623,2.271,627,3.931,635,3.009,721,2.924,741,4.056,798,2.135,820,6.91,873,4.944,874,3.071,877,2.041,878,6.028,879,7.259,880,8.976,881,12.716,882,6.729,883,6.729,884,6.729,885,5.22,886,6.729,887,9.187,888,13.557,889,13.4,890,6.729,891,6.729,892,6.729,893,6.729,894,7.186,895,6.729,896,10.256,897,10.256,898,7.956,899,10.256,900,6.729,901,11.131,902,6.729,903,6.729,904,6.729,905,10.256,906,6.729,907,5.565,908,4.715,909,10.256,910,4.518,911,9.187,912,10.256,913,3.711,914,4.193,915,6.729,916,6.729,917,10.256,918,10.256,919,10.256,920,7.535,921,6.729,922,6.729,923,6.729,924,6.729,925,6.729,926,6.729,927,6.729,928,8.707,929,6.729,930,6.028,931,6.729,932,6.028,933,5.565,934,9.187,935,6.028,936,6.729,937,6.028,938,6.729,939,6.729,940,6.028,941,5.235,942,6.729,943,6.729,944,12.427,945,6.729,946,6.729,947,3.816,948,6.729,949,6.028,950,5.565,951,6.028,952,12.427,953,6.729,954,6.028,955,15.764,956,6.729,957,14.961,958,11.494,959,6.729,960,6.729,961,6.729,962,6.729,963,6.028,964,6.729,965,6.729,966,6.729,967,6.729,968,8.707,969,6.729,970,6.729,971,6.729,972,6.729,973,6.729,974,6.729,975,3.521,976,6.028,977,3.612,978,4.193,979,3.931,980,4.346,981,10.256,982,6.729,983,6.729,984,6.729,985,3.816,986,6.028,987,6.729]],["keywords/22",[]],["title/23",[402,300.791,721,213.024,988,665.279]],["content/23",[1,9.25,18,3.327,73,3.192,142,4.599,216,2.786,307,4.188,308,3.281,312,4.318,319,2.799,353,7.712,374,3.777,613,5.903,706,9.25,721,3.852,846,9.7,874,6.025,941,6.739,986,11.826,989,8.527,990,8.227,991,10.241,992,9.25,993,10.241,994,13.203,995,10.241,996,10.919,997,12.03,998,10.241,999,10.919,1000,9.25,1001,10.919,1002,13.203,1003,13.203,1004,10.919,1005,13.203,1006,18.609,1007,10.919,1008,13.203,1009,10.919,1010,13.203,1011,13.203]],["keywords/23",[]],["title/24",[289,354.397,1012,783.844]],["content/24",[13,2.686,18,1.514,22,2.304,79,3.682,108,2.486,131,1.935,135,2.06,145,1.185,154,3.438,160,2.686,170,2.926,191,2.862,208,1.822,223,4.038,229,3.067,233,1.878,239,1.433,252,2.995,282,9.076,305,3.143,307,1.906,319,2.906,357,6.165,358,1.473,402,4.718,411,3.067,417,3.438,418,2.313,456,2.093,499,2.027,574,5.636,596,3.618,624,1.285,625,5.071,672,4.209,675,2.313,720,2.313,721,3.341,723,7.025,725,1.85,760,5.382,764,2.533,766,2.313,799,3.407,820,3.961,822,5.663,846,4.414,871,2.8,872,4.969,874,8.466,877,1.822,881,4.661,941,5.907,990,8.155,991,11.017,992,4.209,993,11.017,995,8.976,996,7.771,997,11.064,1000,4.209,1004,7.771,1007,7.771,1009,7.771,1013,6.069,1014,7.77,1015,6.008,1016,6.62,1017,9.397,1018,7.888,1019,3.744,1020,3.313,1021,3.621,1022,4.661,1023,6.008,1024,4.969,1025,5.382,1026,4.661,1027,5.382,1028,4.661,1029,5.382,1030,5.382,1031,5.382,1032,11.572,1033,6.008,1034,6.008,1035,7.771,1036,5.382,1037,5.382,1038,9.397,1039,6.008,1040,9.397,1041,6.008,1042,9.397,1043,6.008,1044,9.397,1045,6.008,1046,5.382,1047,8.417,1048,4.661,1049,3.744,1050,4.969,1051,5.382,1052,5.382,1053,5.382,1054,4.661,1055,5.382,1056,5.382,1057,5.382,1058,5.382,1059,11.722,1060,5.382,1061,8.417,1062,5.382,1063,5.382,1064,5.382,1065,11.722,1066,5.382,1067,5.382,1068,5.382,1069,5.382,1070,5.382,1071,5.382,1072,8.417,1073,8.417,1074,8.417,1075,10.365,1076,5.382,1077,5.382,1078,5.382,1079,5.382,1080,5.382,1081,5.382,1082,5.382,1083,5.382,1084,5.382,1085,5.382,1086,5.382,1087,5.382,1088,4.414,1089,5.382,1090,4.414,1091,5.382,1092,5.382,1093,5.382,1094,8.417,1095,15.336,1096,15.336,1097,10.365,1098,4.209,1099,6.008,1100,6.008,1101,6.008,1102,6.008,1103,6.008,1104,9.397,1105,6.008,1106,6.008,1107,6.008,1108,5.382,1109,6.008,1110,6.008,1111,6.008,1112,5.382,1113,6.008,1114,6.008,1115,6.008,1116,6.008,1117,6.008,1118,5.382,1119,3.067,1120,4.661,1121,6.008,1122,4.209,1123,6.008,1124,6.008,1125,4.209,1126,4.661,1127,4.661,1128,5.382,1129,6.583,1130,5.382,1131,5.382,1132,5.382,1133,4.661]],["keywords/24",[]],["title/25",[109,374.625,350,374.625,720,302.794,1016,366.594]],["content/25",[22,1.694,86,0.819,116,2.239,125,3.588,145,1.363,167,2.261,179,2.529,216,1.459,229,3.528,233,2.16,282,9.6,305,3.616,307,2.193,319,2.938,336,2.859,357,6.482,358,1.694,402,4.196,404,2.708,417,3.829,456,2.408,499,2.332,574,5.098,624,1.479,638,4.166,720,4.03,721,3.315,723,5.619,799,3.92,820,4.412,822,6.309,827,3.528,874,8.247,881,5.362,941,6.448,990,6.522,991,8.119,992,4.843,993,8.119,997,11.703,1000,4.843,1004,8.656,1007,8.656,1009,8.656,1014,4.641,1016,6.568,1018,4.166,1024,5.716,1025,6.191,1026,5.362,1027,6.191,1028,5.362,1030,6.191,1031,6.191,1035,10.447,1036,6.191,1037,6.191,1046,6.191,1047,9.376,1048,5.362,1049,4.307,1050,5.716,1051,6.191,1052,6.191,1053,6.191,1054,5.362,1055,6.191,1056,6.191,1057,6.191,1058,6.191,1059,12.621,1060,6.191,1061,9.376,1062,6.191,1063,6.191,1064,6.191,1065,12.621,1066,6.191,1067,6.191,1068,6.191,1069,6.191,1070,6.191,1071,6.191,1072,9.376,1073,9.376,1074,9.376,1075,11.315,1076,6.191,1077,6.191,1078,6.191,1079,6.191,1080,6.191,1081,6.191,1082,6.191,1083,6.191,1084,6.191,1085,6.191,1086,6.191,1087,6.191,1089,6.191,1090,5.079,1091,6.191,1092,6.191,1093,6.191,1094,9.376,1095,15.929,1096,15.929,1097,9.376,1098,7.333,1108,6.191,1112,9.376,1129,4.843,1134,3.71,1135,3.029,1136,6.912,1137,5.079,1138,8.656,1139,6.912,1140,10.467,1141,6.912,1142,10.467,1143,6.912,1144,10.467,1145,6.912,1146,10.467,1147,6.912,1148,6.912,1149,6.912,1150,6.912,1151,6.912,1152,6.912,1153,6.912,1154,14.091,1155,6.912,1156,6.912,1157,6.912,1158,6.912,1159,6.912,1160,6.912,1161,6.912,1162,6.912,1163,4.307,1164,6.912,1165,4.307,1166,5.362]],["keywords/25",[]],["title/26",[524,371.602,1167,955.587]],["content/26",[22,2.781,49,7.328,79,4.445,98,2.781,135,3.889,141,3.493,160,5.073,191,7.081,212,3.599,216,2.394,239,3.545,250,5.655,308,2.82,404,4.445,418,4.368,596,4.368,605,4.875,625,6.514,673,10.163,675,4.368,720,6.383,721,4.297,723,9.445,766,4.368,872,12.294,874,8.03,990,9.263,991,8.801,993,8.801,995,8.801,997,8.336,1014,7.618,1016,8.513,1018,8.959,1021,6.838,1022,8.801,1098,7.949,1130,13.315,1131,13.315,1132,10.163,1133,8.801,1135,4.972,1165,9.263,1168,9.383,1169,6.838,1170,11.346,1171,11.346,1172,7.07,1173,11.346,1174,10.163,1175,7.949,1176,11.346,1177,6.434,1178,5.936,1179,8.336,1180,11.346,1181,7.07,1182,7.949,1183,10.415,1184,10.163,1185,3.828,1186,10.163,1187,11.346,1188,11.346,1189,4.445,1190,8.336]],["keywords/26",[]],["title/27",[1191,882.296,1192,827.555]],["content/27",[]],["keywords/27",[]],["title/28",[1193,955.587,1194,783.844]],["content/28",[22,1.332,57,5.818,66,3.526,68,2.291,73,2.099,96,5.607,98,1.332,100,5.658,108,2.249,114,3.649,119,4.216,125,3.716,135,1.863,138,6.082,141,2.673,145,1.712,153,2.884,154,1.988,170,2.647,179,1.988,190,2.754,206,2.589,239,1.296,245,1.689,300,2.382,307,1.724,319,2.726,324,3.994,347,7.92,358,3.536,374,1.555,402,5.223,409,5.658,415,10.889,422,6.644,447,4.032,449,2.796,456,1.893,492,3.511,499,3.657,508,2.481,510,9.601,596,4.765,613,2.43,625,3.804,629,5.232,630,3.23,635,3.881,644,2.774,721,3.814,725,2.673,726,1.806,739,9.124,794,4.923,820,6.08,877,1.649,898,6.734,941,6.317,950,10.236,989,3.511,1134,2.918,1135,2.382,1137,3.994,1166,4.216,1185,1.834,1191,8.964,1192,11.188,1193,4.869,1194,13.595,1195,4.216,1196,4.869,1197,4.869,1198,2.918,1199,2.997,1200,5.436,1201,4.869,1202,9.709,1203,8.682,1204,4.495,1205,3.994,1206,4.495,1207,8.682,1208,6.734,1209,5.436,1210,5.436,1211,5.436,1212,4.869,1213,5.436,1214,5.436,1215,4.216,1216,3.511,1217,11.928,1218,10.105,1219,8.964,1220,10.494,1221,3.511,1222,4.216,1223,2.844,1224,3.276,1225,3.649,1226,4.869,1227,4.869,1228,4.869,1229,5.436,1230,4.869,1231,4.869,1232,4.869,1233,5.436,1234,5.436,1235,5.436,1236,4.869,1237,4.869,1238,4.869,1239,8.682,1240,7.776,1241,7.776,1242,7.776,1243,7.776,1244,7.776,1245,7.18,1246,5.436,1247,7.776,1248,7.776,1249,8.682,1250,8.682,1251,6.734,1252,8.682,1253,8.682,1254,4.869,1255,4.869,1256,3.994,1257,10.839,1258,5.769,1259,7.776,1260,3.808,1261,7.18,1262,4.869,1263,8.964,1264,3.276,1265,9.709,1266,3.994,1267,12.377,1268,8.682,1269,6.379,1270,8.682,1271,5.436,1272,7.776,1273,5.436,1274,7.18,1275,7.776,1276,8.682,1277,8.682,1278,8.682,1279,7.776,1280,5.436,1281,5.436,1282,8.682,1283,7.46,1284,3.66,1285,7.776,1286,4.495,1287,3.994,1288,5.436,1289,4.495,1290,3.511,1291,5.436,1292,3.649,1293,6.331,1294,5.436,1295,4.869,1296,4.869,1297,4.869,1298,8.682,1299,7.776,1300,5.436,1301,7.776,1302,4.869,1303,5.436,1304,5.436,1305,5.436,1306,3.808,1307,3.387,1308,3.276,1309,4.869,1310,5.436]],["keywords/28",[]],["title/29",[1311,715.826]],["content/29",[22,3.343,25,6.961,57,7.321,68,5.749,125,4.675,201,8.498,209,8.808,239,3.253,252,6.797,381,6.797,456,4.75,508,6.224,526,5.439,624,2.917,721,3.93,739,10.068,833,5.86,1189,5.343,1190,10.02,1192,12.958,1194,12.273,1195,12.958,1208,10.579,1217,11.279,1218,9.555,1219,11.279,1220,10.579,1289,11.279,1308,8.22,1312,13.638,1313,11.279,1314,10.579,1315,5.976,1316,9.157,1317,13.638,1318,11.279,1319,7.966,1320,6.961]],["keywords/29",[]],["title/30",[1195,827.555,1321,783.844]],["content/30",[3,3.186,18,0.701,20,0.924,21,1.13,22,1.967,23,1.129,25,2.516,34,1.663,57,1.494,58,1.734,68,1.173,73,0.673,74,1.898,86,1.301,89,1.22,91,1.151,95,2.971,96,1.797,98,0.682,100,1.001,110,1.456,116,1.054,117,1.869,125,0.954,127,3.093,135,2.275,140,1.387,141,1.518,142,0.969,145,0.549,147,1.535,158,4.135,167,3.001,184,1.297,188,3.662,190,0.883,195,1.734,208,4.052,209,1.797,215,2.298,218,5.943,219,0.924,229,1.421,233,2.074,239,2.789,245,0.959,249,4.285,250,3.999,255,2.159,256,1.966,275,0.985,279,1.95,299,1.626,300,1.22,308,0.692,309,1.677,312,2.17,316,1.22,319,2.842,328,1.244,333,1.071,344,2.25,346,3.516,347,8.202,357,1.09,358,3.565,365,2.16,370,5.447,389,1.387,402,4.092,409,5.723,415,10.073,417,1.803,422,7.406,431,1.22,444,4.649,447,2.468,449,2.584,451,3.454,456,1.717,459,3.093,474,2.579,481,1.421,483,1.774,492,3.184,499,1.663,508,1.27,510,6.224,561,1.297,574,3.232,596,3.906,624,1.054,626,1.626,627,2.879,630,1.035,637,1.626,669,1.95,670,2.045,672,1.95,680,1.297,701,1.95,702,1.95,707,5.53,718,2.159,721,3.567,725,2.47,726,0.924,739,8.052,761,1.734,764,3.382,766,6.28,794,1.578,797,1.356,798,0.883,801,1.734,802,1.734,820,4.627,834,3.184,862,2.302,874,1.27,914,1.734,941,6.288,947,1.578,950,8.391,968,3.454,977,1.494,989,3.184,1019,5.718,1021,2.971,1026,2.159,1028,2.159,1050,2.302,1054,2.159,1129,1.95,1135,1.22,1137,7.455,1167,2.493,1172,1.734,1175,1.95,1185,0.939,1189,1.09,1190,2.045,1191,10.188,1192,3.824,1194,4.875,1195,6.224,1196,9.088,1197,9.088,1199,2.718,1202,4.415,1208,2.159,1217,11.049,1218,10.19,1219,7.588,1220,7.871,1224,1.677,1226,4.415,1227,2.493,1228,2.493,1230,2.493,1231,7.187,1232,4.415,1236,2.493,1237,2.493,1238,2.493,1240,7.187,1241,8.219,1242,7.187,1243,7.187,1244,8.219,1245,6.636,1247,7.187,1248,7.187,1254,2.493,1255,2.493,1256,2.045,1258,5.116,1259,4.415,1260,1.95,1261,4.077,1262,2.493,1263,2.302,1265,7.187,1266,2.045,1269,7.455,1272,9.088,1274,4.077,1275,9.088,1279,9.088,1283,4.836,1285,2.493,1286,2.302,1293,3.876,1295,2.493,1296,2.493,1297,2.493,1299,4.415,1301,4.415,1302,2.493,1309,5.943,1311,1.535,1319,1.626,1321,4.875,1322,4.573,1323,2.783,1324,4.93,1325,2.783,1326,2.783,1327,2.783,1328,2.971,1329,2.971,1330,6.635,1331,2.783,1332,2.045,1333,1.11,1334,1.677,1335,2.159,1336,2.783,1337,2.302,1338,3.184,1339,11.694,1340,2.159,1341,2.493,1342,2.783,1343,2.783,1344,2.783,1345,2.783,1346,1.326,1347,2.159,1348,7.957,1349,1.535,1350,2.579,1351,2.783,1352,2.783,1353,2.783,1354,2.783,1355,2.783,1356,2.783,1357,2.783,1358,4.93,1359,2.783,1360,2.783,1361,8.024,1362,10.147,1363,10.147,1364,11.035,1365,10.147,1366,2.783,1367,10.147,1368,10.147,1369,3.184,1370,4.93,1371,4.93,1372,1.626,1373,3.072,1374,2.783,1375,2.159,1376,2.745,1377,2.783,1378,2.493,1379,2.302,1380,1.626,1381,2.783,1382,2.783,1383,2.783,1384,2.783,1385,2.783,1386,4.93,1387,2.783,1388,4.93,1389,2.783,1390,4.93,1391,2.783,1392,2.045,1393,4.93,1394,2.302,1395,1.456,1396,2.493,1397,2.783,1398,2.493,1399,1.677,1400,2.302,1401,3.31,1402,1.834,1403,3.622,1404,2.783,1405,4.93,1406,2.783,1407,2.783,1408,2.783,1409,1.869,1410,2.045,1411,2.783,1412,1.95,1413,2.493,1414,2.783,1415,2.783,1416,2.302,1417,2.783,1418,6.635,1419,4.93,1420,2.783,1421,4.415,1422,2.783,1423,2.783,1424,4.93,1425,2.783,1426,2.783,1427,2.783,1428,2.783,1429,7.187,1430,2.302,1431,2.783,1432,1.151,1433,2.045,1434,2.159,1435,2.493,1436,1.95,1437,1.95,1438,3.454,1439,1.677,1440,1.535,1441,2.783,1442,2.159,1443,2.783,1444,2.302,1445,1.95,1446,2.493,1447,1.869,1448,2.493,1449,2.783,1450,4.93,1451,2.783,1452,2.783,1453,4.93,1454,2.783,1455,2.783,1456,4.93,1457,2.783,1458,2.783,1459,4.93,1460,2.783,1461,2.783,1462,6.635,1463,1.869,1464,2.159,1465,2.783,1466,2.745,1467,2.783,1468,6.635,1469,2.783,1470,4.93,1471,4.93,1472,2.783,1473,2.783,1474,2.783,1475,2.783,1476,4.415,1477,1.421,1478,4.93,1479,2.783,1480,4.93,1481,2.493,1482,2.783,1483,2.783,1484,2.783,1485,2.783,1486,2.783,1487,2.783,1488,2.783,1489,4.93,1490,8.024,1491,4.93,1492,2.783,1493,2.493,1494,2.783,1495,2.783,1496,2.783,1497,2.783,1498,2.783,1499,2.783,1500,1.95,1501,2.783,1502,7.117,1503,2.783,1504,2.783,1505,2.783,1506,2.783]],["keywords/30",[]],["title/31",[115,431.291,1165,564.238,1507,905.483]],["content/31",[]],["keywords/31",[]],["title/32",[1307,564.238,1508,811.045,1509,607.94]],["content/32",[3,2.465,6,4.558,19,4.816,34,4.807,73,2.053,86,1.006,98,2.082,104,3.269,115,8.171,145,2.81,147,4.682,160,5.447,190,3.865,215,3.958,216,3.729,219,2.821,245,2.371,275,3.006,299,4.96,306,8.847,312,2.777,316,3.721,319,2.366,346,3.721,358,3.493,376,5.118,382,5.212,416,3.958,417,3.106,430,3.449,447,3.159,460,5.934,499,2.865,543,2.911,552,7.606,619,5.701,624,1.816,720,5.993,723,4.558,725,3.75,726,2.821,766,6.802,894,5.949,1018,5.118,1127,6.587,1134,4.558,1165,11.639,1185,2.865,1189,3.327,1223,4.443,1307,5.291,1319,4.96,1322,4.232,1402,3.159,1416,10.075,1466,3.513,1509,5.701,1510,6.587,1511,4.558,1512,8.492,1513,8.492,1514,8.492,1515,8.492,1516,8.492,1517,5.118,1518,11.01,1519,7.606,1520,9.45,1521,8.492,1522,8.827,1523,8.492,1524,8.492,1525,8.322,1526,5.701,1527,11.437,1528,8.492,1529,8.492,1530,7.606,1531,12.183,1532,17.154,1533,8.492,1534,4.682,1535,5.484,1536,8.492,1537,7.606,1538,7.606,1539,8.492,1540,8.492,1541,8.492,1542,12.183,1543,15.566,1544,8.492,1545,15.566,1546,8.492,1547,8.492,1548,8.492,1549,8.492,1550,12.183,1551,8.492,1552,8.492,1553,8.492,1554,8.492,1555,8.492,1556,4.045,1557,7.606,1558,5.701,1559,7.606,1560,8.492,1561,8.492,1562,7.606]],["keywords/32",[]],["title/33",[499,359.982,1563,827.555]],["content/33",[11,9.576,34,3.377,86,1.186,104,3.853,108,4.14,135,3.43,145,3.299,179,3.661,208,3.035,216,3.695,219,3.324,239,2.387,286,5.675,299,5.846,300,4.385,306,9.932,308,2.487,333,3.853,358,3.351,365,4.385,374,3.911,376,6.031,381,4.988,382,3.661,447,3.723,459,4.664,460,8.147,474,5.236,492,6.463,499,3.377,543,3.43,624,2.924,635,4.474,675,3.853,680,4.664,720,6.741,725,3.081,726,3.324,743,6.463,744,4.474,745,8.517,761,6.236,766,6.44,1016,4.664,1018,8.238,1165,10.912,1199,5.518,1223,5.236,1333,3.991,1372,5.846,1402,3.723,1416,11.303,1466,4.14,1517,8.238,1518,11.529,1522,5.675,1525,5.846,1526,6.719,1527,7.353,1537,8.964,1564,8.964,1565,4.767,1566,6.463,1567,10.007,1568,10.007,1569,8.276,1570,10.007,1571,5.108,1572,8.964,1573,10.007,1574,7.763,1575,10.007,1576,7.763,1577,10.007,1578,6.657,1579,10.007,1580,8.964,1581,10.007,1582,13.668,1583,6.812,1584,7.763,1585,8.276,1586,10.007,1587,8.964,1588,10.007,1589,8.276,1590,6.463]],["keywords/33",[]],["title/34",[289,354.397,304,371.602]],["content/34",[3,1.634,18,1.419,22,2.719,23,2.89,34,1.9,49,5.766,73,3.328,86,0.667,89,2.467,100,2.026,102,4.656,116,1.91,124,1.611,125,1.93,141,2.748,145,2.188,153,1.87,156,3.393,185,1.683,212,1.786,216,2.664,219,4.866,239,1.343,265,2.094,266,2.569,289,2.966,299,3.289,304,5.102,305,5.804,306,6.777,307,4.005,308,1.399,312,1.841,319,2.907,344,4.074,353,6.48,357,2.206,358,3.095,365,3.912,374,2.554,382,4.058,389,2.806,402,3.685,404,2.206,417,2.06,447,4.127,451,6.255,454,5.694,459,5.171,460,5.403,483,2.026,496,3.508,498,7.383,596,2.167,608,1.993,644,2.874,668,4.367,675,5.299,701,6.255,706,3.944,720,5.299,721,1.324,725,2.748,726,2.966,744,4.96,745,5.563,766,6.313,796,10.678,798,1.786,833,2.419,871,2.624,877,1.708,1019,3.508,1035,4.656,1138,4.656,1165,5.563,1185,1.9,1205,4.136,1223,4.671,1264,6.686,1266,6.559,1315,2.467,1320,2.874,1376,2.329,1402,2.094,1433,8.151,1508,5.043,1509,7.448,1511,4.792,1518,11.899,1522,6.291,1527,6.559,1557,7.996,1565,2.682,1587,5.043,1590,11.933,1591,5.63,1592,3.193,1593,3.763,1594,5.63,1595,3.78,1596,5.63,1597,5.63,1598,11.094,1599,5.043,1600,3.636,1601,5.043,1602,5.63,1603,5.63,1604,5.63,1605,7.996,1606,7.996,1607,11.308,1608,5.63,1609,3.78,1610,5.043,1611,5.043,1612,4.367,1613,6.925,1614,5.043,1615,6.925,1616,9.936,1617,5.63,1618,3.393,1619,5.63,1620,5.63,1621,5.63,1622,5.63,1623,6.559,1624,5.043,1625,5.63,1626,5.63,1627,5.043,1628,5.63,1629,5.63,1630,3.78,1631,7.996,1632,14.647,1633,8.928,1634,9.936,1635,8.928,1636,7.996,1637,5.63,1638,5.63,1639,5.043,1640,11.308,1641,8.928,1642,5.63,1643,5.63,1644,5.63,1645,5.63,1646,5.63,1647,5.63,1648,5.63,1649,5.63,1650,5.63,1651,5.63,1652,5.63,1653,5.63,1654,5.63,1655,5.63,1656,5.63,1657,8.928,1658,8.928,1659,7.996,1660,5.043,1661,8.928,1662,5.63,1663,5.63,1664,5.63,1665,4.656,1666,5.63,1667,5.043,1668,5.63,1669,5.63,1670,5.63]],["keywords/34",[]],["title/35",[1172,808.967]],["content/35",[16,6.305,22,4.074,23,3.097,102,11.187,109,6.443,124,3.87,201,8.429,216,2.855,232,9.938,233,5.194,239,3.226,250,8.284,308,3.362,344,6.173,359,7.901,382,4.948,454,5.596,460,6.588,484,6.742,700,5.928,720,5.208,726,4.493,745,8.429,871,6.305,1020,7.458,1165,10.357,1216,8.736,1223,7.077,1509,12.6,1518,11.212,1590,8.736,1671,12.116,1672,10.493,1673,9.477,1674,13.527,1675,12.116]],["keywords/35",[]],["title/36",[333,348.594,1676,584.8,1677,905.483]],["content/36",[49,10.051,115,7.413,216,3.284,619,10.449,635,6.958,999,12.871,1165,9.698,1518,9.698,1678,13.94,1679,9.698,1680,15.563,1681,15.563,1682,15.563]],["keywords/36",[]],["title/37",[86,93.195,1518,490.104,1527,577.87,1590,507.965]],["content/37",[]],["keywords/37",[]],["title/38",[1683,827.555,1684,882.296]],["content/38",[3,3.984,18,2.537,20,3.345,22,2.468,34,3.397,48,5.551,53,4.163,73,2.434,77,6.068,79,3.945,100,4.938,134,4.165,141,3.1,142,3.507,145,2.707,153,3.345,154,3.683,160,4.501,170,4.904,172,8.326,190,3.194,216,3.295,223,4.326,245,1.959,289,3.345,297,7.397,307,3.194,336,4.165,342,7.054,358,3.364,359,5.881,374,4.468,418,5.284,460,6.685,554,6.068,555,7.397,596,3.876,605,4.326,723,5.405,725,5.402,745,6.274,766,7.261,796,14.047,798,4.354,871,4.693,874,6.263,877,3.054,1134,5.405,1165,6.274,1185,4.631,1189,3.945,1293,8.017,1308,6.068,1320,5.139,1432,4.165,1517,6.068,1518,11.919,1527,10.084,1590,10.085,1600,6.502,1609,6.76,1685,5.71,1686,5.881,1687,13.724,1688,13.724,1689,9.018,1690,8.326,1691,12.293,1692,10.068,1693,11.472,1694,10.068,1695,6.76,1696,5.881,1697,5.881,1698,13.724,1699,6.76,1700,10.068,1701,10.068,1702,7.81,1703,7.397,1704,6.068]],["keywords/38",[]],["title/39",[289,354.397,304,371.602]],["content/39",[3,3.915,20,2.111,23,1.455,104,2.446,116,2.1,124,1.818,141,1.956,142,2.213,145,1.253,167,3.21,190,2.016,208,4.422,216,2.071,219,2.111,222,2.785,233,1.986,249,4.104,250,3.167,304,2.213,307,2.016,319,2.967,353,5.733,358,4.34,370,5.269,374,1.818,389,3.167,402,4.843,409,5.246,417,2.325,430,2.581,460,3.095,483,4.853,526,2.534,574,3.095,596,2.446,624,1.359,675,4.617,706,4.452,707,5.915,709,6.116,720,2.446,721,2.309,725,1.956,726,2.111,748,4.669,766,3.779,787,8.051,801,3.96,802,3.96,820,6.145,874,2.9,898,4.929,992,4.452,998,4.929,1018,3.83,1138,5.255,1178,3.325,1182,4.452,1264,5.915,1320,3.243,1328,3.83,1329,3.83,1372,3.712,1376,2.629,1433,8.811,1518,11.031,1522,7.649,1590,10.374,1601,5.692,1605,10.741,1606,13.058,1607,8.791,1613,7.613,1614,5.692,1615,7.613,1616,5.692,1623,4.669,1624,5.692,1627,5.692,1631,10.741,1634,10.741,1636,8.791,1639,5.692,1640,5.692,1660,5.692,1667,5.692,1671,5.692,1705,3.712,1706,2.9,1707,5.255,1708,4.452,1709,3.095,1710,4.266,1711,4.929,1712,3.095,1713,6.355,1714,6.355,1715,3.96,1716,5.692,1717,4.669,1718,4.669,1719,6.355,1720,4.669,1721,3.83,1722,6.355,1723,6.355,1724,6.355,1725,6.355,1726,9.815,1727,6.355,1728,6.355,1729,6.355,1730,6.355,1731,14.578,1732,9.815,1733,9.815,1734,6.355,1735,6.355,1736,6.355,1737,9.815,1738,6.355,1739,6.355,1740,6.355,1741,11.992,1742,6.355,1743,6.355,1744,6.355,1745,6.355,1746,9.815,1747,6.355,1748,5.255,1749,5.255,1750,6.355,1751,9.815,1752,9.815,1753,6.355,1754,9.815,1755,6.355,1756,6.355,1757,6.355,1758,6.355,1759,6.355,1760,6.355,1761,5.692,1762,6.355,1763,14.578,1764,6.355,1765,6.355,1766,9.815,1767,6.355,1768,9.815,1769,6.355,1770,6.355,1771,6.355,1772,6.355,1773,6.355,1774,6.355,1775,9.815,1776,6.355,1777,4.929,1778,6.355,1779,6.355,1780,6.355,1781,5.255]],["keywords/39",[]],["title/40",[73,218.94,499,305.531,1782,441.023]],["content/40",[3,1.877,18,3.055,22,1.585,34,3.357,48,7.506,68,2.726,73,1.564,74,2.489,77,3.897,90,8.91,100,2.327,119,5.016,125,3.41,134,2.675,135,2.217,136,4.029,141,1.991,145,2.391,153,2.148,162,3.223,167,4.452,185,1.933,190,4.318,191,3.08,212,3.156,219,2.148,223,2.779,239,3.247,241,5.348,245,1.936,260,4.176,300,2.834,307,4.318,308,1.607,312,2.115,319,1.74,328,2.891,333,2.489,342,10.295,346,2.834,347,5.205,358,2.439,374,1.85,382,2.366,402,2.148,409,2.327,431,4.359,449,2.083,456,2.252,460,7.873,474,3.383,483,2.327,496,8.482,499,4.958,514,3.897,524,3.465,525,4.176,526,3.967,561,5.651,596,5.657,605,2.779,627,3.777,635,2.891,644,6.188,675,2.489,697,3.471,698,5.016,720,3.83,721,1.521,723,6.508,725,1.991,726,2.148,766,6.223,775,6.194,796,5.016,798,2.051,799,3.667,826,3.149,871,3.014,877,1.961,985,3.667,1024,5.348,1122,4.53,1127,5.016,1129,4.53,1135,4.359,1163,4.029,1166,5.016,1185,2.182,1199,3.565,1261,10.026,1263,5.348,1284,2.726,1287,4.751,1293,3.777,1308,3.897,1315,2.834,1333,4.835,1346,3.08,1350,6.343,1364,8.91,1369,4.176,1376,2.675,1379,5.348,1401,4.341,1440,3.565,1509,8.14,1518,4.029,1564,5.792,1569,5.348,1584,5.016,1590,10.776,1693,11.876,1749,5.348,1781,12.833,1783,12.124,1784,6.97,1785,6.466,1786,6.466,1787,6.466,1788,9.948,1789,9.948,1790,6.466,1791,12.124,1792,13.899,1793,12.124,1794,12.124,1795,15.517,1796,6.466,1797,12.124,1798,12.124,1799,10.859,1800,5.792,1801,6.466,1802,6.466,1803,5.016,1804,12.124,1805,6.466,1806,8.791,1807,4.53,1808,6.466,1809,5.016,1810,4.53,1811,6.466,1812,6.466,1813,6.466,1814,6.466,1815,6.466,1816,6.466,1817,6.466,1818,6.466,1819,6.466,1820,6.466,1821,4.637,1822,6.466,1823,6.466,1824,10.859,1825,6.466,1826,6.466,1827,6.466,1828,6.466,1829,6.466,1830,6.466,1831,6.466,1832,6.466,1833,5.348,1834,6.466,1835,6.466,1836,6.466,1837,4.53,1838,4.751,1839,4.751,1840,6.466,1841,6.466,1842,6.466,1843,6.466,1844,5.348,1845,6.466,1846,3.667,1847,6.466]],["keywords/40",[]],["title/41",[109,374.625,250,392.002,1172,490.104,1848,551.044]],["content/41",[3,4.661,58,7.973,62,10.37,109,6.094,124,3.661,135,4.386,137,6.094,167,5.252,233,3.998,250,6.377,275,4.529,289,4.25,304,4.456,317,7.711,342,11.249,347,6.694,449,4.121,483,5.777,499,5.418,526,6.404,624,2.737,630,4.76,675,4.926,698,9.924,720,4.926,721,3.01,725,3.939,990,7.973,1122,8.964,1134,6.868,1183,8.964,1185,4.317,1224,7.711,1283,7.711,1284,5.393,1333,5.103,1341,11.46,1373,7.973,1433,9.4,1509,10.78,1590,8.263,1676,8.263,1849,11.46,1850,12.794,1851,9.924,1852,12.794,1853,12.794,1854,5.607,1855,12.794,1856,11.46,1857,10.581]],["keywords/41",[]],["title/42",[152,507.965,1016,366.594,1858,786.514,1859,551.044]],["content/42",[]],["keywords/42",[]],["title/43",[206,508.154,721,250.988]],["content/43",[3,3.78,8,4.65,18,2.351,22,2.287,23,3.434,73,3.149,86,1.106,91,3.86,110,4.881,116,1.996,124,4.292,135,3.198,142,3.25,145,1.84,152,11.029,167,3.052,203,7.237,208,4.924,209,6.026,212,2.96,216,3.166,229,4.762,233,2.916,239,2.225,245,1.815,256,3.721,275,3.303,289,3.099,308,3.237,309,5.623,312,5.586,319,2.539,333,3.592,346,4.088,357,3.655,358,3.677,382,3.413,386,4.544,405,7.716,409,3.357,458,5.814,474,4.881,483,3.357,484,4.65,629,5.623,669,6.537,707,7.848,720,3.592,721,4.018,739,5.623,801,5.814,802,5.814,871,4.349,877,2.83,880,8.41,977,5.008,978,5.814,1016,6.992,1021,5.623,1134,5.008,1169,5.623,1185,3.148,1205,6.855,1258,4.349,1289,7.716,1315,4.088,1328,5.623,1329,5.623,1337,7.716,1347,7.237,1395,6.813,1412,6.537,1437,6.537,1445,6.537,1447,6.264,1466,3.86,1717,6.855,1718,6.855,1720,6.855,1721,5.623,1839,6.855,1859,6.537,1860,9.33,1861,7.237,1862,7.237,1863,6.855,1864,9.33,1865,7.716,1866,5.623,1867,9.33,1868,9.33,1869,9.33,1870,9.33,1871,9.33,1872,9.33,1873,9.33,1874,9.33,1875,9.33,1876,9.33,1877,11.664,1878,8.357,1879,8.357,1880,6.537,1881,9.33,1882,9.33,1883,9.33,1884,9.33,1885,9.33,1886,7.716,1887,5.623,1888,9.33,1889,13.022,1890,8.41,1891,8.357,1892,5.144,1893,7.716]],["keywords/43",[]],["title/44",[56,388.117,358,152.685,1894,457.62,1895,557.886,1896,284.252,1897,515.098]],["content/44",[13,3.777,18,3.059,19,4.791,23,1.934,56,5.264,73,3.435,79,3.31,100,3.04,104,3.252,125,2.896,145,1.666,152,11.06,164,3.702,167,3.97,180,5.456,184,3.938,188,3.856,190,2.68,191,6.767,198,4.658,208,2.562,239,2.015,274,5.092,286,4.791,307,2.68,319,2.804,357,6.444,358,3.483,382,3.091,389,4.211,416,3.938,418,3.252,449,3.91,451,5.919,453,4.535,454,3.495,456,4.228,499,2.851,524,2.943,605,3.63,608,2.991,672,5.919,680,3.938,701,5.919,721,3.87,725,2.601,761,5.264,775,3.561,1016,6.622,1098,10.88,1126,6.553,1134,4.535,1135,5.319,1137,6.207,1185,2.851,1223,4.42,1258,3.938,1315,3.702,1439,9.36,1447,5.672,1466,3.495,1556,4.024,1706,5.539,1810,5.919,1821,3.938,1866,7.316,1879,10.872,1880,8.504,1887,7.316,1896,6.483,1897,10.038,1898,5.919,1899,8.448,1900,12.138,1901,8.448,1902,8.448,1903,4.935,1904,8.448,1905,8.448,1906,12.138,1907,10.872,1908,12.138,1909,7.567,1910,12.138,1911,4.935,1912,8.448,1913,8.448,1914,8.448,1915,8.448,1916,8.448,1917,8.448,1918,8.448,1919,8.448,1920,8.448,1921,8.448,1922,8.448,1923,7.567,1924,8.448,1925,7.567,1926,8.448,1927,8.448,1928,8.448,1929,8.448,1930,12.138,1931,8.448,1932,8.448,1933,6.207,1934,8.448,1935,14.206,1936,8.448,1937,8.448,1938,8.448,1939,8.448,1940,7.567,1941,8.448,1942,8.448,1943,8.448,1944,8.448,1945,8.448,1946,8.448,1947,10.872,1948,8.448,1949,8.448,1950,8.448,1951,8.448,1952,6.553,1953,7.567,1954,6.553,1955,7.567]],["keywords/44",[]],["title/45",[56,433.189,608,246.084,1894,510.763,1895,622.673,1956,622.673]],["content/45",[20,3.988,22,3.31,27,2.906,41,2.847,56,10.016,57,3.418,58,3.967,62,4.112,64,3.033,73,2.377,77,5.924,81,3.418,86,1.729,89,2.79,98,3.31,104,2.451,125,2.183,141,3.696,142,2.218,145,1.939,153,2.115,164,2.79,184,2.968,208,2.981,212,2.02,219,3.988,232,4.678,233,3.072,239,1.518,245,1.239,250,3.173,289,2.115,307,3.118,308,2.443,312,3.215,315,4.112,319,2.446,333,2.451,346,4.307,358,2.41,377,2.906,381,3.173,389,3.173,402,3.265,413,4.461,431,2.79,447,3.657,453,5.276,457,5.703,458,10.016,499,2.148,554,3.837,561,4.582,596,2.451,635,4.395,637,3.719,721,2.825,725,1.96,726,3.265,775,5.691,797,4.788,810,5.703,820,4.144,827,3.25,871,2.968,880,6.348,908,6.887,1014,4.275,1016,6.293,1020,3.511,1098,4.461,1126,4.939,1163,6.125,1175,4.461,1185,4.556,1222,4.939,1258,6.293,1283,3.837,1320,3.25,1372,3.719,1376,2.634,1402,2.369,1409,4.275,1410,7.222,1439,9.294,1447,6.6,1466,4.066,1556,3.033,1609,4.275,1706,2.906,1800,5.703,1838,4.678,1854,2.79,1861,4.939,1866,3.837,1877,5.703,1887,5.924,1893,9.929,1894,9.92,1896,5.479,1897,5.265,1907,5.703,1940,8.804,1947,15.259,1954,4.939,1955,5.703,1956,8.804,1957,6.367,1958,9.83,1959,9.83,1960,6.367,1961,6.367,1962,9.83,1963,5.703,1964,6.367,1965,5.703,1966,6.125,1967,5.265,1968,6.367,1969,3.611,1970,4.939,1971,6.367,1972,14.591,1973,6.367,1974,6.367,1975,6.367,1976,4.939,1977,4.275,1978,9.83,1979,9.83,1980,6.367,1981,3.837,1982,5.703,1983,9.96,1984,6.367,1985,4.678,1986,5.703,1987,5.703,1988,4.461,1989,6.367,1990,12.006,1991,5.703,1992,6.367,1993,6.367,1994,12.006,1995,9.83,1996,9.83,1997,6.367,1998,9.83,1999,9.83,2000,9.83,2001,13.501,2002,9.83,2003,8.804,2004,9.83,2005,9.83,2006,9.83,2007,9.83,2008,9.83,2009,9.83,2010,9.83,2011,13.501,2012,9.83,2013,9.83,2014,8.804,2015,9.83,2016,6.367,2017,5.265,2018,9.83,2019,5.703,2020,4.461,2021,5.703,2022,6.367,2023,3.719,2024,6.367,2025,6.367,2026,3.033,2027,4.461,2028,4.678]],["keywords/45",[]],["title/46",[358,221.971,766,348.594,1172,564.238]],["content/46",[3,3.671,22,3.908,34,4.268,56,7.881,62,8.168,74,4.869,86,1.499,98,3.1,100,5.736,125,4.336,152,10.295,198,6.974,219,4.201,233,4.981,239,3.016,244,8.491,245,3.102,260,8.168,280,11.328,289,4.201,315,8.168,319,1.816,430,5.136,458,7.881,459,5.895,526,5.044,625,5.542,721,3.75,775,5.331,797,6.16,799,7.172,1016,5.895,1022,9.811,1168,10.46,1178,6.617,1190,9.292,1222,9.811,1283,7.623,1509,8.491,1565,6.024,1865,10.46,1866,7.623,1880,8.861,1909,11.328,2020,8.861,2029,11.712,2030,8.861,2031,12.647,2032,12.647,2033,12.647,2034,12.647,2035,9.811,2036,12.647,2037,12.647,2038,12.647]],["keywords/46",[]],["title/47",[1863,953.834]],["content/47",[86,1.761,116,3.18,208,4.508,319,2.69,389,7.408,721,4.409,1862,11.53,2039,14.864,2040,14.864,2041,17.593,2042,14.864,2043,13.314,2044,14.864,2045,14.864,2046,14.864,2047,14.864,2048,14.864,2049,14.864]],["keywords/47",[]],["title/48",[2050,909.555]],["content/48",[]],["keywords/48",[]],["title/49",[833,557.854]],["content/49",[3,3.671,20,4.201,22,3.1,23,3.649,86,1.889,91,5.232,111,8.168,130,7.43,145,2.494,185,4.764,245,2.461,265,4.705,308,3.143,316,8.03,346,5.542,374,3.619,404,6.839,665,7.881,672,11.168,877,3.836,1019,7.881,1179,11.712,1189,4.955,1220,12.365,1559,11.328,1821,8.542,2050,11.168,2051,9.811,2052,9.811,2053,15.623,2054,12.647,2055,12.647,2056,12.647,2057,10.46,2058,11.328,2059,12.647,2060,15.155,2061,11.328,2062,12.647]],["keywords/49",[]],["title/50",[721,305.42]],["content/50",[3,4.201,86,2.275,116,3.096,179,5.295,185,4.326,233,4.523,265,5.384,294,9.348,353,8.454,798,4.592,1134,7.769,1189,5.671,1283,8.723,1284,6.101,1372,8.454,1574,11.227,1837,10.141,1866,8.723,2050,12.133,2051,11.227,2063,14.321,2064,14.474,2065,10.634,2066,14.474]],["keywords/50",[]],["title/51",[697,696.885]],["content/51",[3,1.573,18,3.404,20,2.876,21,2.2,22,3.311,23,2.476,55,3.638,57,2.908,66,3.517,73,3.266,74,2.086,86,1.464,98,3.311,109,4.124,126,4.203,135,1.857,138,3.796,142,3.016,154,1.982,184,5.758,185,1.619,188,3.952,190,1.719,208,4.369,211,5.396,212,1.719,219,1.8,233,2.706,239,2.065,245,2.104,256,2.161,260,3.499,265,3.221,294,3.499,304,3.016,307,4.569,308,1.347,316,2.374,319,2.906,336,3.582,346,3.794,350,2.581,365,2.374,369,3.796,402,4.487,404,3.392,409,5.651,431,2.374,447,2.015,449,1.745,454,3.582,456,1.887,483,1.949,484,4.316,489,3.981,508,3.952,509,7.161,605,2.328,624,1.159,630,2.015,672,3.796,675,2.086,720,2.086,721,2.544,725,1.668,744,2.422,798,1.719,801,3.376,802,3.376,820,5.694,834,3.499,898,9.583,977,2.908,990,5.396,1119,2.765,1135,2.374,1169,3.265,1189,2.123,1221,3.499,1222,4.203,1258,5.041,1316,3.638,1322,2.7,1328,3.265,1329,3.265,1333,3.453,1338,3.499,1346,2.581,1349,2.987,1350,2.835,1380,8.413,1399,3.265,1401,3.638,1421,13.542,1432,2.241,1439,3.265,1442,4.203,1446,4.853,1447,3.638,1481,4.853,1576,4.203,1578,2.639,1705,3.165,1708,3.796,1717,3.981,1718,3.981,1720,3.981,1721,3.265,1782,2.639,1821,6.713,1854,2.374,1861,9.583,2050,11.634,2053,14.026,2057,4.481,2060,13.733,2061,4.853,2063,4.481,2067,5.418,2068,2.639,2069,5.418,2070,5.418,2071,5.418,2072,4.203,2073,5.418,2074,8.659,2075,5.418,2076,5.418,2077,5.418,2078,5.418,2079,9.687,2080,5.418,2081,8.659,2082,5.418,2083,5.418,2084,5.418,2085,5.418,2086,5.418,2087,5.418,2088,5.418,2089,5.418,2090,5.418,2091,5.418,2092,3.981,2093,5.418,2094,3.981,2095,4.853,2096,8.659,2097,5.418,2098,10.815,2099,5.418,2100,5.418,2101,5.418,2102,7.756,2103,5.418,2104,7.756,2105,5.418,2106,8.659,2107,5.418,2108,5.418,2109,5.418,2110,4.853,2111,5.418,2112,5.418,2113,5.418,2114,5.418,2115,5.418,2116,5.418,2117,5.418,2118,3.981,2119,5.418,2120,8.659,2121,5.418,2122,5.418,2123,8.659,2124,4.853,2125,10.815,2126,5.418,2127,7.756,2128,5.418,2129,5.418,2130,5.418,2131,5.418,2132,8.659,2133,4.481,2134,4.853,2135,5.418,2136,5.418,2137,3.499,2138,2.908,2139,4.853,2140,5.418,2141,4.853,2142,5.418,2143,7.756,2144,7.756,2145,4.853,2146,5.418,2147,3.265,2148,4.853,2149,8.659,2150,7.161,2151,8.659,2152,5.418,2153,5.418,2154,5.418,2155,5.418,2156,5.418,2157,5.418,2158,5.418,2159,4.853,2160,5.418,2161,8.659,2162,5.418,2163,4.853,2164,8.659,2165,5.418,2166,5.418,2167,5.418]],["keywords/51",[]],["title/52",[514,642.995,2168,827.555]],["content/52",[8,4.958,18,4.547,22,2.438,23,2.277,45,4.447,48,5.485,73,2.405,98,2.438,116,2.128,134,5.631,141,3.062,145,1.962,185,2.973,242,6.678,256,3.967,304,5.812,307,4.318,308,3.383,309,5.995,312,3.254,319,2.97,336,6.419,358,2.438,376,5.995,402,3.304,417,3.639,454,4.115,489,7.308,496,6.198,508,4.54,514,5.995,608,3.521,820,4.193,2050,12.242,2053,11.257,2057,8.226,2060,14.451,2102,15.651,2124,12.192,2127,12.192,2133,11.257,2138,5.34,2139,8.91,2147,5.995,2159,12.192,2163,8.91,2169,8.91,2170,9.947,2171,9.947,2172,9.947,2173,13.612,2174,9.947,2175,13.612,2176,9.947,2177,9.947,2178,9.947,2179,9.947,2180,8.226,2181,9.947,2182,8.226,2183,9.947,2184,9.947,2185,15.517,2186,9.947,2187,9.947,2188,9.947,2189,9.947,2190,9.947,2191,13.612,2192,9.947,2193,9.947]],["keywords/52",[]],["title/53",[483,467.128]],["content/53",[7,3.029,18,3.721,20,3.731,21,3.084,25,3.876,31,6.281,68,3.201,73,2.716,79,2.976,86,0.9,91,3.142,98,3.276,100,2.733,116,1.625,125,2.603,135,2.603,141,2.338,142,2.645,143,4.188,145,3.108,153,2.523,160,3.396,190,2.409,191,6.366,212,2.409,216,2.82,219,2.523,233,4.176,239,2.679,245,1.478,249,4.905,250,5.598,255,5.891,256,3.029,275,3.976,298,6.803,308,2.791,319,2.683,418,2.924,453,4.077,458,4.733,484,3.785,543,2.603,630,2.825,635,5.021,637,4.436,644,5.733,720,4.324,721,1.787,725,3.458,726,3.731,744,3.396,766,4.324,798,2.409,827,3.876,908,5.321,1090,5.58,1119,3.876,1137,5.58,1169,4.577,1177,4.307,1181,4.733,1189,2.976,1194,5.58,1284,3.201,1333,3.029,1369,7.254,1392,5.58,1399,4.577,1432,4.646,1502,5.891,1583,3.785,1708,5.321,1844,6.281,1859,5.321,2028,5.58,2035,5.891,2050,7.869,2063,9.288,2068,3.699,2194,5.321,2195,7.595,2196,6.803,2197,7.595,2198,7.595,2199,7.595,2200,11.231,2201,6.803,2202,7.595,2203,11.231,2204,6.803,2205,7.595,2206,7.595,2207,7.595,2208,6.803,2209,7.595,2210,7.595,2211,7.595,2212,7.595,2213,7.595,2214,7.595,2215,6.803,2216,7.595,2217,6.803,2218,6.803,2219,7.595,2220,10.06,2221,7.595,2222,7.595,2223,7.595,2224,7.595,2225,7.595,2226,7.595,2227,7.595,2228,6.281,2229,7.595,2230,7.869,2231,7.595,2232,7.595,2233,7.595,2234,7.595,2235,5.891,2236,7.595,2237,7.595,2238,7.595,2239,10.06,2240,7.595,2241,7.595,2242,7.595,2243,7.595,2244,5.891,2245,6.281,2246,4.733,2247,7.595,2248,11.231,2249,11.231,2250,9.363,2251,11.231,2252,11.231,2253,9.288,2254,7.595,2255,6.281,2256,7.595,2257,7.595,2258,7.595,2259,7.595,2260,7.595,2261,11.231,2262,11.231,2263,9.288,2264,11.231,2265,7.595,2266,7.595,2267,7.595,2268,7.595,2269,5.891,2270,7.595,2271,7.595,2272,7.595,2273,4.733,2274,7.595,2275,7.595,2276,7.595,2277,7.595,2278,7.595,2279,7.595,2280,7.595,2281,13.364,2282,7.595,2283,3.201,2284,10.06,2285,7.254,2286,7.595,2287,6.281]],["keywords/53",[]],["title/54",[108,441.342,630,396.885]],["content/54",[23,3.313,40,9.348,57,7.769,79,5.671,91,5.988,116,3.096,124,4.141,141,4.456,145,2.855,499,5.843,526,5.773,605,6.219,726,4.808,880,9.348,1134,7.769,1307,9.019,1319,8.454,1350,7.572,1565,6.894,1892,7.981,2035,11.227,2288,14.474,2289,17.317,2290,14.474,2291,14.474,2292,7.05,2293,12.964]],["keywords/54",[]],["title/55",[1412,747.456,1709,519.621]],["content/55",[23,3.358,41,6.557,79,5.746,124,4.196,212,4.653,233,5.454,239,3.498,256,5.849,508,6.693,638,8.839,1119,7.486,1333,5.849,1565,6.986,1679,9.139,2250,10.275,2294,13.137,2295,14.666,2296,13.137,2297,12.129,2298,14.666,2299,12.129,2300,14.666,2301,14.666,2302,13.137,2303,12.129]],["keywords/55",[]],["title/56",[412,747.456,2304,1066.856]],["content/56",[]],["keywords/56",[]],["title/57",[2305,747.456,2306,827.555]],["content/57",[10,7.831,18,3.116,74,4.76,124,3.537,134,5.115,141,3.806,145,2.439,160,5.528,167,4.044,190,3.922,233,3.864,239,2.949,245,3.057,256,4.931,289,4.107,300,7.569,307,3.922,308,4.293,309,7.452,319,1.775,336,5.115,346,7.569,382,4.523,404,4.844,415,7.222,418,4.76,499,4.172,512,6.637,524,4.307,526,6.267,721,4.064,1199,6.817,1315,5.418,1320,6.311,1373,7.704,1511,6.637,1517,7.452,1609,8.301,1665,10.225,1892,6.817,2020,8.662,2118,9.084,2220,11.074,2305,8.662,2306,9.591,2307,12.364,2308,8.301,2309,11.074,2310,12.364,2311,9.084,2312,12.364,2313,12.364,2314,8.662,2315,12.364,2316,8.301,2317,9.084,2318,7.012]],["keywords/57",[]],["title/58",[2319,827.555,2320,955.587]],["content/58",[3,4.248,10,5.522,34,3.739,64,5.277,68,4.671,79,4.341,86,1.734,124,4.187,145,2.887,188,5.057,198,8.07,208,3.361,219,4.862,233,5.121,245,2.156,256,6.536,261,6.904,346,8.159,360,10.584,415,6.472,418,4.266,483,3.987,499,3.739,526,6.536,675,6.309,721,4.101,1283,6.678,1290,10.584,1338,7.156,1399,6.678,1402,4.122,1517,8.821,1556,5.277,2020,10.254,2023,6.472,2118,10.753,2305,10.254,2306,13.522,2308,7.439,2316,7.439,2317,12.041,2320,9.924,2321,11.08,2322,9.163,2323,9.924,2324,9.924,2325,11.08,2326,11.08,2327,9.163,2328,11.08,2329,11.08,2330,8.141,2331,9.924,2332,11.08,2333,9.163,2334,11.08,2335,11.353,2336,10.584,2337,11.08,2338,7.156,2339,9.924]],["keywords/58",[]],["title/59",[481,544.542,721,250.988]],["content/59",[6,8.051,95,9.04,118,7.847,266,6.845,374,4.291,499,5.061,630,5.58,721,4.161,988,11.02,1322,7.475,1571,7.656,1710,10.07,1890,9.687,2168,11.634,2311,11.02,2340,8.27,2341,10.508,2342,13.434,2343,11.634,2344,9.687]],["keywords/59",[]],["title/60",[118,558.161,2341,747.456]],["content/60",[118,7.707,127,8.157,208,5.308,256,5.875,308,3.661,309,8.879,319,2.115,374,4.215,977,7.908,1020,8.123,1348,9.514,1464,14.482,1890,9.514,2311,10.824,2341,10.321,2343,11.427,2345,12.183,2346,10.321,2347,14.732,2348,13.195,2349,13.195]],["keywords/60",[]],["title/61",[222,396.796,608,320.529,2343,702.378]],["content/61",[6,4.115,8,3.82,18,1.932,20,2.546,23,4.023,34,2.586,64,3.651,66,3.113,73,2.734,74,2.951,86,1.592,88,6.866,98,2.772,104,2.951,109,3.651,116,1.64,118,9.681,140,3.82,145,1.512,208,2.325,212,2.432,216,2.386,222,3.359,239,1.828,245,2.2,255,5.946,256,4.51,274,9.976,308,2.811,319,2.739,350,6.4,358,1.879,377,5.161,381,5.636,416,3.573,430,3.113,447,2.852,449,2.469,456,2.67,507,7.923,574,5.508,608,2.713,625,4.955,630,5.518,634,6.339,665,4.776,721,4.353,725,4.137,726,5.255,766,2.951,794,4.347,798,2.432,826,3.733,914,8.373,947,4.347,968,10.392,1020,4.226,1090,5.632,1134,4.115,1135,3.359,1189,4.43,1284,5.664,1322,5.636,1346,3.651,1466,3.171,1517,4.62,1522,4.347,1525,4.477,1583,5.636,1611,13.286,1630,5.146,1710,5.146,1810,5.37,1854,3.359,1969,7.62,2026,3.651,2079,10.129,2137,4.95,2311,12.162,2342,6.866,2343,8.772,2348,12.035,2349,6.866,2350,8.886,2351,13.437,2352,5.37,2353,7.665,2354,9.021,2355,10.423,2356,5.146,2357,5.37,2358,5.37,2359,5.632,2360,4.477,2361,7.665,2362,7.665,2363,4.01,2364,7.665,2365,5.146,2366,6.866,2367,6.866,2368,7.665,2369,7.665,2370,7.665,2371,10.129,2372,7.665,2373,11.308,2374,7.665,2375,7.665,2376,7.665,2377,7.665,2378,7.665,2379,7.665,2380,7.665,2381,7.665,2382,7.665,2383,7.665,2384,5.632,2385,6.866,2386,6.866,2387,7.665,2388,6.339,2389,7.665,2390,5.146,2391,6.866,2392,7.665]],["keywords/61",[]],["title/62",[721,250.988,914,664.795]],["content/62",[20,2.903,22,3.549,23,2,27,3.988,57,4.691,64,6.895,73,3.007,86,1.473,96,5.644,104,3.364,145,1.723,181,7.227,208,4.391,245,2.42,292,5.867,300,3.829,307,2.772,319,2.901,358,4.085,370,6.675,402,4.131,409,4.474,418,3.364,454,5.144,461,8.349,482,6.122,624,1.869,707,7.494,721,4.074,748,6.42,766,3.364,787,9.719,820,3.684,834,5.644,940,7.827,941,4.46,968,6.122,988,6.42,1001,7.227,1021,7.494,1189,4.872,1256,11.587,1258,5.796,1328,7.494,1329,5.267,1348,5.644,1777,9.645,1851,9.645,2168,6.778,2308,5.867,2311,6.42,2317,11.587,2335,6.778,2340,4.818,2350,4.691,2391,12.966,2393,7.827,2394,12.435,2395,12.966,2396,8.738,2397,6.778,2398,8.738,2399,7.827,2400,5.267,2401,8.738,2402,8.738,2403,8.738,2404,8.738,2405,8.738,2406,8.738,2407,8.738,2408,11.138,2409,11.138,2410,8.738,2411,8.738,2412,8.738,2413,12.435,2414,8.738,2415,8.738,2416,8.738,2417,8.738,2418,12.435,2419,8.738,2420,8.738,2421,8.738,2422,8.738,2423,8.738,2424,8.738,2425,8.738,2426,8.738,2427,8.738,2428,8.738,2429,8.738,2430,8.738,2431,8.738,2432,8.738,2433,8.738,2434,8.738,2435,8.738,2436,7.827,2437,8.738,2438,8.738,2439,7.827,2440,10.284,2441,8.738,2442,8.738,2443,8.738,2444,8.738,2445,7.227,2446,8.738]],["keywords/62",[]],["title/63",[721,185.035,826,383.078,2335,610.095,2447,786.514]],["content/63",[86,1.785,100,5.421,108,6.233,216,3.18,233,4.708,277,8.545,415,8.801,418,5.801,624,3.223,721,4.172,826,7.339,1016,7.023,1119,7.691,1189,5.903,2023,8.801,2029,11.07,2336,9.731,2448,11.687,2449,15.067]],["keywords/63",[]],["title/64",[188,413.24,526,361.133,2308,607.94]],["content/64",[18,3.505,23,1.863,45,3.638,54,3.875,73,2.856,74,3.132,86,1.808,98,1.995,116,1.74,124,2.328,141,2.505,184,3.792,188,6.347,190,2.581,215,3.792,233,3.691,245,1.583,256,4.711,292,7.931,308,3.793,312,3.864,319,2.847,346,7.644,347,4.257,350,3.875,367,5.754,369,5.701,370,4.368,381,4.055,386,7.894,415,4.753,418,3.132,484,4.055,526,5.547,543,2.789,550,9.163,561,6.482,608,2.88,619,5.463,630,3.027,739,4.904,764,3.43,766,5.354,778,5.463,798,2.581,851,6.311,1020,4.486,1129,5.701,1189,3.188,1256,10.218,1315,3.566,1316,5.463,1432,4.887,1437,5.701,1583,5.888,1782,3.963,1851,13.53,2137,5.255,2305,5.701,2306,9.163,2308,11.997,2309,7.288,2317,5.978,2318,4.614,2330,5.978,2331,7.288,2436,7.288,2439,7.288,2445,9.769,2450,8.136,2451,8.136,2452,15.261,2453,8.136,2454,13.669,2455,6.311,2456,11.813,2457,10.581,2458,7.288,2459,7.288,2460,7.288,2461,7.288,2462,7.288,2463,7.288,2464,7.288,2465,8.136,2466,10.581,2467,10.581,2468,7.288,2469,7.288,2470,7.288,2471,13.908,2472,11.813,2473,13.908,2474,8.136,2475,8.136,2476,8.136,2477,7.288,2478,8.136,2479,11.813,2480,8.136,2481,7.288,2482,7.288,2483,10.581,2484,8.136,2485,8.136,2486,11.813,2487,8.136,2488,11.813,2489,8.136,2490,7.288,2491,8.136,2492,7.288,2493,8.136,2494,8.136,2495,8.136,2496,8.136,2497,8.136,2498,8.136]],["keywords/64",[]],["title/65",[188,413.24,2308,607.94,2499,528.917]],["content/65",[3,3.087,18,2.68,34,2.382,48,5.864,57,3.79,64,3.363,73,2.572,74,4.094,79,2.766,86,1.516,98,3.936,104,2.718,108,2.921,138,4.946,145,1.392,184,3.291,188,7.328,208,2.141,212,2.24,215,5.964,233,3.324,256,4.242,277,4.004,292,7.141,300,3.094,307,2.24,319,2.84,346,5.607,347,8.718,350,6.095,358,3.491,360,6.869,365,3.094,367,5.18,369,7.451,370,3.79,376,4.255,404,2.766,447,2.626,456,2.459,481,3.603,496,10.384,524,3.704,526,2.816,550,8.25,608,3.765,613,6.368,644,3.603,707,4.255,708,5.476,721,2.502,725,2.173,726,4.251,766,5.483,778,4.74,985,4.004,1014,4.74,1016,3.291,1134,3.79,1189,2.766,1199,3.893,1256,7.814,1338,4.56,1346,5.066,1349,3.893,1434,5.476,1502,5.476,1556,5.066,1589,5.838,1672,5.476,1699,4.74,1851,5.476,2020,7.451,2118,7.814,2137,9.868,2308,11.188,2317,10.464,2318,9.45,2445,5.838,2454,13.685,2457,13.685,2458,6.323,2459,6.323,2460,6.323,2461,6.323,2462,6.323,2463,6.323,2464,6.323,2466,6.323,2467,9.526,2468,6.323,2469,6.323,2470,6.323,2477,6.323,2483,6.323,2490,9.526,2492,9.526,2500,6.323,2501,7.06,2502,7.06,2503,14.242,2504,7.814,2505,7.06,2506,5.187,2507,10.635,2508,10.635,2509,7.06,2510,7.06,2511,7.06,2512,8.796,2513,9.526,2514,7.06,2515,14.242,2516,7.06,2517,5.838,2518,7.06,2519,5.476,2520,12.796,2521,12.796,2522,10.635,2523,10.635,2524,7.06,2525,7.06,2526,7.06,2527,7.06,2528,10.635,2529,7.06,2530,7.06,2531,10.635,2532,7.06,2533,7.06,2534,7.06,2535,6.323,2536,6.323,2537,7.06,2538,7.06,2539,7.06]],["keywords/65",[]],["title/66",[1172,808.967]],["content/66",[19,6.501,20,3.808,33,9.481,34,3.868,49,7.404,54,5.46,57,8.034,68,7.024,72,7.404,73,2.772,74,4.413,75,7.697,109,5.46,125,3.93,126,8.893,135,5.13,138,8.032,145,2.952,188,5.232,208,3.477,216,2.419,245,3.437,250,5.714,260,7.404,281,8.423,308,2.849,343,8.423,346,6.559,347,5.998,382,5.475,415,6.696,418,4.413,431,5.024,461,7.697,481,5.851,512,6.154,624,3.201,630,4.265,721,2.697,726,4.972,941,7.639,1208,8.893,1215,8.893,1314,8.893,1315,5.024,1322,5.714,1334,6.909,1398,10.268,1399,6.909,1402,4.265,1409,7.697,1444,9.481,1565,5.46,1618,6.909,1933,8.423,2201,10.268,2318,8.487,2335,8.893,2336,7.404,2338,7.404,2339,10.268,2359,8.423,2499,6.696,2540,11.464,2541,8.893,2542,11.464,2543,10.268,2544,6.501,2545,11.464,2546,8.423,2547,10.268,2548,8.893,2549,10.268,2550,11.464,2551,10.268]],["keywords/66",[]],["title/67",[2552,955.587,2553,642.995]],["content/67",[]],["keywords/67",[]],["title/68",[174,584.8,2356,607.94,2554,665.279]],["content/68",[18,3.705,19,6.326,110,5.836,135,3.824,142,3.885,174,7.204,188,5.091,190,3.539,208,5.301,212,4.664,216,3.688,239,2.66,275,5.204,307,3.539,308,2.772,319,2.361,333,4.294,383,9.991,422,5.988,449,3.593,548,8.653,554,6.723,608,3.949,625,4.888,665,9.16,801,6.951,802,6.951,877,3.383,1169,6.723,1260,11.52,1328,6.723,1329,6.723,1333,4.449,1338,7.204,1346,5.313,1432,7.23,1436,7.815,1578,5.433,1685,6.326,1717,8.196,1718,8.196,1720,8.196,1721,6.723,1821,8.864,1981,6.723,2285,7.204,2554,10.801,2555,7.204,2556,9.225,2557,9.225,2558,10.619,2559,9.87,2560,11.155,2561,14.7,2562,11.403,2563,11.155,2564,11.155,2565,11.155,2566,8.653,2567,11.155,2568,9.991,2569,11.155,2570,7.815,2571,6.326,2572,11.155,2573,11.155,2574,11.155,2575,11.155]],["keywords/68",[]],["title/69",[1432,441.342,2285,689.022]],["content/69",[68,5.87,74,5.361,110,7.285,137,6.633,145,2.747,153,4.626,167,4.555,174,8.994,216,2.939,307,4.418,404,6.628,449,5.449,483,5.011,499,4.699,675,6.513,721,3.276,877,4.224,1177,7.897,1346,6.633,1432,5.761,1578,6.782,1585,11.516,1821,6.491,2285,8.994,2553,8.393,2554,10.231,2558,10.927,2570,11.853,2571,10.335,2576,13.925,2577,12.473]],["keywords/69",[]],["title/70",[358,221.971,1432,374.584,2285,584.8]],["content/70",[20,4.404,160,5.927,167,3.131,239,2.283,319,2.869,337,7.99,358,3.728,365,5.809,367,6.457,402,3.18,409,3.445,418,5.104,449,3.083,561,6.179,608,4.693,613,5.927,675,3.685,778,13.282,797,6.457,820,4.035,1135,4.195,1260,9.288,1695,11.021,1821,4.462,1846,5.429,2137,6.183,2305,6.707,2318,7.518,2559,8.901,2562,10.283,2566,7.426,2578,9.573,2579,8.574,2580,8.574,2581,10.964,2582,17.48,2583,14.456,2584,15.504,2585,12.577,2586,13.622,2587,11.874,2588,8.574,2589,8.574,2590,8.574,2591,8.574,2592,9.573,2593,9.573,2594,9.573,2595,9.573,2596,9.573,2597,8.574,2598,8.574,2599,7.917,2600,8.574,2601,7.917,2602,8.574,2603,8.574,2604,8.574,2605,9.573,2606,7.917]],["keywords/70",[]],["title/71",[608,320.529,1432,374.584,2285,584.8]],["content/71",[20,4.334,34,3.157,49,6.043,110,7.86,153,3.108,154,3.423,160,5.834,167,3.06,174,6.043,212,2.968,223,4.02,239,2.231,316,4.1,319,2.83,337,7.864,358,3.683,365,5.718,418,5.023,422,5.022,449,4.203,454,3.871,485,5.83,508,4.27,526,3.732,561,6.082,608,5.318,613,5.834,625,4.1,675,3.602,778,13.237,797,6.355,877,2.838,954,8.38,1260,6.555,1290,6.043,1378,8.38,1402,3.481,1673,6.555,1695,6.282,1821,6.082,1952,7.258,2318,7.399,2558,6.043,2559,10.913,2562,10.121,2566,7.258,2579,8.38,2580,8.38,2581,10.791,2582,17.412,2583,13.733,2584,15.079,2585,12.425,2586,13.457,2587,11.687,2588,8.38,2590,8.38,2591,8.38,2597,11.687,2598,8.38,2599,7.738,2600,8.38,2601,7.738,2602,8.38,2603,8.38,2604,8.38,2607,9.356,2608,13.048,2609,9.356,2610,9.356,2611,9.356,2612,8.38]],["keywords/71",[]],["title/72",[174,689.022,1311,588.253]],["content/72",[54,5.867,64,5.867,110,6.444,142,4.29,174,7.955,185,4.685,190,3.908,239,2.938,260,7.955,282,7.424,390,9.05,449,5.846,474,6.444,483,6.204,499,4.156,511,7.676,524,4.29,675,6.987,742,9.05,794,6.985,877,5.23,1224,7.424,1290,7.955,1432,5.096,1565,5.867,1584,9.555,1821,7.306,2273,7.676,2285,7.955,2358,8.63,2552,11.033,2554,12.668,2555,7.955,2558,11.722,2570,12.716,2571,10.628,2613,12.16,2614,14.041,2615,11.033,2616,7.955,2617,10.187,2618,9.555,2619,11.033]],["keywords/72",[]],["title/73",[304,371.602,2620,588.253]],["content/73",[20,3.959,22,2.922,53,4.655,56,7.427,81,6.398,86,1.412,98,3.763,104,4.588,110,6.235,116,3.283,124,3.41,135,4.086,141,3.669,145,2.351,167,5.02,208,3.615,212,3.781,215,5.555,217,6.572,233,3.724,239,2.843,304,5.913,374,3.41,377,5.439,431,5.223,458,7.427,483,4.288,574,5.805,596,4.588,697,9.113,700,6.726,725,4.725,775,5.024,797,5.805,798,3.781,1013,7.697,1223,6.235,1224,7.183,1251,9.245,1284,5.024,1287,8.757,1395,6.235,1440,6.572,1556,8.086,1618,7.183,1684,9.857,1689,10.675,1821,7.154,1854,5.223,2344,7.697,2571,8.704,2620,9.361,2621,8.002,2622,9.857,2623,10.675,2624,8.002,2625,11.918,2626,11.918,2627,11.918,2628,8.35,2629,9.857,2630,8.757]],["keywords/73",[]],["title/74",[53,274.647,2630,665.279,2631,748.84]],["content/74",[18,2.371,22,2.307,23,2.999,53,3.973,64,4.482,66,5.32,73,2.275,81,5.051,89,4.123,94,4.803,104,3.622,124,3.748,142,3.277,154,5.961,160,4.207,161,7.299,167,4.285,184,4.386,188,4.294,208,2.854,239,2.244,246,5.671,261,5.863,273,6.317,315,6.077,316,4.123,317,5.671,319,2.546,328,4.207,333,3.622,346,4.123,373,8.428,382,3.442,404,3.687,409,5.863,411,6.686,416,4.386,418,3.622,422,7.032,449,3.031,453,8.089,483,4.713,499,3.175,514,5.671,608,4.637,624,2.013,625,4.123,720,3.622,721,2.214,725,2.897,726,4.351,764,3.966,778,12.217,798,2.985,826,4.583,827,4.803,851,7.299,877,2.854,998,7.299,1048,7.299,1049,5.863,1185,3.175,1189,3.687,1266,9.624,1333,3.753,1380,8.802,1477,4.803,1530,8.428,1595,6.317,1821,7.024,1898,6.592,1952,7.299,2023,5.496,2030,6.592,2318,5.336,2390,6.317,2555,6.077,2559,8.795,2570,9.178,2571,5.336,2581,7.782,2585,7.782,2628,6.592,2630,9.624,2631,7.782,2632,9.409,2633,9.409,2634,9.409,2635,9.409,2636,9.409,2637,9.409,2638,8.428,2639,9.409,2640,9.409,2641,9.409,2642,9.409,2643,5.496,2644,9.409,2645,9.409,2646,9.409,2647,9.409,2648,9.409,2649,8.428,2650,6.592,2651,7.782,2652,9.409,2653,9.409,2654,6.077,2655,9.409,2656,6.317,2657,6.592,2658,9.409,2659,9.409,2660,9.409,2661,9.409]],["keywords/74",[]],["title/75",[304,315.394,1854,396.796,2620,499.273]],["content/75",[3,3.122,8,5.361,21,7.498,48,5.931,53,4.352,72,6.947,104,7.372,109,6.835,124,3.077,141,4.418,154,5.907,212,3.412,216,2.27,245,2.093,282,6.482,304,3.746,316,4.713,317,11.804,336,6.68,360,6.947,449,5.201,542,7.536,605,4.622,697,8.668,700,6.288,720,4.141,721,2.53,764,4.534,775,4.534,877,3.262,894,7.536,910,10.842,1000,7.536,1013,6.947,1175,7.536,1308,6.482,1380,8.382,1432,4.449,1439,8.649,1517,6.482,1526,7.221,1538,9.634,1708,7.536,1821,7.527,1848,7.536,1898,7.536,2194,7.536,2400,8.649,2536,9.634,2559,7.221,2571,6.1,2620,5.931,2630,7.902,2649,9.634,2662,10.756,2663,10.756,2664,8.343,2665,10.756,2666,8.895,2667,10.756,2668,10.756,2669,9.634,2670,10.756,2671,10.756,2672,10.756,2673,11.131,2674,10.756]],["keywords/75",[]],["title/76",[22,261.53,116,228.21]],["content/76",[3,2.623,7,2.28,8,2.85,16,2.665,20,4.23,21,3.67,22,2.215,23,2.069,41,2.556,49,3.693,53,1.734,73,2.71,84,2.365,86,0.677,91,3.739,97,4.435,100,2.057,116,1.223,124,1.636,125,1.96,136,3.563,141,1.76,145,1.128,154,3.306,170,7.521,198,6.179,208,2.741,216,1.907,219,3.002,223,2.457,242,3.839,245,1.113,252,2.85,256,2.28,308,1.421,319,2.978,334,4.728,336,3.739,344,2.609,346,2.505,357,5.777,358,2.215,377,4.124,402,4.607,409,2.057,411,4.613,417,3.306,430,2.322,431,2.505,449,2.911,454,3.739,456,1.991,483,2.057,489,4.201,514,3.446,542,4.006,561,5.935,596,2.201,605,2.457,608,3.199,697,3.069,700,2.505,702,4.006,801,5.631,802,3.563,820,5.368,822,6.754,910,7.524,975,2.991,980,3.693,992,4.006,1135,2.505,1177,3.242,1199,3.153,1223,2.991,1264,3.446,1308,3.446,1376,2.365,1380,6.546,1409,3.839,1437,4.006,1439,8.359,1578,5.458,1589,4.728,1618,3.446,1630,3.839,1693,8.233,1696,3.34,1706,2.609,1708,4.006,1821,2.665,1857,4.728,1861,4.435,1954,4.435,2020,6.332,2065,4.201,2134,8.095,2239,5.121,2246,3.563,2390,3.839,2400,3.446,2440,4.728,2558,3.693,2559,6.068,2571,3.242,2628,4.006,2666,7.474,2669,5.121,2673,4.435,2675,11.206,2676,9.037,2677,12.734,2678,5.717,2679,5.717,2680,9.037,2681,5.717,2682,5.717,2683,5.717,2684,13.869,2685,5.717,2686,5.717,2687,5.717,2688,3.563,2689,4.435,2690,4.006,2691,5.717,2692,5.717,2693,9.037,2694,5.717,2695,5.717,2696,5.717,2697,4.435,2698,5.717,2699,5.121,2700,5.717,2701,5.717,2702,5.717,2703,9.037,2704,5.717,2705,5.717,2706,3.693,2707,5.717,2708,15.442,2709,5.717,2710,15.442,2711,5.717,2712,5.717,2713,5.717,2714,5.717,2715,5.717,2716,4.728,2717,5.121,2718,5.717,2719,5.717,2720,5.717,2721,13.869,2722,13.869,2723,14.745,2724,8.095,2725,15.442,2726,15.442,2727,9.037,2728,4.435,2729,11.206,2730,10.037,2731,10.037,2732,9.037,2733,4.435,2734,9.037,2735,5.717,2736,2.85,2737,5.717,2738,14.745,2739,4.728,2740,9.037,2741,5.717,2742,9.037,2743,5.717]],["keywords/76",[]],["title/77",[2553,642.995,2744,882.296]],["content/77",[3,4.334,22,3.66,64,7.112,98,3.66,110,7.812,141,4.597,167,4.884,215,6.959,261,9.304,307,4.737,308,3.711,1565,7.112,1585,14.589,1821,6.959,2553,8.999,2554,10.97,2558,9.643,2571,10.004,2744,12.348,2745,13.374]],["keywords/77",[]],["title/78",[164,467.512,358,261.53]],["content/78",[3,4.296,86,1.335,125,3.863,208,3.418,219,3.743,223,4.842,245,3.215,304,3.925,319,2.777,336,4.662,337,6.792,365,4.938,367,7.208,431,4.938,820,4.75,877,3.418,1264,6.792,1308,6.792,1693,8.279,1695,7.566,1821,8.179,2400,6.792,2513,10.093,2553,6.792,2566,8.741,2571,6.391,2620,8.16,2730,10.093,2731,13.256,2746,10.093,2747,11.269,2748,14.799,2749,11.269,2750,11.269,2751,11.269,2752,16.525,2753,11.269,2754,14.799,2755,11.269,2756,11.269,2757,11.269,2758,11.269,2759,11.269,2760,11.269,2761,11.269,2762,11.269,2763,14.799,2764,11.269,2765,14.799,2766,11.269,2767,11.269,2768,11.269,2769,11.269,2770,11.269,2771,11.269,2772,11.269,2773,11.269,2774,11.269,2775,16.324,2776,16.755,2777,8.741,2778,11.269,2779,11.269]],["keywords/78",[]],["title/79",[164,467.512,608,377.653]],["content/79",[73,3.562,86,1.746,223,6.33,245,2.866,304,5.131,358,3.611,561,6.866,1695,9.891,2553,8.879,2571,8.354,2583,14.482,2584,15.802,2620,8.123,2780,12.183,2781,13.195,2782,14.732]],["keywords/79",[]],["title/80",[164,467.512,418,410.72]],["content/80",[20,5.737,73,3.484,86,1.708,245,2.804,304,5.019,358,3.533,418,5.548,561,6.717,613,6.443,1695,9.675,2553,8.685,2559,11.596,2583,14.347,2584,15.742,2620,7.946,2780,14.284,2781,12.908,2783,14.411]],["keywords/80",[]],["title/81",[164,467.512,613,476.984]],["content/81",[73,3.643,216,3.18,245,2.932,304,5.248,308,3.745,430,6.119,447,5.605,483,5.421,524,5.248,561,8.266,745,9.389,1402,5.605,2553,9.081,2558,9.731,2620,8.308,2724,13.496,2784,15.067,2785,15.067,2786,15.067]],["keywords/81",[]],["title/82",[164,467.512,365,467.512]],["content/82",[3,2.845,11,6.866,22,2.402,73,2.37,124,2.804,125,3.359,135,3.359,179,3.585,185,2.929,191,6.417,241,8.104,245,1.907,303,5.906,304,3.413,336,7.961,368,8.104,374,2.804,382,3.585,431,8.433,447,3.646,454,4.054,458,6.107,483,3.526,525,6.329,526,3.908,625,4.294,700,4.294,721,3.901,797,4.773,877,2.972,996,8.104,1048,7.602,1306,6.866,1308,11.598,1376,4.054,1402,3.646,1439,5.906,1525,5.724,1583,4.884,1693,14.138,1695,6.58,1821,6.28,1854,4.294,1965,8.778,1982,8.778,2246,6.107,2400,11.598,2499,5.724,2562,7.602,2571,5.557,2620,5.403,2673,7.602,2746,8.778,2775,16.088,2776,15.569,2777,7.602,2787,9.8,2788,9.8,2789,9.8,2790,9.8,2791,9.8,2792,8.778,2793,9.8,2794,9.8,2795,9.8,2796,9.8,2797,9.8,2798,9.8,2799,9.8,2800,9.8,2801,9.8,2802,9.8,2803,9.8,2804,9.8,2805,9.8,2806,9.8,2807,9.8,2808,7.602,2809,8.778]],["keywords/82",[]],["title/83",[1311,715.826]],["content/83",[25,6.556,34,5.431,74,6.196,134,5.313,145,2.533,167,4.201,185,3.839,191,6.118,343,9.437,382,4.699,404,6.306,474,6.72,483,6.325,524,4.474,596,4.945,624,2.747,625,7.053,697,8.64,700,5.628,721,3.022,826,6.256,877,3.896,1013,8.295,1020,7.082,1127,9.963,1290,10.395,1320,6.556,1372,7.502,1402,4.778,1410,9.437,1466,5.313,1583,6.401,1618,7.741,1699,8.623,1821,7.502,1838,9.437,1866,9.701,2553,7.741,2571,7.284,2809,11.504,2810,10.622,2811,12.844,2812,11.504,2813,12.844,2814,12.844,2815,7.502,2816,12.844,2817,12.844]],["keywords/83",[]],["title/84",[304,315.394,1684,748.84,2620,499.273]],["content/84",[]],["keywords/84",[]],["title/85",[304,371.602,2620,588.253]],["content/85",[18,3.354,34,4.491,53,4.037,56,8.293,81,7.144,86,1.577,134,5.506,141,5.499,142,4.636,154,4.869,216,2.809,253,9.778,304,5.732,317,8.021,343,9.778,357,5.214,358,4.034,404,5.214,422,8.833,430,5.405,449,4.287,512,7.144,596,5.124,697,7.144,700,7.211,798,4.222,1697,7.774,2026,6.339,2104,11.921,2138,7.144,2344,8.596,2346,9.324,2620,9.073,2638,11.921,2818,11.921,2819,14.739,2820,13.309,2821,13.309,2822,13.309,2823,11.921,2824,10.324]],["keywords/85",[]],["title/86",[91,537.055]],["content/86",[3,3.092,7,4.248,19,6.041,22,2.611,23,3.264,53,3.231,81,5.718,86,2.12,89,4.668,98,2.611,116,2.279,140,5.309,141,3.279,142,5.597,154,3.897,179,3.897,185,3.184,233,3.329,239,2.54,243,8.263,245,2.073,249,6.879,250,7.106,253,10.475,261,6.638,289,3.538,294,6.879,304,4.966,317,6.42,328,6.374,329,13.29,382,3.897,431,4.668,453,5.718,456,3.71,458,6.638,526,5.686,625,4.668,697,9.603,700,7.839,702,7.463,761,6.638,871,4.965,877,3.231,880,6.879,1185,3.594,1403,7.826,1437,7.463,1444,8.809,1525,6.222,1618,9.685,1673,7.463,1679,6.638,1706,4.861,1838,7.826,1839,7.826,1954,8.263,1981,6.42,2230,7.463,2283,4.49,2346,7.463,2553,6.42,2558,6.879,2620,7.861,2623,9.541,2630,7.826,2812,9.541,2825,9.113,2826,9.208,2827,17.161,2828,9.541,2829,10.652,2830,10.652,2831,10.652,2832,8.809,2833,10.652,2834,8.809,2835,7.152,2836,7.826,2837,9.541]],["keywords/86",[]],["title/87",[1225,528.065,1292,528.065,2292,383.078,2688,490.104]],["content/87",[]],["keywords/87",[]],["title/88",[723,572.688,2330,783.844]],["content/88",[3,2.724,18,1.511,66,2.436,68,2.528,73,1.45,86,0.711,89,4.112,98,1.47,100,2.158,116,2.473,119,4.652,134,2.481,145,1.851,158,3.737,167,3.781,185,1.792,190,2.977,191,2.857,208,4.936,219,3.117,245,1.167,300,5.729,305,3.138,306,7.018,307,2.977,308,2.873,312,1.962,319,2.768,336,2.481,358,3.205,365,6.218,370,3.219,382,3.433,402,3.84,416,2.795,418,5.033,422,7.018,447,2.231,460,2.921,474,3.138,482,4.202,492,8.444,524,2.089,561,2.795,608,2.123,613,7.48,625,2.628,638,3.615,675,2.309,706,6.574,707,5.655,709,3.737,718,4.652,721,1.411,723,7.617,775,3.955,787,6.3,820,4.872,827,3.061,834,3.873,877,3.506,941,3.061,1016,2.795,1020,3.307,1135,2.628,1225,7.76,1258,2.795,1269,6.894,1284,2.528,1293,8.289,1308,3.615,1320,3.061,1328,3.615,1329,3.615,1346,4.469,1464,4.652,1574,7.279,1676,6.06,1685,3.401,1704,3.615,1717,4.406,1718,4.406,1720,4.406,1721,3.615,1777,13.746,1866,3.615,2023,3.503,2043,5.372,2150,7.76,2194,4.202,2245,4.96,2292,7.329,2345,4.96,2535,5.372,2739,4.96,2838,5.372,2839,5.997,2840,5.997,2841,8.966,2842,5.372,2843,9.383,2844,5.997,2845,5.997,2846,5.997,2847,5.997,2848,5.997,2849,9.383,2850,8.405,2851,4.96,2852,5.372,2853,4.202,2854,5.372,2855,7.279,2856,5.372,2857,5.372,2858,5.372,2859,5.372,2860,5.997,2861,5.997,2862,5.997,2863,14.19,2864,5.997,2865,5.997,2866,5.997,2867,5.997,2868,5.997,2869,5.997,2870,5.997,2871,5.997,2872,5.997,2873,5.997,2874,5.997,2875,11.711,2876,5.997,2877,9.383,2878,9.383,2879,10.353,2880,9.383,2881,9.383,2882,13.074,2883,11.711,2884,5.372,2885,5.997,2886,5.997,2887,5.997,2888,11.559,2889,11.711,2890,5.997,2891,9.383,2892,9.559,2893,5.997,2894,5.997,2895,5.997,2896,5.372,2897,4.406,2898,5.997,2899,4.96,2900,5.997,2901,5.997,2902,8.405,2903,5.997,2904,5.997,2905,4.202,2906,5.997,2907,9.383,2908,9.383,2909,5.997,2910,5.997,2911,5.997,2912,5.997,2913,4.96,2914,4.96,2915,5.997,2916,5.372,2917,5.997,2918,5.372,2919,7.76,2920,5.997,2921,9.383,2922,5.372,2923,4.96,2924,5.997,2925,5.372,2926,5.372,2927,8.405,2928,5.997,2929,5.997,2930,5.997,2931,9.383,2932,5.997,2933,5.372,2934,5.372,2935,5.997,2936,5.997,2937,5.372,2938,4.96,2939,5.997,2940,3.873,2941,5.997,2942,5.997]],["keywords/88",[]],["title/89",[19,605.017,2943,1066.856]],["content/89",[13,5.038,19,8.393,20,3.743,23,2.58,25,5.752,34,3.802,66,4.576,72,9.558,73,2.725,79,5.798,125,3.863,142,5.155,145,2.223,153,3.743,185,4.423,188,5.143,212,4.695,252,5.616,300,4.938,360,7.278,367,5.489,386,5.489,404,4.415,416,5.252,456,3.925,460,7.208,484,5.616,485,7.022,499,3.802,525,7.278,596,4.338,624,2.41,721,2.651,723,8.87,725,4.556,764,4.75,766,4.338,826,5.489,877,3.418,1016,6.898,1098,7.895,1199,6.213,1216,7.278,1225,11.782,1293,9.652,1322,5.616,1348,7.278,1413,10.093,1429,10.093,1440,6.213,1466,4.662,1565,5.367,1706,5.143,2292,8.547,2359,8.279,2841,11.48,2944,11.269,2945,11.269,2946,11.269,2947,11.269,2948,8.279,2949,14.799,2950,10.093,2951,11.269,2952,11.269,2953,11.269,2954,11.269,2955,11.269,2956,11.269,2957,8.741,2958,11.269,2959,11.269,2960,11.269]],["keywords/89",[]],["title/90",[1292,716.286,2688,664.795]],["content/90",[18,1.15,20,1.517,22,1.119,27,3.439,54,2.175,55,3.065,79,1.789,86,0.893,100,1.643,108,1.889,116,0.977,125,1.565,137,2.175,145,0.9,148,3.354,154,5.148,167,1.493,173,5.059,185,2.252,208,3.748,216,0.963,222,2.001,306,7.554,308,1.135,316,4.216,319,2.931,324,3.354,343,3.354,344,2.084,357,2.952,358,4.378,365,5.415,382,2.756,402,1.517,404,2.952,409,1.643,411,2.33,430,1.854,459,3.512,460,4.686,474,2.389,492,2.949,542,3.199,561,2.128,562,3.776,605,7.808,608,4.374,619,3.065,624,0.977,628,3.776,629,4.541,680,3.512,701,7.823,702,3.199,707,4.541,708,3.541,717,12.492,720,1.758,721,1.074,725,2.32,741,2.752,742,3.354,744,2.041,748,3.354,764,3.176,766,6.333,778,5.059,787,5.059,798,2.39,801,2.845,802,2.845,807,8.617,820,4.055,833,1.962,941,2.33,975,2.389,978,5.995,985,2.589,992,5.279,1001,6.231,1018,2.752,1020,2.517,1029,4.089,1133,3.541,1135,3.302,1172,4.695,1266,3.354,1269,3.354,1274,3.776,1292,3.065,1328,2.752,1329,2.752,1333,1.821,1346,2.175,1349,4.154,1412,3.199,1437,3.199,1438,3.199,1565,2.175,1578,2.224,1679,4.695,1708,3.199,1777,3.541,1781,6.231,1892,2.517,1923,4.089,1925,11.915,1966,6.958,2014,4.089,2273,2.845,2292,2.224,2305,3.199,2318,2.589,2319,5.845,2358,3.199,2360,2.667,2408,6.749,2440,3.776,2589,4.089,2688,10.441,2689,3.541,2690,7.823,2697,3.541,2699,4.089,2824,3.541,2850,4.089,2851,3.776,2884,4.089,2892,3.776,2896,4.089,2913,3.776,2914,3.776,2948,3.354,2961,3.541,2962,3.199,2963,4.565,2964,7.535,2965,4.565,2966,7.535,2967,4.089,2968,4.089,2969,3.776,2970,4.565,2971,4.565,2972,4.565,2973,4.565,2974,4.565,2975,4.565,2976,4.565,2977,4.565,2978,4.565,2979,7.535,2980,11.165,2981,7.535,2982,7.535,2983,7.535,2984,15.707,2985,7.535,2986,7.535,2987,7.535,2988,7.535,2989,14.71,2990,7.535,2991,7.535,2992,7.535,2993,7.535,2994,7.535,2995,15.707,2996,4.565,2997,4.565,2998,4.565,2999,9.62,3000,9.62,3001,9.62,3002,4.565,3003,11.165,3004,13.302,3005,7.535,3006,4.565,3007,7.535,3008,7.535,3009,4.565,3010,4.565,3011,4.565,3012,9.62,3013,4.565,3014,4.565,3015,4.565,3016,4.565,3017,4.565,3018,4.565,3019,4.565,3020,4.565,3021,4.565,3022,4.565,3023,3.776,3024,3.776,3025,4.565,3026,4.565,3027,4.565,3028,4.089,3029,7.535,3030,7.535,3031,7.535,3032,4.089,3033,4.565,3034,4.565,3035,4.089,3036,4.565,3037,4.565,3038,4.565,3039,4.565,3040,4.565,3041,7.535,3042,4.565,3043,4.565,3044,4.565,3045,4.565,3046,4.565,3047,4.565,3048,4.565,3049,4.565,3050,4.565,3051,4.565,3052,4.565,3053,4.565,3054,9.62,3055,9.62,3056,9.62,3057,4.565,3058,4.565,3059,4.565,3060,4.565,3061,4.565,3062,4.565,3063,4.565,3064,9.62,3065,4.565,3066,4.565,3067,4.565,3068,4.565,3069,3.776,3070,2.845]],["keywords/90",[]],["title/91",[131,152.896,300,208.012,358,116.364,367,231.197,596,182.743,766,182.743,1199,261.734,1293,277.273,2688,295.79]],["content/91",[3,2.076,8,2.137,13,1.917,18,1.802,20,1.424,22,1.051,23,2.106,27,3.264,28,2.878,54,2.042,57,2.301,64,2.042,79,3.605,86,1.09,96,2.769,98,1.051,100,3.311,108,3.806,109,2.042,116,2.759,124,1.227,125,1.47,127,1.998,131,1.381,134,1.774,141,2.202,145,1.411,153,3.056,154,2.616,160,1.917,167,1.402,179,1.568,185,1.281,190,2.269,195,4.456,208,3.257,212,1.36,215,1.998,216,1.509,239,1.023,245,2.789,256,1.71,266,1.957,277,2.431,289,1.424,300,6.525,306,3.839,307,1.36,308,1.066,315,2.769,316,3.134,319,2.899,333,1.651,344,1.957,346,1.879,353,5.374,357,1.68,358,2.256,359,2.504,365,4.032,367,2.088,374,1.227,386,2.088,389,2.137,402,2.376,404,2.802,409,2.573,418,4.134,422,3.839,430,1.741,447,1.595,449,1.381,454,1.774,459,3.333,460,6.982,481,2.188,483,3.311,492,2.769,496,2.672,524,1.493,561,3.333,596,4.965,608,1.518,613,6.409,624,0.917,627,4.178,630,1.595,644,6.582,669,5.011,680,1.998,709,7.438,720,2.753,721,2.527,723,6.408,725,2.202,739,4.31,741,4.31,742,5.255,766,6.962,775,3.015,798,2.919,820,3.015,822,2.584,874,1.957,877,1.3,879,2.504,913,3.943,928,3.004,941,3.65,949,3.84,980,2.769,1000,3.004,1014,2.878,1018,2.584,1135,1.879,1199,2.364,1223,2.243,1225,8.658,1264,2.584,1269,3.15,1284,1.807,1290,2.769,1292,8.658,1293,7.991,1320,2.188,1338,2.769,1348,2.769,1373,2.672,1376,5.335,1379,3.546,1380,2.504,1401,2.878,1433,3.15,1438,3.004,1511,2.301,1517,2.584,1556,3.406,1565,2.042,1593,1.807,1706,5.448,1709,2.088,1792,3.84,1807,3.004,1863,5.255,1898,3.004,1911,2.504,1966,4.456,2023,2.504,2026,2.042,2052,3.326,2292,6.281,2318,2.431,2333,12.313,2360,2.504,2512,3.546,2519,3.326,2544,2.431,2656,2.878,2688,9.574,2689,3.326,2733,3.326,2837,3.84,2855,5.548,2875,3.84,2879,6.406,2883,6.406,2889,3.84,2892,5.915,2913,3.546,2914,3.546,2916,3.84,2918,3.84,2919,5.915,2923,3.546,2925,3.84,2926,3.84,2927,6.406,2933,3.84,2934,3.84,2937,3.84,2962,5.011,2967,3.84,3023,12.313,3035,6.406,3069,3.546,3071,4.287,3072,4.287,3073,4.287,3074,4.287,3075,4.287,3076,7.152,3077,4.287,3078,4.287,3079,4.287,3080,4.287,3081,4.287,3082,4.287,3083,4.287,3084,7.152,3085,4.287,3086,4.287,3087,4.287,3088,7.152,3089,4.287,3090,4.287,3091,4.287,3092,4.287,3093,4.287,3094,4.287,3095,4.287,3096,4.287,3097,4.287,3098,4.287,3099,6.406,3100,4.287,3101,4.287,3102,4.287,3103,3.84,3104,3.546,3105,6.406,3106,3.84,3107,3.84,3108,3.84,3109,3.326,3110,3.546,3111,3.84,3112,3.84,3113,3.84,3114,3.84,3115,3.546,3116,4.287,3117,4.287,3118,4.287,3119,4.287,3120,7.152,3121,4.287,3122,4.287,3123,4.287,3124,4.287,3125,4.287,3126,4.287,3127,3.546,3128,3.84,3129,6.406,3130,6.406,3131,3.84,3132,3.84,3133,3.84,3134,3.84,3135,3.84,3136,3.84,3137,3.84,3138,3.84,3139,3.84,3140,4.287,3141,4.287,3142,9.201,3143,4.287,3144,4.287,3145,4.287,3146,4.287,3147,4.287,3148,4.287,3149,4.287,3150,3.84,3151,3.84,3152,4.287,3153,4.287,3154,4.287,3155,4.287,3156,4.287,3157,3.84,3158,9.201,3159,11.551,3160,8.241,3161,7.152,3162,6.406,3163,3.546,3164,4.287,3165,7.152,3166,3.84,3167,6.406,3168,3.15,3169,3.84,3170,7.152,3171,4.287,3172,4.287,3173,3.84,3174,7.152,3175,4.287,3176,4.287]],["keywords/91",[]],["title/92",[131,181.714,145,111.269,367,274.774,608,199.702,766,217.187,1293,329.534,2688,351.541]],["content/92",[20,2.778,27,3.817,57,6.468,73,2.022,79,3.276,89,5.28,98,2.05,100,3.009,116,3.306,134,3.46,141,2.574,145,2.786,167,2.735,179,4.408,190,2.653,195,5.211,215,3.898,216,1.765,223,3.594,230,5.859,245,3.321,277,4.743,300,6.19,306,4.489,308,3.511,312,2.735,319,2.868,333,4.639,346,3.665,353,8.251,357,3.276,358,2.05,402,4.692,417,3.059,418,3.22,430,3.396,447,3.111,459,3.898,460,7.98,483,3.009,525,5.401,596,4.639,625,5.28,626,4.885,627,7.038,630,4.483,644,4.268,709,5.211,720,3.22,721,2.835,725,2.574,741,5.04,742,6.144,766,6.57,820,3.525,874,3.817,913,4.611,928,5.859,941,4.268,980,5.401,1016,3.898,1199,4.611,1225,5.615,1293,9.029,1348,5.401,1349,4.611,1373,5.211,1376,5.843,1402,3.111,1593,3.525,1863,6.144,1911,4.885,2023,4.885,2314,5.859,2333,9.965,2360,4.885,2519,6.487,2688,8.802,2689,6.487,2855,6.487,2962,8.442,3023,11.682,3069,6.916,3099,7.491,3127,6.916,3128,7.491,3129,7.491,3130,7.491,3131,7.491,3132,7.491,3133,7.491,3134,7.491,3135,7.491,3136,7.491,3137,7.491,3138,7.491,3139,7.491,3157,7.491,3159,15.285,3160,12.652,3162,10.793,3166,7.491,3168,8.853,3169,7.491,3173,7.491,3177,12.05,3178,8.363,3179,14.125,3180,12.05,3181,8.363,3182,8.363,3183,8.363,3184,6.487,3185,12.05,3186,12.05]],["keywords/92",[]],["title/93",[1172,664.795,1311,588.253]],["content/93",[1,3.177,3,1.316,18,1.143,19,2.571,21,1.841,23,1.715,28,3.044,34,1.53,48,2.5,57,2.434,66,1.841,72,2.928,79,4.356,86,0.537,89,1.987,98,1.111,100,1.631,109,2.16,116,1.603,124,1.297,141,2.306,145,1.478,179,1.659,190,3.037,198,2.5,208,5.355,219,1.506,239,2.283,245,1.458,274,2.733,282,4.515,292,3.044,306,5.968,319,2.954,336,1.876,342,3.177,345,4.668,358,1.111,370,2.434,374,1.297,382,1.659,402,3.693,404,1.776,409,4.43,431,4.195,447,1.687,460,6.457,461,3.044,473,3.177,483,1.631,484,2.26,489,3.331,499,1.53,511,2.825,525,4.839,627,4.376,635,2.027,637,2.648,638,2.733,664,4.515,669,3.177,680,2.113,706,6.707,707,5.77,708,5.811,709,9.477,720,2.884,721,3.578,723,7.117,725,2.947,726,3.18,766,1.746,775,4.687,784,3.177,787,5.03,799,2.571,820,5.589,822,2.733,834,4.839,873,3.331,874,3.419,877,1.375,879,2.648,880,2.928,887,4.061,888,9.195,889,4.061,894,3.177,901,4.061,911,4.061,914,2.825,920,3.331,928,5.249,932,4.061,933,3.75,934,6.711,935,4.061,941,5.675,951,4.061,958,3.75,963,4.061,977,2.434,995,7.426,997,3.331,999,3.75,1016,3.492,1018,2.733,1021,2.733,1054,3.517,1122,3.177,1168,3.75,1177,2.571,1185,1.53,1199,4.131,1212,4.061,1225,7.465,1245,3.75,1258,2.113,1264,2.733,1292,3.044,1293,2.648,1306,3.177,1328,4.515,1329,4.515,1346,2.16,1369,2.928,1402,1.687,1439,2.733,1464,3.517,1466,1.876,1476,4.061,1477,2.314,1493,4.061,1535,2.928,1562,4.061,1571,2.314,1593,1.911,1676,4.839,1685,2.571,1686,2.648,1703,3.331,1784,3.177,1824,4.061,1854,1.987,1862,3.517,1863,3.331,1865,3.75,1866,2.733,1933,3.331,1966,2.825,1985,3.331,2023,5.592,2026,2.16,2052,3.517,2292,4.663,2345,3.75,2397,3.517,2544,4.249,2688,8.261,2733,3.517,2792,8.575,2842,4.061,2851,3.75,2852,4.061,2853,3.177,2854,4.061,2855,5.811,2856,4.061,2857,4.061,2858,4.061,2859,4.061,2902,4.061,2948,7.034,3024,6.196,3032,6.711,3103,6.711,3104,3.75,3105,8.575,3106,4.061,3107,6.711,3108,4.061,3109,3.517,3110,3.75,3111,6.711,3112,4.061,3113,4.061,3114,4.061,3167,4.061,3187,4.061,3188,4.061,3189,4.534,3190,4.061,3191,4.534,3192,4.534,3193,4.534,3194,4.534,3195,3.75,3196,4.534,3197,4.061,3198,4.534,3199,4.534,3200,3.177,3201,4.534,3202,4.534,3203,4.534,3204,4.534,3205,4.534,3206,6.196,3207,9.574,3208,4.534,3209,4.534,3210,4.534,3211,4.534,3212,4.534,3213,4.534,3214,4.534,3215,7.492,3216,4.534,3217,4.534,3218,4.534,3219,4.534,3220,4.534,3221,7.492,3222,4.534,3223,3.517,3224,4.534,3225,4.534,3226,4.534,3227,4.534,3228,4.534,3229,4.534,3230,4.534,3231,4.534,3232,4.534,3233,4.534,3234,4.534,3235,4.534,3236,4.534,3237,4.534,3238,4.534,3239,7.492,3240,4.534,3241,4.534,3242,4.534,3243,4.534,3244,4.534,3245,4.534,3246,4.534,3247,4.534,3248,4.534,3249,4.534,3250,4.534,3251,4.534,3252,4.534,3253,4.534,3254,4.534,3255,4.534,3256,4.534,3257,4.534,3258,4.061,3259,4.534,3260,4.534,3261,4.534,3262,4.534,3263,4.534,3264,4.534,3265,4.534,3266,4.534,3267,4.534,3268,4.534,3269,4.534,3270,4.534,3271,4.534,3272,4.534,3273,4.534,3274,4.534,3275,4.534,3276,4.534,3277,4.534,3278,4.534,3279,6.196,3280,7.492,3281,11.119,3282,7.492,3283,7.492,3284,11.119,3285,7.492,3286,7.492,3287,7.492,3288,7.492,3289,7.492,3290,7.492,3291,3.044,3292,4.534,3293,4.534,3294,4.534,3295,4.534,3296,4.534]],["keywords/93",[]],["title/94",[638,474.032,2853,551.044,3297,786.514,3298,786.514]],["content/94",[]],["keywords/94",[]],["title/95",[3299,1073.638]],["content/95",[7,5.064,17,8.2,22,3.112,23,2.906,54,6.047,68,5.352,74,6.151,86,1.504,98,3.917,124,4.572,130,5.918,141,3.909,145,2.504,167,4.153,219,4.217,222,5.564,233,3.967,239,3.028,308,3.156,377,5.794,382,5.845,390,9.328,447,4.723,481,6.48,484,7.964,499,4.284,514,7.652,524,4.422,543,4.352,596,4.888,624,2.716,721,2.987,766,4.888,988,9.328,1440,7,1463,8.524,1500,8.895,1712,6.184,2068,6.184,2299,10.5,2853,8.895,2940,8.2,3300,11.372,3301,10.5,3302,11.372,3303,12.696,3304,12.696,3305,12.696,3306,12.696,3307,12.696,3308,3.29,3309,6.328,3310,8.2,3311,9.848,3312,11.372,3313,12.696]],["keywords/95",[]],["title/96",[100,325.812,358,221.971,947,513.501]],["content/96",[3,3.271,7,3.043,13,3.411,18,1.923,20,2.535,21,3.099,22,1.87,23,2.58,39,5.918,40,4.928,52,5.606,54,3.634,66,3.099,74,2.937,91,3.156,93,3.863,94,7.554,98,1.87,124,2.183,131,2.458,141,4.556,145,2.223,153,2.535,159,4.327,160,5.991,167,2.496,184,3.556,185,3.368,190,4.251,216,1.61,222,3.343,229,3.894,233,2.384,245,2.607,250,3.803,300,3.343,307,4.695,308,1.896,319,2.616,374,2.183,402,2.535,413,5.346,417,5.776,418,2.937,431,3.343,449,2.458,456,2.658,483,2.745,543,2.615,605,3.279,624,1.632,630,2.838,675,4.339,725,4.125,726,3.744,744,3.411,766,2.937,798,2.42,820,3.216,822,4.598,914,9.839,947,9.372,968,11.578,980,4.928,1088,9.846,1120,8.742,1134,4.096,1177,7.599,1178,3.992,1185,2.574,1284,3.216,1286,6.31,1307,4.754,1315,3.343,1322,3.803,1340,5.918,1372,4.457,1376,3.156,1432,3.156,1463,5.123,1466,3.156,1583,3.803,1686,6.583,1706,3.482,1712,7.208,1748,9.32,1810,5.346,1846,4.327,1848,5.346,1896,3.482,1911,4.457,1969,4.327,1988,10.369,2244,5.918,2352,5.346,2354,5.123,2371,6.834,2384,5.606,2400,4.598,2555,4.928,2736,5.617,3308,3.835,3314,6.834,3315,5.123,3316,5.918,3317,7.63,3318,11.27,3319,5.346,3320,7.63,3321,6.31,3322,7.63,3323,7.63,3324,7.63,3325,7.63,3326,7.63,3327,5.155,3328,14.8,3329,9.937,3330,13.256,3331,13.256,3332,11.27,3333,7.63,3334,6.834,3335,6.834,3336,14.8,3337,7.63,3338,7.63,3339,4.928,3340,7.63,3341,7.63,3342,7.63,3343,7.63,3344,3.556,3345,13.401,3346,8.28,3347,7.63,3348,6.834,3349,7.63,3350,5.346,3351,7.63,3352,7.63,3353,7.63,3354,6.31]],["keywords/96",[]],["title/97",[100,250.139,608,246.084,2235,539.245,2621,466.741,3355,539.245]],["content/97",[2,4.004,3,2.575,7,1.626,13,5.62,16,3.195,17,2.632,18,1.027,20,2.947,21,3.603,22,2.55,23,2.031,27,4.049,34,1.375,39,3.162,40,6.718,41,1.822,45,1.822,52,6.518,53,5.279,54,1.941,58,4.272,66,1.655,67,3.162,68,1.718,73,2.515,74,1.569,86,1.584,89,5.084,91,4.8,93,3.977,94,5.309,95,2.457,96,2.632,98,3.276,100,1.467,104,3.415,108,4.8,115,3.265,116,2.225,118,2.132,120,3.162,124,2.976,130,3.195,131,2.208,134,1.686,135,2.35,136,4.272,137,1.941,140,2.031,141,4.114,145,2.052,153,1.354,162,4.422,164,4.558,168,3.651,169,3.651,170,4.321,179,1.491,184,1.9,185,3.109,187,2.995,188,4.049,190,3.3,201,4.272,202,3.371,209,4.427,212,1.293,215,4.848,216,1.872,222,5.084,229,2.08,233,2.772,239,2.116,244,2.737,245,1.334,265,3.3,266,1.86,273,2.737,274,2.457,303,2.457,307,2.175,308,2.884,312,2.902,317,4.132,319,2.548,333,2.639,336,2.836,344,1.86,358,0.999,365,1.786,374,2.976,375,2.995,376,2.457,377,3.129,381,2.031,382,1.491,390,2.995,402,3.455,417,4.244,449,2.208,454,2.836,456,1.42,459,1.9,480,2.995,481,3.499,483,1.467,484,2.031,512,2.188,524,1.42,526,1.626,543,3.566,554,4.132,608,1.443,613,1.822,623,1.375,624,1.898,627,2.381,630,2.55,635,3.065,680,1.9,721,1.613,725,3.202,726,2.277,794,3.888,798,3.3,811,2.995,826,1.985,877,2.691,885,3.162,910,2.737,914,7.832,947,3.888,975,3.587,1020,2.247,1022,6.882,1049,2.54,1120,3.162,1163,2.54,1181,2.54,1185,2.994,1218,4.803,1221,2.632,1283,2.457,1284,3.74,1307,2.54,1316,2.737,1319,4.004,1320,2.08,1346,5.987,1372,2.381,1373,2.54,1395,3.587,1439,2.457,1440,6.931,1466,3.67,1520,3.162,1534,2.247,1535,2.632,1556,1.941,1565,3.265,1571,2.08,1593,3.74,1672,3.162,1673,2.856,1679,2.54,1690,3.371,1705,4.004,1706,1.86,1810,2.856,1846,2.311,1880,2.856,1886,3.371,1887,2.457,1898,2.856,1911,2.381,1969,2.311,1981,2.457,1985,2.995,2017,3.371,2026,1.941,2051,3.162,2235,5.318,2283,2.89,2340,2.247,2350,2.188,2352,2.856,2354,2.737,2355,5.318,2357,2.856,2363,2.132,2365,2.737,2386,3.651,2390,2.737,2448,3.162,2499,2.381,2517,3.371,2544,2.311,2555,4.427,2621,6.984,2628,2.856,2706,2.632,2717,3.651,2808,6.882,2825,3.888,2826,7.493,2853,2.856,2923,3.371,2940,2.632,3188,3.651,3190,3.651,3300,9.317,3301,3.371,3308,3.782,3310,4.427,3315,5.957,3321,8.602,3327,2.388,3329,6.984,3330,6.14,3331,9.317,3344,4.848,3350,2.856,3355,3.162,3356,6.882,3357,4.076,3358,6.14,3359,2.737,3360,2.188,3361,3.651,3362,3.371,3363,2.632,3364,3.651,3365,4.076,3366,12.569,3367,4.076,3368,5.318,3369,4.076,3370,5.669,3371,6.855,3372,4.076,3373,4.076,3374,5.037,3375,5.735,3376,9.317,3377,4.076,3378,2.995,3379,4.427,3380,4.076,3381,4.076,3382,6.855,3383,4.076,3384,2.632,3385,4.076,3386,4.076,3387,4.076,3388,4.076,3389,4.076,3390,6.855,3391,3.651,3392,4.076,3393,4.076,3394,4.076,3395,4.076,3396,5.184,3397,4.076,3398,4.076,3399,4.076,3400,2.995,3401,10.402,3402,2.381,3403,4.076,3404,10.402,3405,3.651,3406,4.076,3407,8.872,3408,4.076,3409,10.402,3410,4.076,3411,4.076,3412,6.855,3413,6.855,3414,4.076,3415,4.803,3416,3.651,3417,3.651,3418,4.603,3419,2.995,3420,4.076,3421,4.076,3422,4.076,3423,4.076,3424,4.076,3425,3.651,3426,4.076,3427,4.076,3428,3.371,3429,4.076,3430,6.14,3431,2.856,3432,4.076,3433,4.076,3434,4.076,3435,4.076,3436,4.076]],["keywords/97",[]],["title/98",[1311,715.826]],["content/98",[3,2.977,11,7.185,21,4.165,23,2.348,41,4.585,53,3.111,62,6.623,68,4.323,73,2.48,75,6.886,77,6.181,86,2.158,94,5.235,104,3.948,116,2.194,118,7.271,124,2.934,125,4.764,130,4.78,137,4.885,140,5.111,145,2.023,147,5.655,173,6.886,191,4.885,208,3.111,217,5.655,233,3.205,239,2.446,256,4.09,265,3.815,279,7.185,289,3.407,308,2.549,346,6.09,358,2.514,359,5.991,374,2.934,524,3.572,623,4.689,624,3.372,766,3.948,794,5.816,797,4.995,798,3.253,833,4.407,874,6.342,877,4.215,913,5.655,947,5.816,1119,7.094,1163,6.391,1179,7.535,1185,3.46,1313,8.481,1320,5.235,1333,4.09,1335,7.955,1346,4.885,1463,6.886,1466,4.243,1593,4.323,1706,4.68,1712,4.995,1837,7.185,1903,9.208,1911,5.991,1970,7.955,2253,8.481,2316,6.886,2355,7.955,2499,5.991,2506,7.535,2544,5.816,2556,8.481,2657,7.185,2969,8.481,3308,4.576,3309,5.111,3315,6.886,3316,7.955,3363,6.623,3368,7.955,3418,9.331,3437,10.255,3438,8.481,3439,6.623,3440,10.255,3441,10.255,3442,7.955,3443,10.255,3444,9.186,3445,7.535,3446,10.255,3447,6.623,3448,10.255,3449,8.481,3450,7.185,3451,8.481,3452,10.255,3453,10.255,3454,10.255]],["keywords/98",[]],["title/99",[83,528.917,1983,584.8,3455,564.238]],["content/99",[]],["keywords/99",[]],["title/100",[21,252.952,1119,317.912,1125,436.376,2780,515.098,3455,388.117,3456,457.62]],["content/100",[10,8.968,18,3.409,21,5.493,73,3.271,83,9.709,111,8.736,124,5.37,145,2.668,191,6.443,201,8.429,215,6.305,233,4.227,245,2.632,266,6.173,294,8.736,308,3.362,328,6.048,404,5.3,512,7.261,721,3.91,725,4.164,1189,5.3,1565,6.443,1583,6.742,1600,10.735,1854,5.928,2245,11.187,2263,11.187,2835,9.082,2899,11.187,3370,11.187,3455,8.429,3456,9.938,3457,13.527,3458,13.527,3459,13.527,3460,9.477]],["keywords/100",[]],["title/101",[83,459.424,3455,490.104,3461,786.514,3462,786.514]],["content/101",[3,3.082,23,2.431,34,3.583,83,9.372,86,1.258,89,4.653,127,8.757,142,4.955,145,2.806,153,4.726,212,3.368,216,2.241,219,3.527,239,3.393,262,7.439,273,7.129,275,3.758,292,7.129,293,8.781,300,4.653,308,2.639,369,7.439,382,3.884,413,7.439,483,3.82,526,4.235,624,3.043,721,3.347,766,4.088,798,3.368,799,8.068,877,3.22,1178,5.555,1185,4.8,1223,5.555,1284,4.476,1315,4.653,1322,5.292,1332,7.801,1350,5.555,1402,3.95,1447,7.129,1525,6.202,1556,5.057,1705,6.202,1706,4.846,1890,6.857,1892,5.854,2029,7.801,2138,8.612,2230,7.439,2615,9.51,2736,7.09,3368,8.236,3431,7.439,3439,6.857,3455,11.462,3463,12.742,3464,8.781,3465,10.618,3466,8.781,3467,11.765,3468,10.618,3469,10.618,3470,9.51,3471,9.51,3472,10.618,3473,10.618,3474,10.618,3475,11.765,3476,8.781,3477,10.618,3478,9.51,3479,10.618,3480,9.51,3481,8.781,3482,12.445,3483,5.7,3484,10.618,3485,9.51,3486,10.618,3487,10.618,3488,9.51]],["keywords/101",[]],["title/102",[360,507.965,1983,507.965,3455,490.104,3456,577.87]],["content/102",[3,2.803,20,3.208,22,2.367,23,2.211,45,4.317,56,8.311,74,3.718,83,5.641,86,2.049,98,2.367,104,3.718,124,2.763,125,4.572,127,4.501,140,8.912,141,4.106,142,4.646,153,3.208,184,7.121,188,4.407,212,4.847,217,5.325,219,3.208,233,4.168,245,1.879,262,6.766,265,3.592,273,6.483,289,3.208,316,5.845,346,6.695,404,5.986,416,4.501,481,4.929,499,3.258,543,3.31,624,2.066,697,5.184,720,5.135,721,3.876,725,4.106,761,6.017,827,4.929,978,8.311,989,6.237,1000,6.766,1013,6.237,1224,8.038,1333,3.851,1346,4.6,1565,4.6,1578,6.496,1580,8.65,1595,6.483,1600,6.237,1630,6.483,1665,11.03,1683,7.491,1703,7.095,1705,5.641,1854,4.232,1866,5.82,1887,8.038,1892,8.424,1894,9.799,1953,8.65,1976,7.491,1977,10.258,1981,5.82,1983,11.167,2138,5.184,2273,6.017,2319,10.346,2352,6.766,2622,7.986,2656,6.483,3439,6.237,3455,8.311,3456,9.799,3460,11.544,3475,7.986,3476,7.986,3489,9.799,3490,7.491,3491,8.65,3492,9.657,3493,9.657,3494,9.657,3495,8.65,3496,11.03,3497,8.65,3498,5.82,3499,8.65]],["keywords/102",[]],["title/103",[289,354.397,697,572.688]],["content/103",[3,3.874,18,3.363,22,3.272,23,1.735,53,2.298,73,1.832,74,4.317,83,9.196,86,1.748,91,4.638,104,2.917,109,3.609,110,5.866,116,1.621,125,2.597,127,3.532,134,5.521,140,3.777,141,2.333,145,2.211,153,2.517,208,4.474,217,4.178,219,3.725,275,3.969,289,3.725,300,3.32,307,4.234,308,3.317,309,4.567,312,2.478,315,4.894,319,2.864,344,3.458,346,3.32,357,4.393,365,3.32,402,2.517,444,7.856,447,4.171,454,3.135,499,2.557,508,3.458,574,3.691,624,1.621,625,6.464,630,2.819,675,2.917,697,6.019,705,6.787,743,4.894,801,4.722,802,4.722,820,3.194,825,6.266,826,3.691,1125,7.856,1189,2.969,1264,6.758,1332,5.567,1347,5.878,1392,5.567,1436,5.309,1686,4.426,1706,5.117,1712,3.691,1838,5.567,1854,3.32,1893,6.266,1903,4.426,1977,5.087,1983,11.016,1991,6.787,2023,4.426,2354,5.087,2656,5.087,2938,6.266,3115,6.266,3374,10.837,3439,4.894,3460,10.334,3464,9.273,3471,6.787,3495,10.043,3496,12.199,3497,10.043,3500,7.577,3501,11.212,3502,4.894,3503,7.577,3504,7.577,3505,7.577,3506,7.577,3507,5.309,3508,7.577,3509,7.577,3510,7.577,3511,7.577,3512,7.577,3513,7.577,3514,13.346,3515,7.577,3516,5.309,3517,6.787,3518,7.577,3519,11.954,3520,7.577,3521,10.043,3522,7.577,3523,14.765,3524,7.577,3525,11.212,3526,7.577,3527,7.577,3528,6.266,3529,7.577,3530,7.577,3531,7.577,3532,7.577,3533,10.043,3534,7.577,3535,12.212,3536,7.577,3537,7.577,3538,7.577,3539,10.043,3540,10.043,3541,8.697,3542,7.577,3543,6.787,3544,6.787,3545,5.567,3546,5.878,3547,6.266,3548,6.787,3549,7.577,3550,6.787,3551,7.577]],["keywords/103",[]],["title/104",[985,605.017,3550,955.587]],["content/104",[13,3.777,18,2.129,23,3.252,54,5.781,68,3.561,83,7.09,86,1.438,91,3.495,98,2.071,113,5.672,124,2.417,125,2.896,137,5.781,141,4.373,145,1.666,154,3.091,164,3.702,170,4.115,184,6.622,185,2.525,198,8.563,212,2.68,216,2.998,219,2.806,239,2.895,245,1.644,256,3.369,299,4.935,300,3.702,305,6.35,337,7.316,346,5.319,374,3.473,381,4.211,499,4.794,507,5.919,508,5.539,526,3.369,605,5.216,624,3.663,625,5.319,626,4.935,721,1.988,764,3.561,797,8.011,826,5.912,978,8.852,1020,6.693,1049,5.264,1118,7.567,1181,5.264,1189,3.31,1221,5.456,1332,8.918,1333,4.841,1432,5.021,1436,5.919,1477,6.195,1566,5.456,1709,4.115,1710,5.672,1782,4.115,1837,5.919,1854,3.702,1866,7.316,1891,15.802,1911,4.935,1966,7.564,1967,6.987,1969,6.884,1977,12.119,1983,11.872,2058,7.567,2263,6.987,2314,5.919,2360,4.935,2399,7.567,2455,6.553,2482,7.567,2546,6.207,2548,6.553,2628,8.504,2969,6.987,3321,6.987,3418,8.149,3456,6.207,3460,11.997,3476,6.987,3482,6.553,3485,7.567,3489,6.207,3535,9.415,3548,10.872,3552,8.448,3553,8.448,3554,8.448,3555,12.138,3556,8.448,3557,8.448,3558,8.448,3559,8.448,3560,8.448,3561,12.138,3562,8.448,3563,5.919,3564,5.919,3565,8.448,3566,6.553,3567,6.987,3568,8.448,3569,8.448,3570,7.567,3571,8.448,3572,6.207,3573,7.567]],["keywords/104",[]],["title/105",[185,270.628,239,215.958,1510,702.378]],["content/105",[8,2.92,13,2.62,23,1.341,53,1.777,68,2.47,83,5.382,86,1.53,91,4.71,98,1.436,127,2.731,135,2.009,140,2.92,141,2.836,153,1.946,167,1.916,179,2.143,208,2.795,219,1.946,239,1.397,245,1.14,260,3.784,265,2.18,307,2.923,319,2.848,337,3.531,346,4.037,358,3.958,367,4.488,369,6.455,374,1.676,382,2.143,402,4.288,431,4.99,444,4.105,447,4.236,454,2.424,456,3.966,459,4.294,473,4.105,483,3.315,525,3.784,526,2.337,605,3.959,608,3.261,613,6.662,625,2.568,630,2.18,720,3.547,735,5.248,797,2.854,820,4.8,826,2.854,877,1.777,908,4.105,913,6.278,1012,4.305,1125,4.105,1290,3.784,1307,3.651,1315,2.568,1328,3.531,1329,3.531,1400,4.846,1432,2.424,1440,3.231,1510,4.545,1520,4.545,1565,2.791,1612,4.545,1696,3.423,1703,4.305,1706,2.674,1761,5.248,1890,3.784,1894,4.305,1977,8.667,1983,10.726,2021,5.248,2118,6.769,2138,4.946,2285,3.784,2314,4.105,2504,9.484,2541,4.545,2834,4.846,2841,7.147,3110,4.846,3258,8.253,3319,6.455,3374,10.947,3439,3.784,3455,7.095,3463,5.248,3464,4.846,3466,4.846,3467,4.846,3470,5.248,3483,6.929,3496,13.353,3519,10.199,3521,8.253,3523,8.253,3533,5.248,3535,8.832,3539,11.562,3540,10.199,3541,10.013,3545,10.311,3574,5.248,3575,5.859,3576,5.859,3577,3.784,3578,5.859,3579,6.278,3580,5.859,3581,9.214,3582,5.859,3583,11.386,3584,8.253,3585,4.545,3586,5.859,3587,5.859,3588,5.859,3589,11.386,3590,9.214,3591,5.859,3592,3.934,3593,5.859,3594,5.859,3595,5.859,3596,11.386,3597,15.781,3598,10.199,3599,12.908,3600,12.908,3601,16.146,3602,5.859,3603,5.859,3604,9.214,3605,9.214,3606,9.214,3607,5.859,3608,9.214,3609,5.859,3610,9.214,3611,5.859,3612,5.859,3613,5.859,3614,5.859,3615,5.859,3616,5.859,3617,5.859,3618,5.859,3619,5.859,3620,5.859,3621,9.214,3622,5.859,3623,5.859,3624,5.859,3625,5.859,3626,5.859,3627,5.859,3628,5.859,3629,15.587,3630,5.859,3631,5.859,3632,9.214,3633,5.859,3634,9.214,3635,5.859,3636,5.859,3637,5.859,3638,5.859,3639,14.034,3640,5.859,3641,5.859,3642,5.859,3643,5.859,3644,5.859,3645,5.859,3646,5.859,3647,4.545,3648,5.248,3649,4.846]],["keywords/105",[]],["title/106",[1311,715.826]],["content/106",[18,2.601,22,3.421,23,2.362,34,5.336,54,4.915,57,5.539,68,5.883,79,4.043,83,9.237,86,1.874,100,3.713,115,4.915,124,2.953,125,3.537,134,4.269,140,5.143,145,2.753,167,3.375,190,3.274,201,6.43,216,2.178,239,2.461,273,9.37,275,3.653,277,5.852,289,3.428,381,5.143,405,15.086,483,3.713,499,3.482,624,3.383,625,6.116,668,8.005,675,3.973,697,5.539,721,3.283,764,4.35,798,5.017,799,5.852,826,6.797,827,5.267,874,4.71,877,3.13,913,5.69,1049,6.43,1119,5.267,1163,6.43,1169,6.22,1178,5.399,1185,3.482,1284,5.883,1290,6.665,1307,6.43,1333,4.116,1346,4.915,1525,6.028,1610,9.243,1696,6.028,1699,6.928,1846,5.852,1854,4.522,1892,5.69,1977,9.37,1983,11.43,2138,8.489,2196,9.243,2273,6.43,2826,6.665,3311,8.005,3350,7.23,3363,6.665,3439,6.665,3455,6.43,3460,11.079,3478,9.243,3535,8.005,3541,8.005,3650,10.319,3651,10.319,3652,10.319,3653,14.637,3654,8.005,3655,10.319,3656,10.319,3657,10.319]],["keywords/106",[]],["title/107",[10,392.002,3299,650.452,3658,704.484,3659,704.484]],["content/107",[]],["keywords/107",[]],["title/108",[106,507.965,350,374.625,358,192.807,3660,610.095]],["content/108",[7,4.588,22,2.82,23,3.821,54,5.479,55,7.724,86,1.978,106,11.849,107,10.071,116,2.461,124,4.292,127,5.362,135,3.943,203,8.923,212,3.65,216,3.166,239,2.744,274,10.06,275,4.072,276,9.041,316,5.041,350,5.479,409,4.139,430,6.092,456,4.007,484,5.734,605,4.943,630,4.28,726,4.983,744,5.143,764,4.849,798,3.65,873,8.452,1185,3.882,1189,4.507,1376,4.759,1534,6.343,1571,7.656,1593,4.849,1685,6.524,1896,7.618,1933,8.452,2026,5.479,2068,5.603,2292,5.603,2340,6.343,2344,7.43,2736,5.734,3070,7.168,3312,10.304,3660,11.636,3661,6.933,3662,6.175,3663,11.504,3664,11.504,3665,8.06,3666,11.504,3667,11.504,3668,10.304,3669,11.504,3670,10.304,3671,11.504,3672,11.504,3673,11.504,3674,11.504,3675,11.504,3676,9.514,3677,8.923,3678,11.504]],["keywords/108",[]],["title/109",[3,163.761,10,281.174,350,268.71,608,199.702,3308,146.175,3662,302.835,3679,311.066]],["content/109",[2,7.064,7,4.823,8,6.027,10,7.721,22,2.964,23,2.768,27,5.519,45,5.407,73,2.924,104,5.964,107,8.119,116,2.587,130,5.636,145,3.056,159,6.858,245,2.353,265,4.499,269,10.401,316,5.299,319,2.783,358,2.964,447,4.499,454,5.003,608,4.281,624,2.587,630,4.499,637,7.064,664,7.288,764,5.098,1163,7.535,1623,8.885,1686,7.064,1896,5.519,2068,5.89,2110,10.831,2390,8.119,2899,10.001,3308,4.014,3660,12.017,3662,8.316,3668,13.876,3679,8.542,3680,10.831,3681,12.812,3682,10.001,3683,8.885,3684,10.831,3685,12.093,3686,12.093,3687,12.093,3688,10.831,3689,12.093,3690,10.001,3691,15.492,3692,12.093,3693,11.382]],["keywords/109",[]],["title/110",[7,277.257,350,331.12,418,267.63,455,487.052,3661,418.984]],["content/110",[3,5.014,7,4.931,10,6.162,18,3.116,27,7.171,45,5.528,54,5.889,58,7.704,73,3.799,127,5.763,130,5.763,143,6.817,156,7.452,179,4.523,216,2.609,284,11.074,308,4.293,312,5.945,316,5.418,319,2.48,357,4.844,358,3.031,409,4.449,430,5.021,447,4.6,454,5.115,455,8.662,459,5.763,721,2.909,833,5.313,1119,8.02,1258,5.763,1618,7.452,1679,7.704,1896,5.643,2027,8.662,2541,9.591,2555,7.985,2736,6.162,3396,6.162,3400,9.084,3489,9.084,3579,6.817,3661,10.954,3680,11.074,3681,10.225,3682,10.225,3694,12.995,3695,12.364,3696,12.364,3697,14.074]],["keywords/110",[]],["title/111",[104,239.785,145,122.846,265,231.708,350,296.668,613,278.47,1854,272.94]],["content/111",[10,5.578,20,3.718,22,2.744,45,5.004,64,5.331,73,3.562,77,6.746,84,4.63,86,1.746,93,5.999,104,5.672,116,2.394,127,8.702,130,5.217,131,3.605,144,9.256,145,2.906,153,3.718,190,3.551,216,2.362,245,2.178,261,6.974,265,5.481,312,3.661,316,4.905,319,2.513,358,2.744,382,5.39,416,5.217,430,4.545,447,4.164,454,4.63,484,5.578,526,4.464,608,3.962,624,2.394,638,6.746,764,4.718,1223,5.856,1349,6.171,1445,7.842,1477,5.713,1704,6.746,1705,6.538,1854,4.905,2027,7.842,2065,8.223,2147,6.746,2733,8.682,3308,2.9,3327,3.898,3649,9.256,3661,10.548,3662,7.909,3679,8.124,3684,10.025,3690,12.184,3698,14.733,3699,8.223,3700,9.256,3701,7.229,3702,11.192,3703,11.192,3704,11.192,3705,11.192,3706,11.192,3707,9.256,3708,14.733,3709,11.192,3710,11.192,3711,11.192]],["keywords/111",[]],["title/112",[265,292.594,289,261.271,350,374.625,365,344.662]],["content/112",[8,4.461,10,6.304,18,2.256,22,3.908,23,2.049,68,3.773,73,3.058,91,3.703,98,2.194,104,3.446,111,5.781,116,3.734,127,5.896,130,4.172,135,3.068,137,4.264,141,2.756,144,7.403,145,1.765,153,2.973,159,7.173,167,5.214,179,4.627,180,8.169,184,6.837,185,3.78,190,5.057,198,6.974,208,2.715,212,2.84,229,4.569,256,3.57,265,4.705,276,8.841,286,5.076,289,4.873,308,2.225,312,2.928,316,3.923,319,1.816,344,5.773,374,3.619,409,3.221,416,4.172,459,4.172,484,4.461,485,5.578,508,4.085,526,3.57,624,1.915,626,5.229,664,5.395,726,2.973,743,5.781,764,7.089,798,2.84,1012,6.577,1119,4.569,1182,6.271,1189,3.507,1206,7.403,1258,4.172,1314,6.943,1321,6.577,1322,4.461,1349,4.936,1448,8.018,1466,3.703,1556,4.264,1565,4.264,1571,7.487,1609,6.01,1862,6.943,1892,4.936,1970,6.943,2068,4.36,2283,3.773,2297,7.403,2340,6.974,2624,6.01,2650,6.271,2825,5.076,2826,9.473,3308,2.319,3375,6.974,3384,9.473,3396,4.461,3402,7.388,3450,6.271,3564,6.271,3661,5.395,3662,4.805,3677,11.378,3679,4.936,3681,7.403,3683,9.293,3694,10.46,3712,8.951,3713,11.329,3714,8.018,3715,8.951,3716,8.951,3717,8.951,3718,8.018,3719,7.403,3720,8.951,3721,8.018,3722,12.131,3723,10.777,3724,6.943,3725,12.649,3726,8.951,3727,12.649,3728,8.951]],["keywords/112",[]],["title/113",[179,287.728,216,165.981,350,374.625,561,366.594]],["content/113",[3,3.164,10,5.432,22,3.549,23,2.495,27,5.955,45,4.873,53,2.212,58,6.791,73,3.746,84,3.017,86,0.864,104,5.573,106,4.71,109,3.474,116,3.477,127,3.399,130,6.747,137,5.191,141,2.245,145,2.855,179,3.987,185,2.18,187,5.359,210,5.657,216,2.3,233,3.406,245,2.121,265,4.854,282,4.396,307,3.457,308,3.243,312,2.386,319,2.935,333,2.808,336,3.017,344,3.328,350,3.474,377,3.328,409,2.624,422,3.915,430,2.962,447,2.713,449,3.51,454,4.508,456,2.54,524,2.54,596,2.808,624,2.791,630,4.854,635,3.261,721,3.07,726,2.423,764,6.102,808,6.533,826,3.552,877,2.212,978,4.545,979,4.26,1258,3.399,1284,3.074,1349,6.009,1376,3.017,1466,3.017,1583,5.432,1593,3.074,1696,4.26,1704,4.396,1721,4.396,1782,5.308,1848,5.11,1854,3.196,1896,3.328,1898,5.11,1969,4.136,2026,3.474,2147,4.396,2182,9.013,2316,4.897,2350,3.915,2357,5.11,2499,4.26,2621,4.897,2825,4.136,2905,5.11,3311,5.657,3316,5.657,3327,2.54,3329,4.897,3375,9.289,3384,8.427,3498,4.396,3516,5.11,3574,6.533,3660,8.454,3661,6.568,3662,7.771,3676,6.032,3679,7.982,3683,5.359,3690,6.032,3697,6.533,3700,6.032,3701,4.71,3714,6.533,3722,10.791,3723,5.359,3729,6.032,3730,7.293,3731,3.635,3732,7.293,3733,7.293,3734,7.293,3735,7.293,3736,7.293,3737,7.293,3738,6.032,3739,7.293,3740,7.636,3741,7.293,3742,7.293,3743,7.293,3744,7.293,3745,7.293,3746,7.293,3747,7.293,3748,7.293,3749,7.293,3750,7.293,3751,4.897,3752,10.142,3753,6.032,3754,7.293,3755,7.293,3756,9.142,3757,5.657,3758,5.657,3759,5.657,3760,5.359,3761,5.657,3762,6.032,3763,6.533,3764,6.533]],["keywords/113",[]],["title/114",[1696,459.424,3658,704.484,3659,704.484,3765,551.044]],["content/114",[]],["keywords/114",[]],["title/115",[108,325.369,164,344.662,358,192.807,1593,331.546]],["content/115",[13,3.204,16,3.34,18,2.711,21,2.911,79,2.808,84,2.965,85,10.817,86,1.275,91,4.45,93,2.457,94,7.325,108,4.45,115,3.414,116,2.301,125,2.457,130,5.014,135,2.457,140,6.436,141,2.206,160,3.204,164,3.141,190,2.274,222,6.739,256,2.858,275,2.537,308,1.781,312,3.518,319,2.97,333,2.759,386,7.49,417,5.25,422,3.847,456,2.496,459,3.34,481,3.658,508,3.271,613,3.204,670,5.266,798,2.274,811,10.544,1019,4.466,1181,4.466,1284,4.534,1320,3.658,1376,4.45,1392,5.266,1522,4.064,1526,4.812,1578,3.491,1583,3.572,1593,4.534,1630,4.812,1807,5.021,1880,10.054,1896,3.271,1966,4.466,1969,4.064,2072,8.344,2235,5.559,2350,3.847,2363,8.763,2388,11.868,2395,12.854,2512,5.927,2621,4.812,2629,5.927,2631,5.927,3109,8.344,3168,5.266,3308,3.718,3327,2.496,3329,4.812,3355,5.559,3359,4.812,3360,3.847,3375,3.952,3378,10.544,3379,9.268,3391,6.419,3516,5.021,3564,5.021,3752,7.536,3756,5.021,3757,5.559,3758,5.559,3759,5.559,3760,5.266,3761,10.016,3762,5.927,3763,6.419,3764,6.419,3765,5.021,3766,4.812,3767,6.419,3768,7.167,3769,7.167,3770,5.927,3771,5.927,3772,9.158,3773,7.536,3774,11.566,3775,12.912,3776,12.912,3777,12.912,3778,14.35,3779,11.868,3780,9.635,3781,9.635,3782,6.419,3783,9.635,3784,9.635,3785,6.419,3786,7.167,3787,7.167,3788,7.167,3789,5.559,3790,7.167,3791,4.629,3792,9.635,3793,6.419,3794,6.419,3795,7.167,3796,7.167]],["keywords/115",[]],["title/116",[45,310.809,164,304.637,608,246.084,3723,510.763,3797,466.741]],["content/116",[16,3.229,21,2.813,22,1.698,25,3.536,40,4.474,73,1.675,79,2.714,84,2.865,85,11.174,86,1.242,91,2.865,93,3.594,94,7.2,108,2.865,109,3.299,114,4.651,116,1.482,124,1.982,130,3.229,131,4.074,135,2.374,145,2.068,153,2.301,160,3.097,162,3.452,164,3.035,167,2.266,190,2.197,216,2.669,222,6.64,245,1.348,279,4.853,300,3.035,307,2.197,312,3.429,319,2.961,374,3,377,3.161,386,7.38,417,5.16,422,3.718,430,2.813,449,2.231,454,2.865,456,2.413,459,3.229,613,3.097,627,4.046,720,2.667,811,10.364,877,2.101,879,4.046,998,5.373,1019,4.316,1119,3.536,1178,3.624,1223,3.624,1321,5.089,1376,4.337,1402,3.9,1432,4.337,1522,3.928,1685,3.928,1697,4.046,1807,4.853,1846,3.928,1880,9.883,1896,3.161,1969,3.928,2095,6.204,2144,12.634,2246,4.316,2363,9.133,2384,11.133,2388,10.461,2745,6.204,3115,5.728,3308,2.716,3327,2.413,3329,4.651,3360,5.628,3375,6.975,3378,10.364,3379,9.786,3419,7.703,3428,8.67,3516,4.853,3564,4.853,3662,3.718,3679,3.819,3723,9.293,3752,4.853,3756,4.853,3757,5.373,3758,5.373,3759,5.373,3760,5.089,3761,8.132,3762,5.728,3766,4.651,3770,5.728,3772,9.389,3773,8.862,3774,11.33,3779,12.531,3780,9.39,3781,9.39,3782,6.204,3783,9.39,3784,9.39,3785,6.204,3791,4.474,3792,6.204,3797,4.651,3798,6.927,3799,6.927,3800,6.927,3801,6.927,3802,6.927,3803,6.927,3804,6.927,3805,6.927,3806,6.927,3807,12.649,3808,14.106,3809,6.927,3810,6.927,3811,6.927,3812,10.484,3813,6.204,3814,6.204]],["keywords/116",[]],["title/117",[164,396.796,418,348.594,3815,811.045]],["content/117",[2,5.091,21,5.04,22,3.543,66,3.539,73,3.495,84,3.605,85,9.493,86,1.713,91,3.605,95,5.253,108,5.134,115,4.151,116,1.864,124,3.551,130,4.062,131,3.998,162,4.344,164,3.819,179,3.188,212,2.765,222,3.819,233,2.723,303,7.48,312,4.728,319,2.799,336,3.605,344,5.664,374,4.136,377,3.977,386,4.245,422,4.678,430,3.539,454,3.605,455,6.106,456,3.036,459,4.062,499,2.941,509,7.208,554,5.253,626,5.091,630,3.242,721,3.401,726,2.895,833,7.153,877,2.643,879,7.25,978,7.734,1019,5.431,1174,7.806,1284,3.674,1348,5.629,1369,5.629,1399,5.253,1402,3.242,1685,4.942,1697,5.091,1806,5.629,1896,6.597,1969,4.942,2217,7.806,2283,3.674,2316,5.851,2318,4.942,2360,5.091,2363,7.562,2384,9.119,2397,6.76,2654,5.629,3308,3.216,3327,3.036,3329,5.851,3344,4.062,3358,7.806,3375,9.179,3417,14.911,3428,7.208,3516,6.106,3564,6.106,3579,4.806,3662,7.759,3679,7.97,3723,6.403,3752,6.106,3756,6.106,3757,6.76,3758,6.76,3759,6.76,3760,6.403,3761,12.218,3766,5.851,3770,7.208,3779,7.208,3813,7.806,3815,11.117,3816,7.208,3817,8.715,3818,8.715,3819,8.715,3820,8.715,3821,8.715,3822,12.411,3823,6.106,3824,8.715,3825,8.715,3826,8.715,3827,8.715,3828,8.715,3829,8.715,3830,8.715,3831,5.851,3832,8.715,3833,8.715,3834,8.715,3835,8.715,3836,8.715,3837,8.715,3838,8.715]],["keywords/117",[]],["title/118",[3839,1298.223]],["content/118",[10,7.029,16,7.947,20,4.685,73,3.41,145,2.782,160,6.306,164,6.18,219,4.685,223,6.06,233,4.407,250,7.029,256,5.625,275,4.992,374,4.035,508,6.436,630,5.247,743,9.109,744,6.306,1189,5.526,1216,9.109,1218,9.881,1571,7.199,1676,9.109,1878,12.633,2027,9.881,2359,10.362,2557,11.664,3840,11.664,3841,12.633,3842,14.103,3843,14.103,3844,14.103,3845,12.633,3846,14.103]],["keywords/118",[]],["title/119",[217,433.675,1711,610.095,3200,551.044,3308,203.791]],["content/119",[]],["keywords/119",[]],["title/120",[300,467.512,3847,955.587]],["content/120",[3,3.174,8,5.449,22,2.68,48,6.029,53,3.316,66,4.44,73,2.644,74,4.209,86,1.719,91,4.523,98,3.556,116,2.339,141,4.466,145,2.156,198,6.029,216,3.659,222,4.791,245,3.374,252,5.449,275,3.87,308,2.717,374,3.128,376,8.743,382,4,447,4.067,449,3.522,624,2.339,664,6.59,675,4.209,741,6.59,744,6.486,879,6.387,941,5.581,947,6.2,1049,6.813,1169,6.59,1178,5.72,1185,4.895,1322,7.23,1333,4.361,1340,8.481,1346,6.91,1376,4.523,1434,8.481,1439,6.59,1463,7.341,1578,5.325,1583,5.449,1697,6.387,1704,6.59,1712,7.066,1715,6.813,1837,7.66,1846,6.2,1987,9.793,2068,7.066,2250,7.66,2255,9.042,2354,7.341,2706,7.061,2736,5.449,2832,9.042,3104,11.997,3200,7.66,3308,2.833,3442,8.481,3450,7.66,3848,9.793,3849,10.933,3850,10.933,3851,9.793,3852,10.933,3853,10.933,3854,10.933,3855,10.933,3856,10.933,3857,10.933,3858,9.793,3859,10.933,3860,10.933,3861,10.933,3862,8.033,3863,7.341,3864,10.933,3865,10.933,3866,10.933]],["keywords/120",[]],["title/121",[3867,1066.856,3868,827.555]],["content/121",[7,2.662,16,3.111,18,1.682,21,4.14,22,3.031,23,1.528,53,3.092,54,4.855,55,4.482,64,3.179,68,4.297,86,1.766,93,3.494,96,4.311,98,3.031,100,2.402,116,3.695,117,4.482,124,2.916,125,2.288,131,2.15,134,2.761,135,2.288,140,5.08,141,4.589,145,2.439,153,4.597,156,4.023,160,2.984,162,3.327,164,2.925,173,4.482,175,5.979,190,2.118,193,4.904,201,4.16,212,4.391,216,2.609,232,4.904,233,4.325,239,2.431,244,4.482,245,2.406,252,3.327,256,2.662,273,4.482,281,4.904,292,4.482,300,2.925,307,2.118,319,1.463,333,2.57,353,3.899,365,2.925,374,3.96,377,3.046,406,5.52,430,2.711,431,2.925,473,4.677,481,3.407,485,4.16,510,5.178,524,2.325,605,2.868,624,2.645,625,2.925,627,3.899,664,4.023,680,5.763,720,3.924,744,4.557,764,2.814,787,4.482,794,5.78,798,3.234,871,4.751,877,2.025,894,7.141,913,5.62,928,7.141,958,5.52,980,4.311,985,3.785,1012,4.904,1028,9.592,1119,3.407,1181,4.16,1184,5.979,1185,2.252,1198,5.472,1205,4.904,1264,4.023,1284,2.814,1315,2.925,1319,3.899,1333,2.662,1334,4.023,1335,5.178,1369,4.311,1380,3.899,1395,3.492,1440,3.681,1463,4.482,1466,2.761,1502,5.178,1534,3.681,1565,4.855,1571,5.203,1578,3.251,1593,2.814,1676,4.311,1706,3.046,1710,6.844,1712,7.26,1839,4.904,1844,5.52,1846,5.78,2026,3.179,2035,5.178,2052,5.178,2068,3.251,2344,4.311,2350,3.583,2354,6.844,2499,5.954,2549,5.979,2706,4.311,2736,3.327,2744,8.43,2808,5.178,2836,4.904,2922,5.979,2940,4.311,2962,4.677,3028,9.13,3163,5.52,3184,5.178,3200,7.141,3308,4.072,3315,4.482,3346,10.169,3362,5.52,3442,7.907,3447,4.311,3502,4.311,3563,4.677,3572,4.904,3579,3.681,3719,5.52,3869,6.675,3870,6.675,3871,5.52,3872,6.675,3873,6.675,3874,6.675,3875,5.979,3876,6.675,3877,6.675,3878,6.675,3879,6.675,3880,6.675,3881,6.675,3882,10.193,3883,6.675,3884,6.675,3885,6.675,3886,5.178,3887,6.675,3888,6.675,3889,6.675,3890,6.675,3891,6.675,3892,6.675,3893,6.675,3894,5.52,3895,6.675,3896,6.675,3897,6.675,3898,6.675,3899,5.979,3900,6.675,3901,6.675,3902,4.904,3903,6.675,3904,6.675,3905,6.675,3906,6.675,3907,5.979,3908,6.675,3909,6.675,3910,6.675,3911,6.675,3912,6.675,3913,6.675,3914,6.675,3915,6.675,3916,6.675,3917,6.675,3918,6.675,3919,5.979,3920,6.675,3921,6.675,3922,6.675,3923,6.675,3924,6.675,3925,6.675,3926,5.979,3927,6.675,3928,5.979,3929,6.675]],["keywords/121",[]],["title/122",[86,107.292,3309,451.297,3930,905.483]],["content/122",[7,5.352,13,4.356,16,4.541,20,3.236,21,3.956,23,2.23,34,4.528,54,4.64,64,4.64,68,4.107,73,2.356,76,8.726,77,5.872,86,1.59,98,2.388,100,3.505,115,4.64,117,6.541,125,3.34,131,3.138,135,3.34,140,4.855,145,1.921,159,5.525,184,4.541,190,3.091,191,4.64,195,6.071,215,4.541,216,2.056,233,4.796,239,2.323,256,3.885,275,4.75,279,6.825,316,4.269,511,6.071,543,3.34,554,5.872,605,5.766,624,2.084,635,4.356,707,5.872,720,3.75,725,4.131,726,3.236,766,3.75,809,7.158,877,2.955,879,5.691,941,4.972,977,5.23,1129,9.401,1177,5.525,1189,3.817,1315,4.269,1322,4.855,1333,3.885,1335,7.557,1402,3.624,1578,4.745,1618,5.872,1696,5.691,1699,6.541,1702,7.557,1712,4.745,1854,4.269,1859,6.825,1988,6.825,2028,7.158,2068,8.448,2147,5.872,2292,6.535,2322,8.057,2340,5.372,3187,8.726,3200,9.401,3308,4.285,3315,6.541,3316,7.557,3418,6.541,3729,8.057,3851,8.726,3931,8.726,3932,9.742,3933,9.742,3934,9.742,3935,8.726,3936,13.418,3937,13.418,3938,15.349,3939,9.742,3940,9.742,3941,9.742,3942,9.742,3943,13.418,3944,9.742,3945,9.742,3946,9.742,3947,9.742,3948,9.742,3949,9.742,3950,9.742,3951,13.418,3952,8.726,3953,9.742,3954,9.742,3955,9.742,3956,9.742,3957,9.742,3958,9.742,3959,9.742,3960,8.726,3961,9.742,3962,8.726,3963,9.742]],["keywords/122",[]],["title/123",[380,748.84,3964,905.483,3965,905.483]],["content/123",[16,7.978,17,6.835,18,2.667,23,3.918,66,4.298,68,4.461,98,2.594,100,3.808,108,6.626,124,3.028,125,3.628,127,4.933,134,6.626,141,4.37,147,5.836,179,3.872,193,7.776,198,5.836,216,2.233,233,5.578,245,2.059,288,8.753,289,3.516,308,3.981,316,4.638,333,4.075,359,6.182,374,4.062,380,8.753,381,5.275,384,8.753,404,4.147,415,6.182,416,4.933,430,4.298,456,3.686,481,5.402,574,5.155,633,7.776,635,4.732,637,6.182,718,8.21,720,4.075,725,4.37,798,3.358,809,7.776,834,6.835,877,3.21,913,5.836,914,6.595,1322,5.275,1332,7.776,1346,5.041,1394,8.753,1402,5.281,1583,5.275,1696,6.182,1856,9.48,1859,7.415,1933,7.776,2336,6.835,2546,7.776,3498,6.379,3966,10.584,3967,10.584,3968,10.584,3969,7.776,3970,14.196,3971,16.018,3972,10.584,3973,9.48,3974,17.116,3975,10.584,3976,10.584,3977,10.584,3978,10.584,3979,9.48,3980,10.584,3981,10.584,3982,10.584,3983,10.584,3984,10.584,3985,10.584,3986,8.21,3987,10.584,3988,10.584,3989,10.584]],["keywords/123",[]],["title/124",[1311,588.253,3990,1066.856]],["content/124",[8,5.774,13,5.179,23,2.652,73,2.801,116,2.478,145,2.285,154,4.238,157,9.58,160,5.179,190,3.675,192,10.376,195,7.219,209,7.482,233,5.234,239,2.763,245,2.254,256,4.62,265,4.31,269,7.778,277,6.57,308,3.745,312,3.789,336,4.792,359,6.767,415,6.767,456,4.035,484,7.51,499,3.909,596,4.46,605,4.978,668,8.986,726,5.006,827,5.913,879,6.767,920,8.511,941,7.691,977,6.219,1134,6.219,1177,6.57,1181,7.219,1185,3.909,1223,6.061,1315,6.603,1333,4.62,1373,7.219,1376,4.792,1395,6.061,1430,9.58,1522,6.57,1673,8.116,1704,6.982,1846,6.57,2068,5.642,2143,10.376,2147,6.982,2269,8.986,2314,8.116,2716,9.58,2940,7.482,3200,8.116,3308,3.002,3354,9.58,3665,8.116,3677,8.986,3919,10.376,3969,11.071,3973,10.376,3991,11.584,3992,11.584,3993,11.584,3994,10.376,3995,11.584,3996,15.069,3997,11.584,3998,11.584,3999,11.584,4000,11.584]],["keywords/124",[]],["title/125",[29,610.095,3308,203.791,4001,786.514,4002,704.484]],["content/125",[0,8.118,2,1.496,3,3.984,6,2.458,7,1.826,8,4.326,9,3.551,10,3.764,16,2.134,17,1.654,18,2.187,19,1.452,20,0.851,21,1.04,22,1.122,23,2.396,25,1.307,27,2.089,28,3.074,29,9.599,34,1.545,45,1.145,47,9.599,52,1.882,53,0.777,62,1.654,66,1.04,68,3.659,70,7.178,73,1.107,74,1.762,79,1.794,81,2.458,86,1.669,89,2.006,91,3.124,93,2.975,94,5.342,95,4.552,96,1.654,98,2.363,100,4.252,104,1.762,106,2.957,107,3.074,108,1.059,110,2.395,111,1.654,116,1.857,117,1.72,118,5.043,120,4.815,124,2.758,125,0.878,127,5.213,130,1.194,131,2.433,134,1.059,135,0.878,136,3.868,141,3.443,142,0.892,145,1.489,147,3.423,149,6.533,152,2.957,153,0.851,157,2.118,158,1.596,159,5.935,161,5.858,162,1.276,164,3.309,167,2.03,170,1.247,179,4.092,180,1.654,183,2.118,185,1.855,186,2.118,190,0.812,191,4.134,208,1.389,210,4.815,215,1.194,216,1.31,217,1.412,219,0.851,221,4.561,222,1.122,223,1.967,228,2.118,229,2.337,232,3.364,233,3.867,236,1.987,239,1.801,245,0.891,246,1.544,249,2.957,250,3.764,251,4.101,252,1.276,253,3.364,265,3.229,269,4.168,274,1.544,275,3.705,281,1.882,282,2.759,286,1.452,288,3.786,289,4.425,294,1.654,295,2.294,299,1.496,300,1.122,307,0.812,308,2.396,312,1.497,319,2.07,328,1.145,333,0.986,336,1.059,350,2.181,360,1.654,374,3.811,375,1.882,381,1.276,382,3.175,384,5.134,386,2.23,402,0.851,404,1.003,415,2.674,416,2.134,417,0.937,430,1.04,431,1.122,456,0.892,474,1.34,484,2.282,499,1.545,508,2.089,511,1.596,512,2.458,514,1.544,524,0.892,526,1.021,543,2.128,574,2.23,596,1.762,624,1.615,625,1.122,630,2.809,633,1.882,635,1.145,675,1.762,725,2.672,726,2.509,744,1.145,764,1.08,797,1.247,798,3.058,799,2.596,804,2.294,809,1.882,827,1.307,828,1.987,833,1.101,874,1.169,877,2.633,878,2.294,885,8.118,913,2.524,937,2.294,968,1.794,977,3.332,988,1.882,1119,3.169,1120,1.987,1134,1.375,1135,2.72,1177,3.52,1178,3.951,1182,1.794,1183,1.794,1185,2.548,1186,2.294,1189,1.003,1199,1.412,1205,1.882,1206,2.118,1216,1.654,1221,4.009,1251,4.815,1284,3.659,1315,2.72,1316,5.07,1319,2.674,1320,1.307,1322,1.276,1333,3.462,1346,1.22,1347,1.987,1349,1.412,1350,1.34,1372,1.496,1373,2.853,1376,2.568,1380,1.496,1392,1.882,1394,2.118,1395,1.34,1396,4.101,1402,2.309,1403,1.882,1410,3.364,1434,4.815,1438,1.794,1440,1.412,1466,1.059,1500,1.794,1511,1.375,1522,1.452,1525,1.496,1534,4.786,1535,1.654,1556,1.22,1558,1.72,1565,2.957,1571,3.169,1576,3.551,1578,1.247,1593,1.93,1609,1.72,1612,1.987,1618,2.759,1630,1.72,1673,3.208,1676,1.654,1679,1.596,1686,2.674,1690,2.118,1706,1.169,1710,3.074,1715,1.596,1784,1.794,1803,1.987,1821,1.194,1833,2.118,1837,1.794,1846,1.452,1854,1.122,1890,1.654,1892,1.412,1896,2.833,1911,2.674,1963,2.294,1966,1.596,1988,3.208,2017,2.118,2028,1.882,2029,1.882,2065,1.882,2068,1.247,2072,1.987,2133,2.118,2147,1.544,2148,2.294,2204,2.294,2244,1.987,2246,1.596,2250,3.208,2273,1.596,2283,1.08,2284,2.294,2287,2.118,2299,2.118,2303,2.118,2323,4.101,2344,2.957,2352,1.794,2356,3.074,2357,1.794,2393,2.294,2481,5.56,2506,1.882,2541,1.987,2551,4.101,2617,2.118,2629,2.118,2643,1.496,2654,2.957,2664,1.987,2736,1.276,2838,2.294,2853,3.208,2938,2.118,2940,1.654,3184,1.987,3195,2.118,3197,2.294,3223,1.987,3279,2.118,3308,3.451,3309,2.282,3315,1.72,3344,1.194,3362,2.118,3363,2.957,3431,1.794,3438,2.118,3439,1.654,3449,2.118,3451,2.118,3491,2.294,3498,2.759,3502,1.654,3544,2.294,3546,1.987,3547,2.118,3563,1.794,3567,2.118,3682,2.118,3683,4.561,3693,1.882,3707,3.786,3713,2.294,3794,2.294,3823,1.794,3848,2.294,3935,2.294,4002,2.294,4003,2.561,4004,2.561,4005,2.561,4006,2.561,4007,2.561,4008,2.561,4009,2.561,4010,2.561,4011,2.561,4012,2.561,4013,2.561,4014,2.561,4015,2.561,4016,2.561,4017,2.561,4018,2.561,4019,2.561,4020,2.561,4021,2.561,4022,2.561,4023,2.561,4024,2.561,4025,4.578,4026,2.561,4027,2.561,4028,2.561,4029,15.006,4030,2.561,4031,2.561,4032,2.294,4033,2.561,4034,2.561,4035,2.561,4036,2.294,4037,2.561,4038,2.561,4039,2.561,4040,2.561,4041,2.294,4042,2.561,4043,2.561,4044,2.561,4045,2.561,4046,2.561,4047,2.561,4048,2.561,4049,2.561,4050,4.101,4051,16.769,4052,4.578,4053,2.561,4054,2.561,4055,2.561,4056,2.294,4057,2.561,4058,2.561,4059,2.561,4060,2.561,4061,2.561,4062,2.561,4063,2.561,4064,2.561,4065,2.561,4066,2.561,4067,2.561,4068,2.561,4069,9.25,4070,2.561,4071,7.178,4072,2.561,4073,2.561,4074,2.561,4075,2.561,4076,2.561,4077,6.208,4078,9.639,4079,2.561,4080,2.561,4081,2.561,4082,2.561,4083,2.294,4084,2.561,4085,2.561,4086,14.089,4087,2.561,4088,8.68,4089,2.561,4090,2.561,4091,2.561,4092,2.561,4093,2.561,4094,7.552,4095,2.561,4096,2.561,4097,2.561,4098,2.294,4099,7.552,4100,2.561,4101,2.561,4102,2.561,4103,2.561,4104,2.561,4105,2.561,4106,2.561,4107,2.561,4108,2.561,4109,2.561,4110,4.578,4111,4.578,4112,5.56,4113,4.578,4114,4.578,4115,4.578,4116,4.578,4117,4.578,4118,4.578,4119,2.561,4120,4.578,4121,4.578,4122,4.578,4123,4.578,4124,6.208,4125,2.561,4126,2.561,4127,4.101,4128,2.561,4129,2.561,4130,2.561,4131,4.578,4132,4.578,4133,2.561,4134,2.561,4135,2.561,4136,2.561,4137,1.452,4138,2.561,4139,2.561,4140,4.578,4141,2.561,4142,2.561,4143,2.561,4144,2.561,4145,2.561,4146,2.118,4147,2.561,4148,2.561,4149,2.561,4150,2.561,4151,2.561,4152,2.561,4153,2.561,4154,1.987,4155,2.561,4156,2.561,4157,2.561,4158,2.561,4159,7.552,4160,6.208,4161,2.561,4162,3.786,4163,2.561,4164,2.561,4165,2.561,4166,4.578,4167,4.578,4168,2.561,4169,2.561,4170,2.561,4171,4.578,4172,1.987,4173,2.561,4174,8.68,4175,7.972,4176,2.561,4177,4.578,4178,2.561,4179,2.561,4180,2.561,4181,2.561,4182,2.561,4183,2.561,4184,2.561,4185,2.561,4186,2.561,4187,2.294,4188,2.561,4189,2.294,4190,2.561,4191,2.561,4192,2.294,4193,2.561,4194,1.987,4195,4.578,4196,2.561,4197,2.561,4198,2.294,4199,2.561,4200,2.561,4201,2.118,4202,2.561,4203,2.561,4204,2.561,4205,2.561,4206,2.561,4207,2.561,4208,2.561,4209,2.561,4210,2.561,4211,2.561,4212,2.561,4213,2.561,4214,2.561,4215,2.561,4216,2.294,4217,2.561,4218,2.561,4219,2.561,4220,2.561,4221,2.561]],["keywords/125",[]],["title/126",[2706,507.965,3308,203.791,3363,507.965,4222,474.032]],["content/126",[]],["keywords/126",[]],["title/127",[344,413.24,3447,584.8,4222,545.735]],["content/127",[18,2.274,27,4.119,41,4.035,53,2.737,66,5.167,67,7,73,2.182,74,3.474,75,6.059,77,5.439,79,3.536,84,5.263,86,1.507,93,3.094,94,8.166,131,4.746,134,3.733,142,3.143,156,5.439,160,4.035,167,2.952,211,5.623,222,3.955,233,2.82,245,1.756,275,4.503,289,2.998,319,2.795,337,5.439,344,4.119,358,2.212,374,3.64,382,3.301,409,4.577,449,4.098,456,5.573,498,7.463,543,3.094,623,3.045,624,1.93,637,5.271,644,6.493,664,7.667,665,5.623,674,7.463,725,2.778,743,5.828,744,4.035,798,2.863,833,3.878,877,2.737,880,8.216,933,10.521,979,5.271,1178,4.721,1258,6.867,1284,3.804,1334,5.439,1466,3.733,1593,3.804,1697,5.271,1699,6.059,1782,4.395,1887,5.439,1892,4.976,2026,4.298,2027,6.323,2283,3.804,2322,7.463,2336,5.828,2643,5.271,2826,8.216,2905,6.323,3308,3.296,3319,6.323,3335,8.083,3344,5.93,3360,4.844,3447,11.303,3499,8.083,3546,7,3547,7.463,3584,8.083,3647,7,4137,5.118,4222,9.642,4223,9.024,4224,9.024,4225,9.024,4226,12.393,4227,9.024,4228,8.083,4229,11.395,4230,11.395,4231,12.722,4232,12.722,4233,9.024,4234,12.722,4235,9.024,4236,9.024,4237,12.722,4238,13.197,4239,7,4240,9.024,4241,9.024,4242,11.395,4243,9.024,4244,9.024,4245,9.024,4246,9.024]],["keywords/127",[]],["title/128",[156,418.984,222,304.637,337,418.984,1903,406.071,4222,418.984]],["content/128",[6,3.95,18,1.854,23,1.684,25,6.695,53,3.979,54,3.505,68,3.102,84,5.426,86,1.3,93,3.761,98,2.689,116,2.347,124,2.105,137,3.505,145,1.451,156,6.612,180,4.752,190,3.48,206,5.225,212,2.334,216,1.553,265,2.737,275,2.605,285,4.752,297,5.406,307,3.48,308,1.829,311,6.591,312,4.29,319,2.794,337,4.435,357,2.883,409,5.596,416,3.43,449,3.534,453,3.95,456,5.68,524,2.563,543,5.59,613,6.953,623,4.906,626,4.298,630,2.737,637,4.298,644,7.938,700,3.224,720,2.833,749,11.278,764,5.529,975,8.136,979,7.662,1013,4.752,1119,3.756,1185,2.483,1215,5.708,1284,3.102,1315,3.224,1320,5.6,1346,6.248,1500,5.155,1526,4.94,1535,4.752,1556,3.505,1709,3.584,1806,4.752,1903,8.493,2141,6.591,2283,3.102,2350,3.95,2504,5.406,2654,7.085,2968,9.826,3070,4.585,3308,3.767,3309,3.667,3327,3.821,3360,5.889,3400,5.406,3447,4.752,3564,5.155,3868,5.708,4194,5.708,4222,4.435,4226,8.06,4230,6.591,4238,9.826,4247,7.751,4248,7.358,4249,7.358,4250,7.358,4251,13.117,4252,6.591,4253,10.971,4254,10.971,4255,10.848,4256,17.364,4257,14.014,4258,12.65,4259,9.826,4260,6.085,4261,13.023,4262,11.278,4263,13.487,4264,14.607,4265,13.117,4266,5.708,4267,7.358,4268,7.358,4269,6.591,4270,6.591,4271,9.073,4272,10.971,4273,7.358]],["keywords/128",[]],["title/129",[1712,441.023,3402,528.917,4222,545.735]],["content/129",[3,1.957,17,4.355,18,1.699,25,3.442,53,5.255,68,4.33,73,2.484,84,4.249,89,2.955,93,3.521,98,1.653,116,1.442,127,3.143,131,2.172,135,2.312,141,2.076,153,3.412,160,4.593,162,3.361,184,3.143,185,3.07,195,7.754,206,4.893,212,2.139,216,1.423,222,2.955,223,2.898,239,1.608,245,1.312,262,4.724,285,4.355,286,3.824,289,3.412,299,3.939,300,2.955,307,2.139,312,2.206,319,2.844,358,1.653,370,3.62,374,2.939,409,5.006,416,3.143,417,2.467,431,2.955,449,3.309,456,4.846,499,4.198,512,3.62,514,4.064,543,5.408,574,3.284,624,2.662,626,3.939,630,2.509,644,8.053,680,3.143,725,2.076,744,3.015,749,5.231,798,2.139,811,4.954,820,2.843,880,4.355,913,5.664,947,3.824,979,3.939,1284,2.843,1315,2.955,1320,3.442,1346,6.627,1402,2.509,1511,3.62,1593,2.843,1683,5.231,1696,3.939,1706,3.077,1712,6.06,1784,4.724,1892,3.718,2244,5.231,2269,5.231,2344,6.634,2357,4.724,2628,4.724,2643,3.939,2826,6.634,2828,6.04,3109,5.231,3308,3.605,3311,5.231,3327,4.334,3344,4.788,3363,4.355,3379,4.355,3396,5.12,3402,7.268,3447,4.355,3450,4.724,3647,13.438,3721,6.04,3731,5.12,3823,4.724,3926,6.04,3994,6.04,4071,5.577,4222,7.499,4247,6.202,4257,9.652,4258,10.792,4259,6.04,4260,5.577,4270,6.04,4271,8.495,4274,6.743,4275,6.743,4276,10.272,4277,6.743,4278,6.743,4279,6.04,4280,6.743,4281,6.743,4282,9.142,4283,9.201,4284,6.743,4285,6.04,4286,6.743,4287,5.577,4288,6.743,4289,6.743,4290,6.743,4291,6.743,4292,6.634,4293,6.743,4294,6.743,4295,10.272,4296,12.443,4297,6.743,4298,6.743,4299,6.04,4300,6.743,4301,6.743,4302,6.743,4303,6.743,4304,10.272,4305,6.743,4306,6.743,4307,6.743,4308,6.743,4309,15.777,4310,6.743,4311,6.743,4312,6.743,4313,6.743,4314,6.743,4315,6.743,4316,6.743,4317,6.743,4318,6.743,4319,6.743,4320,6.743,4321,6.743,4322,6.743,4323,6.743,4324,6.743,4325,6.743,4326,6.743,4327,6.743,4328,6.743,4329,12.443,4330,6.743,4331,6.743,4332,6.743,4333,5.577]],["keywords/129",[]],["title/130",[1311,715.826]],["content/130",[22,3.161,45,5.765,68,5.435,73,3.118,116,2.758,131,4.153,212,5.119,222,5.65,223,5.541,256,5.142,266,5.884,308,3.205,374,3.689,480,9.473,514,7.771,623,4.351,700,5.65,726,4.283,1183,9.034,1284,5.435,1333,5.142,1402,4.797,1438,9.034,1463,8.657,1706,5.884,1712,6.28,1833,10.663,1887,9.724,1903,7.532,2094,9.473,2138,6.921,2180,10.663,2273,8.035,2360,7.532,2543,11.549,2643,7.532,2897,9.473,3308,4.181,3309,6.426,3356,10.002,3363,10.42,3488,11.549,3647,10.002,4222,9.724,4247,6.426,4279,11.549,4333,10.663,4334,12.894,4335,9.473,4336,12.894,4337,12.894,4338,12.894]],["keywords/130",[]],["title/131",[1292,607.94,1432,374.584,4339,702.378]],["content/131",[]],["keywords/131",[]],["title/132",[3648,1162.823]],["content/132",[3,3.174,7,5.786,18,3.656,41,4.888,89,4.791,111,7.061,113,7.341,124,3.128,125,3.748,152,7.061,187,8.033,212,3.469,216,3.061,217,6.029,223,4.698,233,3.417,252,5.449,256,4.361,265,5.397,276,6.59,308,2.717,374,3.128,377,4.99,382,4,453,5.869,482,10.164,483,3.934,623,5.851,625,6.357,635,4.888,670,8.033,720,4.209,726,3.632,827,5.581,871,5.096,1169,6.59,1189,4.284,1284,4.609,1556,5.208,1578,5.325,1584,8.481,1618,6.59,1712,7.93,1803,8.481,1848,7.66,1892,7.999,1976,8.481,2068,5.325,2094,8.033,2147,6.59,2728,8.481,2808,8.481,2835,7.341,3308,2.833,3348,9.793,3379,7.061,3405,9.793,3445,8.033,3566,8.481,3573,9.793,3701,7.061,3765,11.406,3789,8.481,3969,8.033,4339,8.481,4340,10.933,4341,7.341,4342,10.933,4343,10.933,4344,10.933,4345,10.933,4346,10.933,4347,9.793,4348,10.933,4349,10.933,4350,10.933,4351,10.933,4352,10.933,4353,5.338,4354,10.933,4355,10.933,4356,10.933,4357,10.933,4358,10.933,4359,10.933,4360,10.933]],["keywords/132",[]],["title/133",[266,413.24,744,404.835,4353,278.756]],["content/133",[8,6.999,66,5.703,74,5.407,86,2.015,116,3.004,216,2.964,250,6.999,266,7.761,285,9.07,319,2.016,447,5.224,676,10.318,1021,8.464,1315,6.154,1782,6.84,2352,9.839,3308,4.406,3344,6.546,3502,9.07,3899,12.579,4162,11.614,4353,4.323,4361,14.044,4362,14.044,4363,14.044,4364,14.044,4365,12.579,4366,14.044,4367,14.044,4368,14.044,4369,14.044,4370,9.839,4371,10.318]],["keywords/133",[]],["title/134",[289,354.397,4339,827.555]],["content/134",[34,4.699,54,6.633,91,5.761,106,8.994,107,9.349,110,7.285,118,7.285,127,6.491,145,3.337,167,5.534,319,1.999,429,12.473,459,6.491,624,2.979,664,8.393,1119,7.108,1182,9.756,1315,6.102,1534,7.678,1558,11.359,2246,8.677,2283,5.87,2318,7.897,2346,9.756,3223,10.802,3665,9.756,3670,12.473,3694,11.516,4339,13.124,4372,13.925,4373,13.925,4374,13.925,4375,13.925,4376,13.925]],["keywords/134",[]],["title/135",[1709,519.621,4377,1066.856]],["content/135",[20,4.107,25,8.02,53,5.239,66,5.021,73,2.989,84,5.115,86,1.862,89,5.418,98,3.031,139,11.074,142,4.307,147,6.817,154,4.523,167,5.139,185,3.695,216,2.609,230,8.662,244,8.301,245,2.406,275,4.377,308,3.073,312,4.044,374,3.537,382,5.748,416,5.763,492,7.985,508,5.643,543,4.238,623,5.302,624,3.361,630,4.6,877,3.75,1135,7.569,1169,7.452,1177,7.012,1334,7.452,1350,9.037,1372,7.222,1410,11.545,1438,8.662,1477,6.311,2283,5.212,2557,10.225,3291,10.55,3765,8.662,4353,5.317,4378,12.364,4379,11.074,4380,12.364,4381,12.364,4382,12.364,4383,10.225]],["keywords/135",[]],["title/136",[700,467.512,3969,783.844]],["content/136",[6,7.891,18,2.811,27,5.091,45,4.987,73,2.697,75,7.489,84,4.615,86,1.948,116,2.386,147,6.151,153,3.705,159,6.326,167,4.808,178,9.991,179,4.081,212,3.539,245,2.86,250,5.56,300,4.888,319,2.608,413,7.815,417,4.081,512,7.891,543,3.824,596,5.659,608,3.949,623,4.96,633,8.196,638,9.91,834,10.619,920,12.081,928,11.52,947,6.326,1020,6.151,1128,9.991,1350,5.836,1593,4.702,1685,6.326,1803,8.653,2283,4.702,2330,8.196,2616,7.204,3163,9.225,3327,3.885,3724,11.403,3731,5.56,3740,7.815,3969,10.801,4353,5.381,4379,9.991,4384,11.155,4385,11.155,4386,11.155,4387,11.155,4388,11.155,4389,11.155,4390,11.155,4391,11.155,4392,11.155,4393,11.155,4394,11.155,4395,11.155,4396,11.155,4397,11.155,4398,7.489,4399,11.155,4400,11.155,4401,9.991,4402,11.155,4403,11.155,4404,11.155,4405,11.155]],["keywords/136",[]],["title/137",[1311,715.826]],["content/137",[7,5.824,13,6.528,23,3.343,86,1.73,137,6.955,149,8.529,152,9.43,195,9.099,219,4.85,252,7.277,404,5.721,454,6.04,508,6.664,623,4.927,798,4.632,977,7.838,1185,4.927,1583,7.277,1782,7.112,2094,10.728,2283,6.155,4353,4.495,4406,14.602,4407,14.602,4408,14.602,4409,14.602,4410,14.602]],["keywords/137",[]],["title/138",[4353,278.756,4411,607.94,4412,811.045]],["content/138",[]],["keywords/138",[]],["title/139",[4353,399.662]],["content/139",[7,5.969,20,3.808,55,7.697,62,7.404,72,7.404,86,1.358,89,5.024,116,3.564,118,5.998,134,4.742,148,8.423,149,6.696,208,3.477,217,6.321,239,2.734,244,10.048,245,3.242,261,7.144,275,4.058,305,5.998,328,5.125,344,5.232,374,3.28,508,5.232,624,3.564,725,4.607,726,3.808,885,8.893,985,6.501,1016,5.343,1049,9.326,1135,5.024,1216,7.404,1321,8.423,1402,5.568,1556,7.129,1558,7.697,1571,5.851,1697,6.696,1981,6.909,2030,8.032,2255,9.481,2283,4.832,2619,10.268,2666,9.481,2836,8.423,2957,8.893,3308,3.878,3363,7.404,3699,8.423,3791,9.666,3962,10.268,4353,5.786,4413,11.464,4414,11.464,4415,11.464,4416,6.909,4417,11.464,4418,11.464,4419,11.464,4420,11.464,4421,11.464,4422,11.464,4423,11.464,4424,11.464,4425,11.464,4426,11.464,4427,9.481,4428,11.464,4429,11.464]],["keywords/139",[]],["title/140",[185,318.859,358,261.53]],["content/140",[86,1.723,131,4.683,319,2.665,623,4.905,725,4.475,726,4.829,1198,7.804,1525,8.492,1704,8.762,1784,10.185,2138,7.804,2544,8.244,3308,3.767,3327,5.064,3699,10.681,3753,12.022,3766,9.76,3831,9.76,4263,12.022,4353,4.475,4430,12.757,4431,12.022,4432,12.164,4433,14.537]],["keywords/140",[]],["title/141",[185,318.859,608,377.653]],["content/141",[23,3.201,53,4.242,98,3.428,124,4.001,131,4.504,239,3.335,263,11.565,265,5.202,319,2.621,374,4.001,377,6.382,473,9.798,700,6.128,764,5.895,1440,7.711,2138,7.507,2292,6.811,3310,9.032,3327,4.871,3483,9.105,3797,11.388,4069,11.565,4263,11.565,4353,5.222,4430,10.275,4432,9.798,4434,13.984,4435,13.984,4436,13.984,4437,8.261,4438,13.984]],["keywords/141",[]],["title/142",[185,318.859,418,410.72]],["content/142",[116,3.165,209,9.557,269,9.935,319,2.519,374,4.234,404,5.797,624,3.165,675,5.697,1049,9.221,1224,8.918,2138,7.943,2340,8.159,2390,9.935,2836,10.872,2957,11.478,3327,5.154,3766,9.935,3831,9.935,3902,10.872,4194,11.478,4353,4.555,4439,14.797,4440,13.254]],["keywords/142",[]],["title/143",[145,178.591,374,259.07,980,584.8]],["content/143",[72,8.426,81,7.003,85,7.863,98,3.198,115,6.214,116,3.964,136,8.13,148,9.586,212,4.139,246,7.863,253,9.586,265,4.853,374,3.733,524,4.544,574,6.354,637,7.621,725,5.45,775,5.5,798,5.156,985,7.399,1016,6.081,1135,5.717,1556,6.214,1702,10.12,2283,5.5,2292,6.354,2358,9.141,2363,6.826,2616,8.426,2618,10.12,3350,9.141,3507,12.404,3699,9.586,4137,7.399,4353,5.45,4411,12.442,4412,11.686,4441,10.12,4442,13.047,4443,10.79,4444,10.79]],["keywords/143",[]],["title/144",[86,107.292,3346,665.279,4445,905.483]],["content/144",[53,4.086,84,5.573,86,1.964,319,2.919,354,9.438,2023,7.869,2826,8.701,3327,5.775,3329,9.045,3344,6.279,3507,12.583,3766,9.045,3871,11.141,4137,10.185,4353,4.147,4370,9.438,4411,11.131,4430,9.898,4440,12.067,4446,13.472,4447,13.472,4448,13.472,4449,11.141,4450,12.067,4451,13.472,4452,13.472,4453,13.472,4454,11.141,4455,16.579]],["keywords/144",[]],["title/145",[86,107.292,3346,665.279,4456,702.378]],["content/145",[23,3.072,34,4.527,84,5.55,86,1.96,131,4.322,135,4.599,239,3.2,245,2.611,319,2.899,354,9.4,624,2.87,630,4.991,977,7.202,985,9.379,1376,5.55,1966,8.361,2138,7.202,2657,9.4,3327,4.673,3344,6.254,4137,9.379,4353,4.13,4370,9.4,4411,11.103,4430,9.858,4432,9.4,4449,11.096,4454,11.096,4457,13.417,4458,13.417,4459,13.417,4460,12.018,4461,13.417,4462,12.018,4463,13.417]],["keywords/145",[]],["title/146",[53,274.647,86,107.292,543,310.397]],["content/146",[84,5.484,86,2.113,98,3.25,223,5.696,265,4.931,312,4.336,319,2.869,354,9.287,454,5.484,555,9.739,1376,5.484,2292,6.456,2499,7.743,2617,10.963,2657,9.287,2825,7.517,3327,4.617,3344,6.178,3483,8.811,3507,9.287,3738,10.963,4137,10.112,4353,5.489,4370,9.287,4411,11.021,4430,9.739,4432,9.287,4449,10.963,4454,10.963,4464,13.256,4465,13.256,4466,13.256,4467,13.256,4468,13.256,4469,13.256]],["keywords/146",[]],["title/147",[1306,909.555]],["content/147",[53,4.882,84,5.313,86,1.907,98,3.149,113,8.623,116,2.747,179,4.699,208,3.896,281,9.437,289,4.267,319,2.877,417,4.699,543,4.403,624,2.747,1135,5.628,1350,8.421,1376,5.313,1395,6.72,1402,4.778,1445,8.999,3327,5.606,3346,9.437,3402,7.502,3415,8.999,3507,12.316,3760,9.437,4137,7.284,4353,3.954,4411,8.623,4450,11.504,4462,11.504,4470,10.622,4471,12.844,4472,12.844,4473,12.844,4474,16.095,4475,12.844,4476,12.844,4477,12.844,4478,12.844,4479,12.844,4480,12.844,4481,12.844]],["keywords/147",[]],["title/148",[1311,715.826]],["content/148",[7,6.419,13,5.742,34,4.334,86,1.522,98,3.149,99,11.504,116,3.443,159,9.128,229,6.556,233,4.014,239,3.839,275,4.547,485,8.003,499,4.334,508,5.862,574,6.256,596,4.945,624,3.443,629,7.741,675,6.196,726,4.267,775,6.785,797,7.839,874,5.862,1181,8.003,1333,5.123,1432,5.313,1534,7.082,1571,6.556,2253,10.622,2292,6.256,2650,8.999,2836,9.437,3308,4.17,3354,10.622,3729,10.622,3765,8.999,3952,11.504,4083,11.504,4353,5.412,4411,10.806,4482,12.844,4483,12.844,4484,12.844,4485,10.622,4486,11.504]],["keywords/148",[]],["title/149",[239,187.584,605,337.97,1284,331.546,2948,577.87]],["content/149",[]],["keywords/149",[]],["title/150",[246,545.735,1715,564.238,2250,634.395]],["content/150",[16,5.288,53,3.441,62,7.328,79,4.445,81,6.091,98,2.781,124,3.246,180,7.328,191,5.404,195,7.07,201,7.07,216,2.394,219,3.769,233,3.546,256,4.525,266,7.567,299,6.627,312,3.711,374,3.246,543,3.889,624,2.427,744,5.073,745,7.07,766,4.368,826,8.075,827,5.791,846,8.336,1122,7.949,1163,7.07,1183,10.415,1185,3.828,1316,7.618,1318,9.383,1322,7.409,1334,6.838,1338,7.328,1349,6.256,1375,8.801,1380,6.627,1566,7.328,1571,5.791,1676,7.328,1706,5.178,1782,5.526,1846,6.434,1859,7.949,1890,7.328,2297,9.383,2318,6.434,2336,7.328,2948,8.336,2957,8.801,3361,10.163,3451,9.383,3480,10.163,3563,7.949,3649,9.383,3816,9.383,3858,10.163,3868,8.801,3986,8.801,4056,13.315,4266,8.801,4487,14.866,4488,11.346,4489,11.346,4490,11.346,4491,11.346,4492,11.346,4493,11.346,4494,11.346,4495,11.346,4496,11.346,4497,11.346,4498,11.346,4499,11.346,4500,11.346,4501,11.346,4502,11.346,4503,11.346,4504,11.346,4505,11.346,4506,11.346,4507,11.346]],["keywords/150",[]],["title/151",[93,269.615,700,344.662,3308,203.791,4353,242.131]],["content/151",[]],["keywords/151",[]],["title/152",[1432,374.584,3797,607.94,4401,811.045]],["content/152",[18,2.244,23,2.038,64,4.241,74,3.427,84,5.213,86,1.493,89,5.522,93,4.319,98,2.182,108,3.683,116,1.904,166,10.421,167,2.912,206,4.241,208,2.7,212,2.824,266,4.063,286,5.049,305,4.658,319,2.954,342,8.828,409,4.534,417,3.257,431,3.901,456,3.101,483,3.203,543,3.052,676,6.541,680,4.15,700,3.901,743,5.75,744,5.634,833,3.826,985,5.049,989,5.75,1012,6.541,1198,4.779,1258,6.817,1376,3.683,1432,3.683,1697,5.2,1721,5.366,1782,4.336,2316,5.977,2577,7.974,3150,7.974,3308,3.265,3309,4.437,3327,5.539,3344,5.873,3359,10.677,3384,8.138,3396,4.437,3402,5.2,3418,5.977,3498,5.366,3528,7.363,3731,4.437,3773,8.828,3793,7.974,3797,5.977,3863,5.977,4172,6.906,4247,4.437,4262,6.906,4282,6.541,4292,5.75,4335,12.802,4353,4.896,4370,6.238,4437,6.137,4441,9.774,4443,7.363,4508,13.152,4509,8.903,4510,8.903,4511,7.974,4512,7.974,4513,8.903,4514,7.974,4515,11.286,4516,8.903,4517,8.903,4518,8.903,4519,8.903,4520,8.903,4521,8.903,4522,7.363,4523,7.974,4524,8.903,4525,14.244,4526,7.974,4527,7.974,4528,7.974,4529,7.974,4530,7.974,4531,11.286,4532,11.286,4533,7.974,4534,7.974,4535,7.974,4536,7.974,4537,7.974,4538,5.75]],["keywords/152",[]],["title/153",[217,383.313,700,304.637,2269,539.245,2409,622.673,2690,487.052]],["content/153",[41,4.687,53,3.18,84,4.337,93,5.464,94,5.351,98,3.908,116,3.017,126,8.132,131,3.377,142,3.651,145,2.782,162,5.225,191,4.993,206,4.993,215,4.886,216,2.212,219,3.482,229,5.351,263,8.67,289,3.482,319,2.89,382,3.835,524,3.651,623,3.537,700,6.985,828,8.132,862,8.67,980,6.77,1178,5.485,1198,7.571,1223,5.485,1333,4.181,1376,4.337,1395,5.485,1436,7.345,1571,5.351,1576,10.941,1966,6.532,2194,7.345,2283,5.946,3308,3.655,3327,3.651,3396,8.868,3467,8.67,3483,5.627,3545,12.527,3577,6.77,3731,5.225,4416,6.318,4432,7.345,4443,8.67,4508,13.183,4538,6.77,4539,10.483,4540,10.483,4541,10.483,4542,10.483,4543,10.483,4544,9.39,4545,7.702,4546,15.272,4547,12.634,4548,15.272,4549,8.132,4550,12.634,4551,12.634,4552,12.634,4553,8.132,4554,12.634,4555,9.39]],["keywords/153",[]],["title/154",[623,265.389,3308,203.791,3310,507.965,4353,242.131]],["content/154",[]],["keywords/154",[]],["title/155",[3360,572.688,4556,783.844]],["content/155",[18,2.232,20,2.942,27,4.041,66,3.596,74,3.409,86,2.061,93,3.036,98,2.171,116,1.894,131,4.697,135,3.036,147,4.883,185,2.647,190,4.626,206,4.218,216,1.869,239,2.994,319,2.764,328,3.959,333,3.409,344,4.041,374,2.534,404,3.469,447,3.294,524,3.084,623,4.92,624,2.685,630,4.67,680,7.394,720,3.409,721,3.94,741,5.337,764,3.733,798,2.809,833,5.394,979,5.173,985,8.997,1013,5.719,1020,4.883,1021,5.337,1218,6.204,1373,5.518,1511,4.754,1534,6.921,1558,5.945,1593,3.733,1600,5.719,1612,6.869,1903,5.173,2068,4.313,2092,6.506,2138,4.754,2340,4.883,2355,9.737,2356,5.945,2363,4.633,2656,5.945,2815,5.173,2962,6.204,3310,5.719,3327,5.526,3360,9.337,3400,6.506,3416,7.932,3419,6.506,3483,4.754,3701,5.719,3731,7.907,3797,5.945,3902,6.506,4069,7.323,4071,7.323,4247,7.907,4353,4.489,4437,8.472,4522,7.323,4556,12.78,4557,8.855,4558,8.855,4559,8.855,4560,8.855,4561,8.855,4562,8.855,4563,8.855,4564,8.855,4565,8.855,4566,6.869,4567,8.855,4568,7.323,4569,7.932,4570,8.855,4571,7.932,4572,8.855,4573,8.855,4574,8.855,4575,8.855,4576,8.855,4577,8.855,4578,8.855,4579,8.855,4580,8.855,4581,8.855,4582,8.855,4583,8.855,4584,8.855,4585,8.855,4586,8.855,4587,8.855,4588,8.855,4589,8.855]],["keywords/155",[]],["title/156",[4341,871.625]],["content/156",[8,4.332,21,3.53,23,1.99,25,4.437,27,3.967,84,5.125,86,1.71,93,2.98,125,2.98,130,4.052,131,4.649,147,4.793,153,2.888,166,10.245,188,3.967,206,4.14,212,2.758,216,1.834,239,2.073,245,1.691,266,3.967,305,4.548,316,3.809,319,2.899,409,3.128,417,3.18,430,3.53,456,4.315,499,2.933,543,4.948,574,4.234,623,5.309,624,1.859,630,3.234,667,7.189,680,4.052,741,5.239,744,5.539,833,5.323,914,5.417,985,4.929,1135,3.809,1534,4.793,1583,4.332,1969,4.929,2068,4.234,2499,5.077,2616,5.614,2706,5.614,2823,7.786,3308,3.21,3310,8.001,3327,5.48,3344,5.774,3359,9.691,3360,4.666,3384,8.001,3396,4.332,3402,5.077,3418,5.836,3483,4.666,3498,5.239,3546,6.743,3579,4.793,3585,6.743,3731,4.332,3753,10.245,3766,5.836,3773,8.679,3831,5.836,4247,4.332,4262,6.743,4335,12.702,4341,10.563,4353,4.843,4370,6.09,4416,5.239,4437,8.1,4511,7.786,4512,7.786,4514,7.786,4515,11.096,4522,7.189,4523,7.786,4525,14.092,4526,7.786,4527,7.786,4528,7.786,4529,7.786,4530,7.786,4531,11.096,4532,11.096,4533,7.786,4534,7.786,4535,7.786,4536,7.786,4537,7.786,4538,5.614,4556,6.386,4590,8.692,4591,8.692,4592,8.692,4593,8.692,4594,8.692,4595,8.692,4596,8.692,4597,7.786,4598,8.692,4599,8.692,4600,8.692,4601,7.786,4602,8.692,4603,8.692,4604,8.692]],["keywords/156",[]],["title/157",[2624,716.286,4437,519.621]],["content/157",[23,4.003,53,3.851,74,4.888,86,1.504,98,3.112,162,6.328,179,4.645,244,8.524,245,2.47,360,10.32,456,4.422,574,6.184,624,2.716,725,3.909,741,7.652,833,5.456,1198,9.386,1477,6.48,1571,8.156,2068,6.184,2338,8.2,2340,7,2365,10.728,2624,10.728,3308,3.29,3350,8.895,3360,6.815,3498,7.652,3701,10.32,4222,7.652,4353,5.649,4398,8.524,4437,8.516,4470,10.5,4556,9.328,4605,12.696,4606,11.372,4607,12.696,4608,12.696,4609,12.696,4610,12.696,4611,12.696,4612,12.696,4613,12.696,4614,12.696,4615,12.696,4616,12.696]],["keywords/157",[]],["title/158",[4353,328.435,4617,1066.856]],["content/158",[7,7.099,16,6.154,41,5.903,54,6.289,74,5.083,75,8.864,100,4.751,116,3.503,124,3.777,136,8.227,149,7.712,216,3.455,252,6.58,275,5.796,308,3.281,430,5.362,508,6.025,624,3.503,775,5.565,798,4.188,871,6.154,874,6.025,1334,7.957,1395,6.907,1445,9.25,1609,8.864,2385,11.826,2624,8.864,2728,12.701,3308,3.421,3444,11.826,3654,10.241,4353,4.065,4416,7.957,4437,6.431,4569,11.826,4618,10.241,4619,13.203,4620,13.203,4621,13.203,4622,13.203,4623,13.203,4624,13.203,4625,13.203]],["keywords/158",[]],["title/159",[1172,564.238,3308,234.617,4353,278.756]],["content/159",[8,5.258,13,4.717,19,5.983,23,3.243,40,6.814,86,1.678,93,4.856,115,6.747,130,7.454,131,4.563,154,3.859,173,7.083,180,6.814,190,3.347,211,6.574,275,3.735,377,4.815,416,4.917,431,4.623,449,3.398,499,3.56,623,4.78,624,2.257,630,3.925,726,3.505,741,6.358,798,3.347,833,4.533,947,5.983,975,7.411,1198,9.176,1224,6.358,1333,4.208,1395,5.52,1578,5.138,1593,4.447,1721,6.358,1911,8.274,2068,5.138,2400,8.537,2544,8.033,2643,6.162,2690,7.391,2961,8.183,3308,2.734,3360,9.176,3415,7.391,3701,6.814,3772,5.983,3797,7.083,3886,8.183,3902,7.751,4247,5.258,4353,5.946,4371,7.751,4416,8.537,4431,8.725,4437,8.685,4441,8.183,4556,12.56,4568,8.725,4606,9.45,4626,9.45,4627,10.55,4628,10.55,4629,9.45,4630,9.45,4631,10.55,4632,10.55,4633,10.55,4634,10.55,4635,8.725,4636,10.55,4637,10.55,4638,10.55,4639,10.55,4640,10.55,4641,10.55,4642,10.55,4643,10.55]],["keywords/159",[]],["title/160",[3308,234.617,4353,278.756,4644,905.483]],["content/160",[2,6.196,3,2.456,6,2.825,7,4.231,13,3.782,16,3.943,17,3.399,20,1.748,22,1.29,23,1.937,41,3.782,45,2.353,48,2.902,53,1.596,64,2.507,66,4.308,70,4.352,73,1.272,77,3.172,79,3.314,84,2.177,86,2.091,89,2.306,91,2.177,93,4.874,94,2.686,100,1.894,115,2.507,116,2.599,118,4.426,130,3.943,131,1.695,135,1.804,137,5.052,141,2.604,145,1.038,148,3.867,149,4.941,153,1.748,164,2.306,167,1.721,170,4.12,184,2.453,190,2.684,208,2.566,212,1.67,216,1.111,217,2.902,219,1.748,221,3.867,223,2.261,230,5.927,243,4.082,245,1.646,246,3.172,252,4.216,260,5.464,265,1.958,266,5.545,275,5.29,289,4.723,307,2.684,308,2.103,312,1.721,314,4.082,336,3.5,344,3.861,350,2.507,359,3.074,374,2.42,381,2.623,382,3.88,416,2.453,447,4.52,456,1.833,458,3.279,459,2.453,482,3.687,511,3.279,524,1.833,526,2.099,543,1.804,623,5.955,624,2.269,625,3.707,626,3.074,627,3.074,635,2.353,665,3.279,700,2.306,726,2.81,775,2.218,823,4.714,826,2.563,833,3.635,837,7.577,871,3.943,873,3.867,874,2.402,881,4.082,976,4.714,1122,3.687,1178,2.753,1189,2.062,1224,3.172,1287,3.867,1306,3.687,1315,4.648,1318,4.352,1322,2.623,1372,3.074,1412,3.687,1432,2.177,1436,3.687,1442,4.082,1445,3.687,1466,2.177,1477,2.686,1525,4.941,1534,5.849,1556,2.507,1563,4.082,1574,4.082,1578,4.12,1592,6.015,1679,3.279,1685,4.797,1686,3.074,1697,6.196,1704,3.172,1707,4.352,1709,4.12,1712,2.563,1715,3.279,1782,2.563,1809,4.082,1810,3.687,1887,3.172,1892,2.902,1896,2.402,1903,3.074,1911,3.074,1967,4.352,1981,3.172,1985,6.215,1988,3.687,2230,3.687,2283,5.993,2292,4.12,2330,3.867,2336,3.399,2338,3.399,2340,6.699,2350,2.825,2354,3.533,2356,3.533,2397,4.082,2506,6.215,2544,2.984,2548,4.082,2657,3.687,2697,4.082,3168,3.867,3308,4.679,3309,4.216,3310,3.399,3339,5.464,3356,4.082,3359,3.533,3364,4.714,3370,4.352,3419,3.867,3442,6.562,3447,3.399,3483,2.825,3502,3.399,3570,4.714,3683,8.927,3701,5.464,3718,4.714,3765,5.927,3771,4.352,3816,4.352,3823,3.687,3863,5.68,4050,4.714,4098,9.501,4187,4.714,4194,4.082,4247,2.623,4255,4.352,4269,4.714,4341,3.533,4353,2.604,4398,3.533,4427,6.996,4437,2.563,4444,4.352,4456,4.082,4486,4.714,4571,9.501,4626,7.577,4635,4.352,4645,5.263,4646,5.263,4647,5.263,4648,5.263,4649,5.263,4650,5.263,4651,4.352,4652,5.263,4653,5.263,4654,4.714,4655,5.263,4656,5.263,4657,5.263,4658,5.263,4659,5.263,4660,4.714,4661,5.263,4662,5.263,4663,4.714,4664,4.352,4665,5.263,4666,5.263,4667,5.263,4668,4.714,4669,5.263,4670,5.263,4671,5.263,4672,4.714,4673,5.263,4674,5.263,4675,5.263,4676,5.263,4677,4.714,4678,5.263,4679,5.263,4680,5.263,4681,8.772,4682,5.263,4683,5.263,4684,5.263,4685,5.263,4686,4.714,4687,5.263,4688,5.263,4689,5.263,4690,8.459,4691,5.263,4692,5.263,4693,5.263,4694,5.263,4695,5.263,4696,5.263,4697,5.263,4698,5.263,4699,5.263,4700,5.263,4701,5.263,4702,5.263,4703,5.263,4704,5.263,4705,5.263,4706,5.263,4707,5.263,4708,5.263,4709,5.263,4710,5.263,4711,5.263,4712,5.263,4713,5.263,4714,5.263,4715,5.263,4716,5.263,4717,5.263,4718,5.263,4719,5.263,4720,5.263,4721,5.263,4722,4.714,4723,5.263]],["keywords/160",[]],["title/161",[216,225.142,3840,882.296]],["content/161",[3,2.523,7,3.467,10,4.332,16,4.052,18,2.191,41,3.886,45,6.453,55,5.836,73,2.102,86,1.03,98,3.538,113,9.691,117,5.836,134,3.596,141,2.676,142,3.028,158,7.719,170,4.234,190,3.93,208,2.637,209,5.614,212,2.758,215,4.052,216,2.614,217,6.831,219,2.888,230,6.09,231,11.096,233,4.916,239,2.955,245,2.809,246,5.239,247,7.786,249,5.614,252,4.332,256,4.941,275,3.077,277,4.929,279,6.09,285,8.001,297,6.386,299,7.236,336,3.596,386,4.234,456,3.028,508,3.967,543,2.98,605,5.323,670,6.386,675,3.346,703,6.386,744,3.886,745,5.417,794,4.929,798,2.758,799,4.929,827,4.437,846,6.386,874,3.967,877,3.757,989,5.614,1018,5.239,1119,4.437,1135,3.809,1185,2.933,1189,3.406,1315,3.809,1319,5.077,1320,4.437,1333,3.467,1350,6.481,1402,3.234,1477,4.437,1522,4.929,1572,7.786,1685,4.929,1706,3.967,1848,8.679,1890,5.614,2168,6.743,2182,7.189,2218,7.786,2287,7.189,2338,5.614,2340,4.793,2448,6.743,2606,7.189,2616,5.614,2650,6.09,2739,7.189,2819,7.786,3688,7.786,3789,6.743,3823,6.09,3840,13.011,3841,7.786,3845,14.896,3960,14.092,3986,6.743,4545,6.386,4553,6.743,4668,7.786,4724,8.692,4725,8.692,4726,8.692,4727,8.692,4728,8.692,4729,7.786,4730,8.692,4731,8.692,4732,8.692,4733,12.388,4734,8.692,4735,7.786,4736,14.434,4737,16.63,4738,8.692,4739,8.692,4740,8.692,4741,8.692,4742,8.692,4743,8.692,4744,7.786,4745,8.692,4746,12.388,4747,8.692,4748,8.692,4749,12.388,4750,8.692,4751,8.692,4752,8.692,4753,8.692,4754,12.388,4755,8.692,4756,8.692,4757,8.692,4758,8.692]],["keywords/161",[]],["title/162",[1896,413.24,2736,451.297,4759,811.045]],["content/162",[]],["keywords/162",[]],["title/163",[879,459.424,1896,358.946,4760,786.514,4761,704.484]],["content/163",[2,6.035,7,3.269,10,2.523,22,2.01,23,1.159,79,1.983,86,0.6,116,2.21,127,2.359,128,3.926,131,1.63,136,3.154,142,1.763,143,2.791,153,1.681,154,1.852,158,3.154,159,2.87,170,2.465,179,1.852,185,2.45,190,1.606,203,3.926,216,1.068,222,2.218,229,4.184,233,1.582,239,1.207,261,5.108,265,3.843,266,2.31,294,3.269,306,2.717,312,1.655,319,3.051,324,7.591,337,3.05,357,5.472,358,3.199,365,4.527,381,2.523,404,1.983,411,2.583,417,1.852,418,4.572,422,2.717,460,2.465,499,2.766,512,4.4,543,1.735,561,4.815,608,4.204,613,5.834,624,1.754,644,6.062,698,3.926,721,3.286,723,6.376,726,1.681,775,2.134,797,2.465,798,1.606,871,2.359,908,3.546,913,4.52,920,8.726,977,2.717,978,3.154,1088,3.719,1221,3.269,1260,7.238,1284,2.134,1402,1.883,1583,2.523,1686,2.956,1703,3.719,1709,3.993,1784,3.546,1849,4.533,1896,2.31,2051,3.926,2068,2.465,2137,5.294,2283,2.134,2292,2.465,2338,3.269,2504,3.719,2555,3.269,2736,5.92,2825,2.87,2940,3.269,2961,3.926,3327,1.763,3375,2.791,3400,3.719,3483,2.717,3577,3.269,3661,3.05,3731,2.523,3738,4.186,3751,3.398,3772,2.87,3773,3.546,3931,4.533,4146,4.186,4247,2.523,4282,3.719,4660,4.533,4759,4.533,4761,10.638,4762,5.061,4763,5.061,4764,5.061,4765,5.061,4766,5.061,4767,5.061,4768,5.061,4769,5.061,4770,5.061,4771,4.533,4772,7.342,4773,8.197,4774,7.342,4775,5.061,4776,5.061,4777,5.061,4778,10.331,4779,5.061,4780,5.061,4781,5.061,4782,5.061,4783,5.061,4784,5.061,4785,5.061,4786,5.061,4787,5.061,4788,5.061,4789,5.061,4790,5.061,4791,5.061,4792,13.967,4793,8.197,4794,5.061,4795,5.061,4796,4.186,4797,5.061,4798,4.533,4799,4.186,4800,5.061]],["keywords/163",[]],["title/164",[3662,572.688,3679,588.253]],["content/164",[3,2.763,6,7.088,18,2.399,21,6.157,23,2.179,45,4.255,64,4.533,73,2.301,79,3.729,84,3.937,86,2.109,95,5.736,98,2.333,100,4.751,113,6.39,116,2.036,124,3.778,130,4.436,141,2.93,154,3.482,159,5.398,179,3.482,184,4.436,185,2.845,188,4.344,212,3.019,215,4.436,216,2.009,219,3.162,245,1.852,259,8.525,275,3.369,328,4.255,350,4.533,376,5.736,431,4.171,623,3.212,624,2.036,638,7.958,761,5.931,775,4.012,809,6.993,833,4.09,877,2.887,975,4.98,1402,3.541,1466,5.462,1511,5.109,1535,6.147,1569,7.871,1578,4.636,1675,8.525,1709,7.976,1711,7.383,1715,5.931,1782,4.636,1806,8.528,1854,4.171,2230,6.668,2250,6.668,2359,6.993,2506,6.993,2544,5.398,2621,6.39,2656,6.39,2736,6.581,3206,7.871,3308,3.421,3355,7.383,3356,7.383,3375,10.419,3489,6.993,3662,9.799,3679,9.815,3722,7.871,3751,6.39,3752,11.473,3756,6.668,3831,6.39,4239,7.383,4353,5.041,4437,4.636,4798,8.525,4799,7.871,4801,9.518,4802,9.518,4803,9.518,4804,9.518,4805,9.518,4806,9.518,4807,9.518,4808,9.518,4809,9.518,4810,8.525,4811,13.204,4812,9.518,4813,9.518,4814,12.538,4815,9.518,4816,9.518,4817,9.518,4818,9.518]],["keywords/164",[]],["title/165",[4819,953.834]],["content/165",[18,2.426,21,3.91,22,2.36,27,4.394,66,3.91,79,3.772,81,8.189,86,1.577,91,3.983,95,5.803,98,2.36,100,3.465,124,3.808,125,3.301,131,3.101,134,3.983,136,6,142,3.354,149,5.624,153,3.199,154,4.869,158,6,164,4.219,216,2.032,222,5.833,262,6.746,265,3.582,316,4.219,319,2.363,375,7.074,381,4.799,411,4.915,524,3.354,725,2.964,775,6.43,797,4.69,879,5.624,888,7.963,913,5.309,947,7.548,975,5.038,990,6,1125,6.746,1178,5.038,1183,9.325,1215,7.469,1283,5.803,1287,7.074,1369,6.219,1402,3.582,1409,6.465,1566,6.219,1592,5.46,1678,8.624,1679,6,1685,5.46,1709,4.69,1715,8.294,1782,4.69,1806,6.219,1809,7.469,1846,5.46,1854,4.219,1896,4.394,1969,7.548,2656,8.936,2736,6.634,2940,6.219,3206,11.008,3308,3.449,3375,10.446,3483,7.145,3653,11.008,3662,8.189,3679,8.411,3751,6.465,3831,10.242,3894,7.963,3907,8.624,3979,8.624,3986,7.469,4192,8.624,4292,6.219,4353,2.964,4819,13.454,4820,9.629,4821,9.629,4822,9.629,4823,9.629,4824,9.629,4825,9.629,4826,9.629,4827,9.629,4828,15.255,4829,9.629,4830,9.629,4831,9.629,4832,9.629,4833,9.629,4834,9.629,4835,9.629]],["keywords/165",[]],["title/166",[1686,528.917,1896,413.24,3489,665.279]],["content/166",[20,3.821,23,2.634,40,7.43,86,1.777,124,3.291,125,3.943,131,4.832,162,5.734,193,8.452,198,6.343,208,3.489,216,2.428,222,5.041,223,4.943,249,7.43,250,5.734,256,4.588,266,5.25,275,4.072,526,4.588,624,2.461,721,3.529,761,7.168,775,4.849,797,5.603,798,3.65,871,5.362,1221,7.43,1319,6.72,1350,6.019,1376,4.759,1402,4.28,1526,7.724,1592,6.524,1709,5.603,1711,8.923,1715,10.401,1887,6.933,1896,5.25,2026,7.145,2338,7.43,2390,7.724,2736,8.319,3308,2.981,3375,8.271,3396,5.734,3431,8.06,3482,8.923,3653,9.514,3661,6.933,3662,6.175,3679,6.343,4137,6.524,4239,8.923,4353,3.541,4545,8.452,4771,13.436,4819,8.452,4836,13.721,4837,11.504,4838,8.06,4839,11.504,4840,11.504,4841,8.923,4842,11.504,4843,14.951,4844,11.504,4845,11.504,4846,11.504,4847,11.504,4848,11.504,4849,11.504,4850,10.304]],["keywords/166",[]],["title/167",[483,467.128]],["content/167",[22,3.487,154,5.204,216,3.002,245,2.768,265,5.292,289,5.693,376,8.573,430,5.777,480,10.451,483,6.166,485,8.864,629,8.573,721,4.327,739,8.573,766,5.476,871,6.63,879,8.309,1185,4.8,1264,8.573,2736,7.09,2834,11.764,3024,11.764,3577,9.187,4112,12.741,4796,11.764,4851,14.225,4852,14.225,4853,14.225,4854,14.225]],["keywords/167",[]],["title/168",[3751,871.625]],["content/168",[7,5.373,314,10.45,871,6.279,1185,4.546,1466,5.573,2547,12.067,2736,6.714,3375,9.142,3661,8.119,3662,7.232,3679,9.142,3751,9.045,3752,9.438,4266,10.45,4353,4.147,4618,10.45,4796,11.141,4814,11.141,4819,9.898,4836,10.45,4855,12.067,4856,11.141,4857,12.067,4858,14.85,4859,12.067,4860,12.067,4861,12.067,4862,13.472,4863,13.472,4864,13.472,4865,13.472,4866,13.472,4867,13.472,4868,13.472,4869,13.472,4870,13.472,4871,13.472,4872,13.472,4873,13.472,4874,13.472,4875,13.472,4876,13.472,4877,13.472]],["keywords/168",[]],["title/169",[3756,909.555]],["content/169",[5,11.64,116,2.78,142,4.526,153,4.317,154,4.754,162,6.477,314,10.08,455,9.105,775,6.835,871,6.057,1185,4.385,1466,5.376,1709,6.329,1807,9.105,2736,8.081,3375,8.94,3661,7.832,3662,6.976,3679,8.94,3751,8.725,4545,9.548,4618,10.08,4814,10.747,4819,9.548,4836,10.08,4855,11.64,4856,10.747,4857,11.64,4858,14.523,4859,11.64,4860,11.64,4861,11.64,4878,16.214,4879,12.995,4880,12.995,4881,12.995,4882,12.995,4883,12.995,4884,12.995,4885,12.995,4886,12.995,4887,12.995,4888,12.995,4889,12.995,4890,12.995,4891,12.995,4892,12.995,4893,12.995,4894,12.995]],["keywords/169",[]],["title/170",[1311,715.826]],["content/170",[11,9.477,13,6.048,23,3.805,98,3.316,131,4.357,137,6.443,198,7.458,208,4.103,216,2.855,223,5.813,229,6.904,239,3.226,245,2.632,265,5.032,308,3.362,328,6.048,526,5.395,744,6.048,775,7.006,1189,5.3,1283,8.153,1308,8.153,1430,13.746,1432,6.876,1556,6.443,1592,7.671,1706,6.173,2028,9.938,2294,12.116,2303,11.187,2736,6.742,3375,7.458,3483,7.261,3577,8.736,4629,12.116,4836,12.893,4850,12.116,4856,11.187,4895,13.527,4896,13.527]],["keywords/170",[]],["title/171",[265,292.594,266,358.946,775,331.546,797,383.078]],["content/171",[]],["keywords/171",[]],["title/172",[66,433.273,3309,531.726]],["content/172",[16,3.43,22,1.804,45,3.29,49,4.752,66,2.988,81,3.95,86,1.723,89,3.224,93,5.331,115,3.505,116,2.347,124,2.105,131,2.37,137,6.248,142,3.821,145,1.451,153,2.444,154,4.013,158,4.585,159,4.173,185,3.279,188,3.358,190,2.334,212,2.334,216,2.315,223,3.162,239,1.755,242,4.94,243,5.708,245,2.829,252,5.468,261,4.585,266,3.358,275,2.605,289,3.644,299,4.298,309,4.435,324,5.406,357,2.883,359,4.298,417,2.692,431,3.224,449,2.37,508,3.358,524,2.563,528,6.591,541,6.085,554,4.435,605,3.162,623,5.503,624,1.574,635,3.29,644,3.756,675,2.833,697,5.889,700,4.807,721,2.581,725,2.265,764,4.625,775,5.529,798,3.48,799,4.173,833,4.714,930,6.591,989,4.752,1135,4.807,1178,3.85,1185,4.426,1201,6.591,1204,6.085,1350,3.85,1395,3.85,1401,4.94,1403,5.406,1435,6.591,1593,3.102,1595,4.94,1600,7.085,1630,4.94,1683,5.708,1702,8.51,1705,4.298,1712,5.343,1715,4.585,1903,10.143,1952,5.708,2283,5.529,2346,5.155,2358,5.155,2400,4.435,2455,5.708,2556,6.085,2606,6.085,2618,5.708,2624,4.94,2650,5.155,2716,6.085,2810,6.085,2824,5.708,2825,4.173,2835,4.94,2841,5.708,3291,4.94,3308,3.399,3309,8.128,3339,4.752,3445,8.06,3447,10.532,3481,6.085,3517,6.591,3577,4.752,3791,4.752,3863,7.366,3868,5.708,4041,6.591,4137,4.173,4201,6.085,4335,8.06,4341,10.949,4353,5.02,4365,6.591,4383,9.073,4398,4.94,4416,4.435,4437,5.343,4485,9.073,4508,6.085,4686,6.591,4838,5.155,4897,7.358,4898,7.358,4899,7.358,4900,5.406,4901,6.085,4902,7.358,4903,7.358,4904,8.51,4905,10.971,4906,7.358,4907,7.358,4908,7.358,4909,7.358,4910,7.358,4911,7.358,4912,7.358,4913,7.358,4914,6.591,4915,7.358,4916,7.358,4917,6.591,4918,7.358,4919,7.358,4920,7.358,4921,7.358,4922,7.358,4923,7.358,4924,7.358,4925,7.358,4926,7.358,4927,7.358,4928,7.358,4929,6.591,4930,13.023,4931,7.358,4932,7.358,4933,7.358,4934,7.358,4935,7.358,4936,7.358,4937,7.358]],["keywords/172",[]],["title/173",[4938,1007.024]],["content/173",[7,3.253,16,3.802,18,2.055,50,6.745,52,5.993,53,2.474,85,4.916,91,3.374,100,4.258,104,5.882,108,3.374,116,2.979,118,4.267,127,3.802,128,6.327,134,3.374,137,3.885,140,4.065,167,2.668,185,2.438,188,3.722,191,3.885,208,4.224,212,2.588,216,2.497,222,7.109,266,7.404,269,5.476,289,5.075,377,3.722,413,5.715,430,3.313,453,4.378,524,2.841,526,3.253,543,4.774,623,3.993,624,2.531,680,3.802,726,2.71,744,3.647,874,3.722,910,10.258,1135,6.103,1185,2.752,1338,5.268,1376,3.374,1395,4.267,1399,8.394,1403,5.993,1409,5.476,1466,3.374,1477,4.163,1563,6.327,1583,4.065,1595,5.476,1623,5.993,1691,7.306,1709,3.973,1716,7.306,1782,3.973,1854,7.109,1985,5.993,2169,7.306,2180,6.745,2194,5.715,2283,6.44,2341,5.715,2350,4.378,2650,8.291,2651,6.745,2654,5.268,2824,6.327,2825,4.626,3223,6.327,3301,6.745,3339,8.995,3430,7.306,3460,8.291,3502,5.268,3566,6.327,3572,5.993,3665,5.715,3677,6.327,3719,6.745,3791,5.268,3863,5.476,3871,6.745,4137,6.711,4432,5.715,4544,7.306,4553,6.327,4566,9.18,4651,6.745,4681,6.745,4772,7.306,4838,5.715,4914,7.306,4938,11.851,4939,6.745,4940,16.92,4941,15.278,4942,17.456,4943,12.005,4944,8.157,4945,8.157,4946,8.157,4947,13.927,4948,8.157,4949,8.157,4950,8.157,4951,8.157,4952,8.157,4953,8.157,4954,8.157,4955,8.157,4956,8.157,4957,8.157,4958,8.157,4959,11.834,4960,8.157,4961,8.157,4962,8.157,4963,8.157,4964,8.157,4965,8.157,4966,8.157,4967,8.157,4968,11.834,4969,8.157,4970,10.6,4971,8.157,4972,7.306]],["keywords/173",[]],["title/174",[4939,1073.638]],["content/174",[1,7.075,6,5.421,13,6.149,20,4.569,34,3.408,86,1.197,93,3.462,98,3.371,100,3.634,116,2.942,118,7.195,124,2.889,128,7.834,145,1.992,149,5.899,184,4.707,187,10.105,215,6.41,221,12.907,239,4.005,266,6.277,267,11.374,275,4.868,289,3.355,308,2.51,317,6.087,377,4.609,453,5.421,543,3.462,623,5.666,665,6.293,726,3.355,775,4.257,799,5.727,1016,4.707,1126,7.834,1314,7.834,1333,4.028,1380,5.899,1447,6.78,1477,5.155,1558,6.78,1706,4.609,1710,9.234,1986,9.046,2023,5.899,2092,7.42,2338,6.522,2350,5.421,2548,7.834,2568,9.046,2624,6.78,2643,5.899,2810,11.374,3070,6.293,3291,6.78,3490,7.834,3498,6.087,3579,5.568,3791,6.522,4146,8.352,4198,9.046,4216,9.046,4663,9.046,4664,11.374,4810,9.046,4838,10.957,4938,12.131,4939,8.352,4943,10.5,4973,10.099,4974,13.753,4975,10.099,4976,10.099,4977,10.099,4978,10.099,4979,10.099,4980,10.099,4981,10.099,4982,10.099,4983,13.753,4984,10.099,4985,10.099,4986,10.099,4987,12.319,4988,10.099,4989,9.046,4990,10.099,4991,10.099,4992,8.352,4993,10.099,4994,10.099,4995,9.046,4996,10.099,4997,10.099,4998,10.099]],["keywords/174",[]],["title/175",[4992,1073.638]],["content/175",[23,2.941,33,7.566,50,10.623,79,3.585,86,1.522,108,3.785,109,6.118,115,4.358,160,4.091,170,4.456,179,4.699,188,4.175,216,3.133,222,5.629,245,1.78,266,4.175,275,5.255,276,5.514,277,5.189,305,4.787,308,2.274,328,4.091,336,3.785,386,7.23,390,6.722,411,4.67,430,3.716,453,4.911,480,6.722,485,5.701,561,4.264,605,5.52,624,1.957,675,3.522,676,6.722,680,4.264,721,4.247,726,3.039,794,5.189,826,4.456,877,2.775,910,10.807,1169,7.742,1185,3.087,1190,6.722,1224,5.514,1316,6.143,1369,5.909,1399,5.514,1526,6.143,1578,4.456,1697,5.344,1748,7.566,2030,8.999,2094,6.722,2147,5.514,2215,8.195,2314,6.41,2340,5.045,2384,6.722,2544,5.189,2654,8.296,2728,7.097,2832,7.566,2919,7.566,3184,7.097,3299,7.566,3314,8.195,3368,11.514,3438,7.566,3439,5.909,3475,7.566,3483,6.895,3592,6.143,3707,10.623,3791,5.909,4127,8.195,4239,7.097,4398,6.143,4416,5.514,4681,7.566,4774,14.417,4838,6.41,4970,11.505,4992,12.276,4999,9.149,5000,9.149,5001,9.149,5002,9.149,5003,9.149,5004,9.149,5005,9.149,5006,9.149,5007,9.149,5008,9.149,5009,9.149,5010,9.149,5011,9.149,5012,9.149,5013,9.149,5014,9.149,5015,9.149,5016,9.149,5017,9.149,5018,9.149,5019,9.149,5020,9.149,5021,9.149,5022,9.149,5023,9.149,5024,9.149,5025,9.149,5026,9.149,5027,9.149,5028,9.149,5029,14.844,5030,9.149,5031,9.149,5032,9.149,5033,9.149,5034,9.149,5035,9.149,5036,9.149,5037,8.195,5038,9.149]],["keywords/175",[]],["title/176",[524,371.602,1970,827.555]],["content/176",[1,6.611,6,5.065,13,4.219,18,3.803,19,5.351,22,2.313,28,6.336,41,4.219,79,3.697,86,1.933,106,6.094,125,3.235,134,3.904,149,7.667,153,3.135,156,5.687,164,4.135,167,3.086,185,2.82,190,2.994,212,4.164,216,1.991,228,7.804,230,6.611,245,2.554,246,5.687,262,6.611,266,7.446,267,7.804,289,3.135,350,4.495,430,3.832,474,4.937,499,3.184,524,4.572,526,3.763,635,4.219,700,4.135,725,2.905,726,3.135,739,5.687,761,5.88,775,6.362,793,8.452,797,6.393,877,2.862,910,6.336,977,5.065,1021,5.687,1177,5.351,1216,6.094,1307,5.88,1315,5.752,1322,4.703,1333,3.763,1334,5.687,1337,7.804,1350,4.937,1395,4.937,1399,5.687,1477,4.816,1500,6.611,1511,5.065,1571,4.816,1600,8.477,1705,5.512,1707,7.804,1782,4.596,1821,4.398,1854,4.135,2030,6.611,2147,5.687,2283,3.978,2340,5.203,2360,5.512,2546,9.644,2643,7.667,2657,6.611,2835,6.336,3195,7.804,3309,4.703,3339,9.747,3431,6.611,3445,6.933,3481,7.804,3490,7.32,3567,7.804,3577,9.747,3654,7.32,3665,6.611,3676,10.855,3789,7.32,3847,8.452,4032,8.452,4137,5.351,4189,8.452,4255,7.804,4341,6.336,4456,7.32,4485,7.804,4618,10.181,4635,7.804,4651,7.804,4838,9.196,4943,6.336,4972,8.452,4987,8.452,4989,8.452,5039,9.436,5040,9.436,5041,9.436,5042,9.436,5043,9.436,5044,9.436,5045,9.436,5046,9.436,5047,9.436,5048,9.436,5049,9.436,5050,9.436,5051,9.436,5052,9.436,5053,9.436,5054,9.436,5055,9.436]],["keywords/176",[]],["title/177",[623,265.389,3308,203.791,4353,242.131,4371,577.87]],["content/177",[]],["keywords/177",[]],["title/178",[449,343.638,3772,605.017]],["content/178",[23,2.884,27,5.75,41,5.633,93,6.273,110,6.592,115,6.001,116,2.695,145,2.485,153,4.185,170,6.137,179,4.609,245,2.452,389,6.28,449,6.207,483,4.533,499,4.251,543,4.319,623,4.251,624,3.402,700,5.521,975,8.32,1179,9.257,1223,6.592,1319,7.36,1566,8.137,1592,7.145,1595,8.459,1709,6.137,1782,6.137,1806,8.137,1911,7.36,2283,6.703,2363,6.592,2815,7.36,2835,8.459,3291,8.459,3327,4.389,3579,6.947,3772,10.701,4630,11.285,4735,11.285,5037,11.285,5056,12.599,5057,12.599,5058,12.599,5059,11.285,5060,12.599,5061,12.599]],["keywords/178",[]],["title/179",[1709,632.31]],["content/179",[18,3.68,34,2.996,41,3.97,84,6.041,86,2.063,91,3.673,94,4.532,98,3.083,134,5.203,135,4.311,147,4.896,179,3.248,185,3.759,208,2.693,245,1.728,286,5.035,312,2.904,319,2.913,374,2.54,377,4.052,389,4.425,404,3.479,449,4.051,451,10.231,456,3.093,624,2.69,675,3.418,680,5.862,794,5.035,1021,5.351,1088,11.67,1090,11.67,1179,6.524,1313,7.343,1375,6.887,1402,4.679,1477,4.532,1511,8.526,1565,4.229,1566,5.734,1593,5.301,2092,6.524,2365,5.961,2664,9.755,2815,5.186,2826,5.734,2897,6.524,2905,6.221,2962,6.221,3279,7.343,3291,5.961,3308,4.344,3327,5.84,3350,6.221,3384,5.734,3415,6.221,3516,6.221,3528,7.343,3724,9.755,3740,8.811,3772,9.008,4416,5.351,4538,9.432,4566,12.321,5062,8.879,5063,8.879,5064,8.879,5065,8.879,5066,8.879,5067,8.879,5068,9.755,5069,12.576,5070,12.576,5071,8.879,5072,12.576,5073,12.576,5074,15.884,5075,12.576,5076,7.343,5077,7.343,5078,12.576,5079,7.953,5080,7.953,5081,8.879,5082,12.576,5083,7.953,5084,8.879,5085,8.879,5086,8.879,5087,8.879,5088,8.879,5089,8.879]],["keywords/179",[]],["title/180",[389,647.04]],["content/180",[20,4.201,23,2.895,27,5.772,41,5.655,84,5.232,86,1.889,93,5.983,109,6.024,110,6.617,206,6.024,245,2.461,319,2.712,374,3.619,417,4.627,449,5.903,543,4.336,623,5.379,1221,8.168,1315,5.542,1592,7.172,1782,6.16,1896,5.772,2283,6.719,2350,6.789,2544,7.172,2815,7.388,3327,4.405,3579,6.974,3731,6.304,3772,9.899,4036,11.328,4137,7.172,4292,10.295,4566,12.365,4568,10.46,4943,8.491,5068,9.811,5090,12.647,5091,12.647,5092,12.647,5093,12.647,5094,12.647,5095,10.46,5096,11.328,5097,12.647,5098,12.647]],["keywords/180",[]],["title/181",[975,679.208]],["content/181",[13,4.628,34,3.493,41,4.628,53,3.14,66,4.204,86,1.227,93,5.43,114,6.95,115,4.931,116,2.214,135,3.549,142,3.606,167,4.574,185,3.094,206,4.931,211,8.715,223,4.448,319,2.792,417,5.116,449,6.197,481,5.284,524,3.606,613,4.628,624,2.992,635,4.628,680,6.519,744,4.628,798,3.284,826,5.042,827,7.138,871,4.825,975,7.317,979,6.047,1166,8.03,1395,5.416,1578,5.042,1592,5.871,1595,9.39,1659,9.272,1721,6.239,2228,14.652,2327,8.561,2777,13.158,2825,5.871,3070,10.57,3327,4.871,3360,7.507,3572,7.606,3654,8.03,3701,6.686,3731,6.97,3772,10.047,4162,8.561,4247,7.894,4257,12.286,4264,14.187,4292,11.443,5095,8.561,5099,9.272,5100,9.272,5101,10.352,5102,10.352,5103,10.352,5104,10.352,5105,10.352,5106,10.352]],["keywords/181",[]],["title/182",[449,343.638,3344,497.261]],["content/182",[86,1.493,110,6.592,137,6.001,142,4.389,153,4.185,162,6.28,190,3.997,211,9.909,239,3.005,245,2.452,382,4.609,447,4.687,635,5.633,979,7.36,1175,8.827,1185,4.251,1477,6.431,1593,5.311,1709,6.137,1976,9.773,2026,9.514,2283,6.703,2316,8.459,2336,8.137,2357,8.827,2363,6.592,2815,7.36,3344,9.31,3431,8.827,3740,8.827,3771,10.42,3772,9.018,3902,9.257,4201,10.42,4371,9.257,5107,12.599,5108,12.599,5109,12.599,5110,12.599,5111,12.599,5112,12.599,5113,11.285,5114,9.773,5115,12.599]],["keywords/182",[]],["title/183",[211,664.795,623,359.982]],["content/183",[21,4.44,23,2.503,41,4.888,86,1.719,89,4.791,93,4.973,114,7.341,115,6.91,116,2.339,124,3.128,142,5.053,170,7.066,185,3.268,206,5.208,211,9.04,319,2.862,376,6.59,386,5.325,389,5.449,417,5.307,449,5.244,481,7.405,484,5.449,623,3.689,664,6.59,851,8.481,975,5.72,979,6.387,1019,6.813,1185,3.689,1216,7.061,1350,5.72,1593,6.115,2026,6.91,2228,15.651,2356,7.341,2365,7.341,2499,6.387,2777,11.253,3291,7.341,3327,5.053,3344,8.083,3731,7.23,3772,9.233,4247,8.114,4261,12.994,4262,11.253,4285,12.994,4292,11.655,4545,8.033,5095,9.042,5099,9.793,5116,10.933,5117,14.507,5118,14.507]],["keywords/183",[]],["title/184",[389,647.04]],["content/184",[21,3.91,34,3.249,58,6,84,5.506,85,5.803,86,1.808,93,3.301,94,4.915,109,4.586,124,2.755,131,3.101,135,4.563,229,4.915,245,1.874,275,3.408,286,5.46,307,3.055,319,2.936,336,3.983,374,2.755,377,4.394,386,4.69,389,7.603,409,5.921,417,3.522,456,3.354,624,2.06,874,4.394,1088,9.779,1306,6.746,1319,5.624,1432,5.506,1522,5.46,1558,6.465,1571,4.915,1593,4.059,2026,6.34,2363,5.038,2815,5.624,3308,3.953,3327,6.378,3344,8.698,3378,7.074,3396,7.603,3402,5.624,3772,8.651,4154,10.325,4282,9.779,4292,9.852,4299,11.922,4441,7.469,4460,8.624,4538,9.852,4841,7.469,5068,7.469,5077,7.963,5119,9.629,5120,13.31,5121,15.859,5122,14.74,5123,9.629,5124,9.629,5125,9.629,5126,9.629,5127,9.629,5128,9.629,5129,9.629,5130,8.624,5131,9.629,5132,9.629,5133,9.629]],["keywords/184",[]],["title/185",[4154,827.555,5114,827.555]],["content/185",[34,3.868,41,5.125,85,9.02,86,1.358,93,3.93,109,5.46,116,2.452,125,3.93,131,3.693,135,3.93,162,8.305,179,4.194,185,4.473,202,9.481,211,7.144,239,2.734,245,2.231,285,7.404,319,2.698,386,5.584,389,5.714,409,5.385,542,8.032,644,5.851,667,9.481,1258,6.976,1334,6.909,1349,6.321,1520,11.609,1522,6.501,1709,5.584,1969,6.501,2026,7.129,2027,10.486,2273,7.144,2350,6.154,2363,7.83,2825,6.501,2897,8.423,3308,3.878,3315,7.697,3344,8.234,3378,8.423,3379,7.404,3396,7.459,3402,6.696,3585,11.609,3814,10.268,4154,13.703,4292,7.404,4371,8.423,4538,7.404,5068,8.893,5077,9.481,5113,10.268,5114,8.893,5121,14.609,5122,10.268,5130,10.268,5134,11.464,5135,11.464,5136,11.464]],["keywords/185",[]],["title/186",[3740,747.456,5076,882.296]],["content/186",[84,5.192,86,1.88,116,2.685,117,8.427,185,3.751,236,9.736,312,4.105,319,2.839,333,4.832,377,7.24,524,4.372,543,4.303,626,7.332,725,3.864,1019,7.821,1402,4.669,1511,6.738,1623,12.779,1705,7.332,1782,6.113,2026,5.978,2230,8.794,2363,6.567,2664,9.736,2815,7.332,3308,4.11,3327,4.372,3339,8.106,3344,7.394,3359,8.427,3384,8.106,3507,8.794,3724,9.736,3740,8.794,4538,8.106,5076,14.385,5079,11.242,5080,11.242,5083,11.242,5137,15.864,5138,12.551,5139,12.551,5140,12.551,5141,15.864,5142,12.551,5143,12.551,5144,12.551]],["keywords/186",[]],["title/187",[2292,519.621,4900,783.844]],["content/187",[]],["keywords/187",[]],["title/188",[5145,1007.024]],["content/188",[3,3.285,7,1.862,16,2.176,17,3.015,18,3.389,20,1.551,22,1.144,27,2.131,34,2.59,40,3.015,45,2.087,48,2.574,53,4.502,72,3.015,74,1.797,85,10.71,86,1.158,93,1.6,94,2.383,95,2.814,100,1.68,111,4.956,116,1.642,124,1.336,125,1.6,127,4.555,134,4.042,135,1.6,142,1.626,153,2.549,154,1.708,158,2.909,159,4.352,164,3.363,170,2.274,181,6.347,190,1.481,208,1.416,216,0.985,223,2.006,239,1.83,245,3.577,252,2.327,265,1.737,274,8.104,289,5.601,293,3.861,296,4.182,305,2.442,307,1.481,319,2.728,333,1.797,344,2.131,346,2.046,357,5.567,358,2.395,367,7.229,377,2.131,381,3.825,382,1.708,402,4.467,411,3.917,416,2.176,447,1.737,449,2.472,481,2.383,511,2.909,512,6.713,524,2.673,543,3.35,554,2.814,624,0.999,665,2.909,674,3.861,675,1.797,680,4.555,700,2.046,784,3.271,820,3.235,822,4.625,877,2.964,907,3.861,913,5.388,978,2.909,990,2.909,1133,3.621,1178,2.442,1185,2.59,1333,1.862,1340,3.621,1375,3.621,1376,3.175,1380,2.727,1400,3.861,1442,3.621,1466,5.563,1525,2.727,1534,4.232,1613,7.58,1615,7.58,1686,2.727,1696,2.727,1712,6.091,1799,4.182,1854,3.363,1887,2.814,1903,8.669,1981,2.814,2068,2.274,2137,3.015,2194,3.271,2246,2.909,2283,1.968,2292,6.091,2302,6.874,2350,2.506,2358,3.271,2360,4.483,2363,5.922,2570,3.271,2614,4.182,2643,2.727,2673,3.621,2897,3.43,2905,3.271,3127,3.861,3302,4.182,3309,2.327,3359,3.134,3374,5.639,3502,3.015,3543,4.182,3592,8.396,3693,3.43,3767,4.182,3791,3.015,3863,3.134,4175,10.342,4226,3.43,4228,4.182,4398,3.134,4470,3.861,4799,3.861,4900,12.915,4901,6.347,4904,5.953,4943,8.396,5145,11.022,5146,4.668,5147,4.182,5148,6.874,5149,4.668,5150,4.668,5151,4.668,5152,4.668,5153,4.668,5154,4.668,5155,4.668,5156,10.342,5157,14.527,5158,4.668,5159,4.668,5160,6.874,5161,9.772,5162,7.674,5163,4.668,5164,3.861,5165,4.668,5166,9.772,5167,7.674,5168,4.668,5169,4.668,5170,4.668,5171,4.668,5172,7.674,5173,15.744,5174,8.753,5175,11.201,5176,7.674,5177,4.668,5178,7.674,5179,4.668,5180,11.318,5181,12.044,5182,8.753,5183,8.753,5184,8.753,5185,8.753,5186,4.668,5187,4.668,5188,4.668,5189,4.668,5190,7.674,5191,4.668,5192,4.668,5193,4.668,5194,4.668,5195,4.668,5196,4.668,5197,6.874,5198,7.674,5199,4.668,5200,4.182,5201,4.668,5202,4.668,5203,4.668,5204,4.668,5205,4.668,5206,4.668,5207,4.668,5208,4.668,5209,4.668,5210,4.668,5211,4.668,5212,4.668,5213,7.674,5214,4.668,5215,4.668,5216,4.668,5217,4.668,5218,4.668,5219,4.668,5220,4.668,5221,7.674,5222,4.668,5223,4.668,5224,4.668]],["keywords/188",[]],["title/189",[5225,1073.638]],["content/189",[3,2.547,18,3.143,24,4.934,53,4.616,79,2.158,85,7.516,86,1.296,89,2.414,93,5.416,95,3.32,98,1.35,111,3.557,114,3.698,116,2.668,124,2.51,131,2.826,134,2.279,138,3.859,153,2.914,154,2.015,170,2.683,193,6.446,198,3.037,201,3.432,208,1.671,215,2.567,223,2.367,245,3.548,274,7.516,289,5.055,305,2.882,307,1.747,319,2.811,333,2.12,336,2.279,357,5.335,358,3.338,367,7.412,402,4.819,417,4,447,2.049,453,2.957,474,2.882,483,1.982,512,6.694,524,1.919,543,4.275,624,1.178,633,4.047,638,3.32,665,3.432,675,2.12,725,1.696,775,5.257,784,3.859,798,1.747,820,4.609,822,6.59,871,2.567,877,1.671,907,7.256,908,3.859,989,3.557,1125,3.859,1185,4.208,1349,3.037,1409,3.698,1412,3.859,1466,4.523,1511,2.957,1599,4.934,1613,8.482,1615,8.482,1672,4.273,1712,4.273,1806,3.557,1807,3.859,1809,4.273,1903,9.51,2137,5.666,2208,4.934,2273,3.432,2292,2.683,2319,4.273,2360,3.217,2363,2.882,2546,4.047,2613,4.273,2622,9.043,2654,3.557,3168,4.047,3309,2.745,3374,4.047,3418,3.698,3498,3.32,3592,11.205,3693,4.047,3862,8.034,4172,4.273,4175,10.313,4226,11.181,4383,7.256,4398,3.698,4416,3.32,4444,9.043,4900,11.181,4901,4.555,4904,4.273,4929,4.934,4930,9.794,4943,8.373,5145,11.254,5147,4.934,5148,4.934,5156,9.043,5157,4.934,5160,4.934,5164,7.256,5173,15.979,5174,4.934,5175,11.17,5181,12.995,5182,9.794,5183,9.794,5184,9.794,5185,9.794,5197,12.198,5225,13.066,5226,5.508,5227,5.508,5228,11.17,5229,5.508,5230,10.935,5231,10.935,5232,5.508,5233,5.508,5234,8.774,5235,10.935,5236,8.774,5237,5.508,5238,10.935,5239,8.774,5240,5.508,5241,5.508,5242,5.508,5243,5.508,5244,12.47,5245,8.774,5246,5.508,5247,5.508,5248,8.774,5249,5.508,5250,5.508,5251,5.508,5252,5.508,5253,8.774,5254,5.508,5255,5.508,5256,5.508,5257,8.774,5258,5.508]],["keywords/189",[]],["title/190",[1311,715.826]],["content/190",[6,7.77,10,5.431,18,2.746,23,3.314,25,5.562,48,6.009,53,3.305,79,4.269,81,5.85,86,1.926,93,3.736,94,5.562,97,8.453,107,7.317,116,3.096,118,5.701,131,3.51,134,4.508,143,6.009,145,2.149,149,6.365,161,8.453,174,7.038,179,3.987,208,3.305,216,2.3,223,4.683,239,2.599,265,4.054,269,7.317,286,8.209,289,4.808,359,6.365,375,8.007,524,3.796,624,2.331,635,4.872,721,2.564,764,4.594,833,4.683,894,7.635,1334,6.568,1399,6.568,1510,8.453,1534,6.009,1566,7.038,1592,8.209,1712,7.917,1821,7.576,1896,4.973,2246,6.791,2296,9.761,2344,7.038,2350,5.85,2365,9.719,2448,8.453,2500,9.761,2555,7.038,2825,6.18,3490,8.453,3502,9.349,3693,8.007,3700,9.012,3863,7.317,3894,9.012,4172,8.453,4252,9.761,4900,13.244,4904,8.453,5059,9.761,5145,12.608,5156,9.012,5225,13.442,5228,9.761,5259,10.897,5260,10.897,5261,10.897,5262,10.897,5263,10.897,5264,10.897,5265,10.897,5266,9.761]],["keywords/190",[]],["title/191",[623,265.389,2544,446.034,3308,203.791,4353,242.131]],["content/191",[]],["keywords/191",[]],["title/192",[3396,647.04]],["content/192",[3,3.102,18,3.601,27,6.521,74,4.114,86,1.693,93,3.663,98,2.62,108,4.421,109,6.805,124,3.057,130,6.659,140,8.564,145,2.108,179,7.084,206,5.09,216,2.255,312,3.495,319,2.944,333,4.114,357,5.598,358,2.62,409,5.792,608,3.783,623,6.043,680,6.659,833,4.592,979,6.242,990,6.659,1198,7.67,1258,7.502,1402,3.975,1432,4.421,1535,6.902,1704,6.441,2504,10.497,2818,9.572,3070,8.903,3319,11.277,3327,3.722,3396,8.022,3545,7.851,3579,5.892,3592,9.593,3598,9.572,3731,5.326,4247,5.326,4258,11.083,4549,11.083,4841,8.289,5266,9.572,5267,10.686,5268,14.288,5269,10.686,5270,10.686]],["keywords/192",[]],["title/193",[53,323.594,3862,783.844]],["content/193",[3,2.249,16,2.201,22,1.157,23,1.773,34,1.593,41,2.111,45,2.111,53,4.682,73,1.142,86,1.767,93,4.634,98,1.157,108,3.205,116,1.01,124,1.351,137,2.249,142,1.645,154,1.727,167,1.544,173,3.17,179,5.954,180,3.05,185,1.411,190,1.498,191,2.249,206,4.691,215,2.201,219,2.573,229,2.41,285,3.05,308,1.174,319,2.989,333,1.818,350,2.249,358,1.899,365,3.395,374,1.351,404,1.85,409,5.555,416,2.201,417,4.169,418,2.982,431,2.069,449,3.172,459,2.201,473,7.984,483,4.527,512,2.535,524,3.431,543,3.907,561,3.611,608,2.742,613,3.463,623,4.245,624,1.01,676,3.469,680,3.611,726,1.569,794,2.678,825,3.905,877,1.432,979,2.758,1013,3.05,1014,3.17,1175,3.308,1198,6.117,1258,7.195,1348,3.05,1401,3.17,1402,2.882,1440,2.604,1500,3.308,1511,4.158,1517,2.846,1519,4.229,1535,3.05,1583,3.861,1593,1.99,1686,2.758,1699,3.17,1704,2.846,1709,2.3,1721,5.936,1806,3.05,1839,3.469,1857,3.905,1981,2.846,1988,3.308,2003,4.229,2019,14.883,2026,3.69,2246,2.942,2293,4.229,2324,4.229,2341,7.984,2356,3.17,2519,3.663,2599,13.139,2601,13.139,2613,3.663,2616,3.05,2621,3.17,2905,3.308,3070,4.827,3308,1.223,3309,2.353,3319,3.308,3327,4.709,3339,3.05,3360,4.158,3396,4.909,3419,3.469,3450,3.308,3563,5.427,3579,2.604,3592,7.651,3731,6.271,3862,8.373,4242,4.229,4247,6.271,4257,3.663,4258,7.64,4266,3.663,4271,3.905,4283,4.229,4287,3.905,4335,3.469,4347,4.229,4353,3.032,4437,4.797,4744,4.229,4917,4.229,4943,3.17,5100,4.229,5271,4.722,5272,4.722,5273,4.722,5274,9.849,5275,4.722,5276,4.722,5277,4.229,5278,15.888,5279,7.746,5280,13.52,5281,4.722,5282,13.52,5283,13.52,5284,15.888,5285,13.52,5286,15.888,5287,13.52,5288,14.909,5289,14.909,5290,4.722,5291,7.746,5292,7.746,5293,7.746,5294,7.746,5295,7.746,5296,7.746,5297,7.746,5298,7.746,5299,4.722,5300,7.746,5301,4.722,5302,4.722,5303,4.722,5304,4.722,5305,4.722,5306,4.722,5307,4.722]],["keywords/193",[]],["title/194",[3886,1007.024]],["content/194",[23,2.562,25,5.713,77,6.746,86,1.952,89,6.456,93,5.05,131,4.746,179,4.094,206,5.331,212,3.551,216,2.362,252,5.578,275,3.962,319,2.872,336,4.63,382,4.094,409,5.926,511,6.974,524,3.898,525,7.229,623,3.777,634,9.256,765,10.025,798,3.551,827,5.713,1016,5.217,1182,7.842,1189,4.385,1258,7.677,1886,9.256,2026,5.331,2030,7.842,2145,10.025,2499,6.538,2517,9.256,3308,2.9,3327,3.898,3396,5.578,3483,7.909,3579,6.171,3585,8.682,3731,5.578,3886,14.106,4247,5.578,4353,5.07,4437,8.022,4654,10.025,4722,10.025,4843,13.196,4995,10.025,5121,12.184,5308,11.192,5309,11.192,5310,11.192,5311,16.47,5312,11.192,5313,11.192,5314,11.192,5315,11.192,5316,11.192,5317,11.192,5318,11.192,5319,11.192]],["keywords/194",[]],["title/195",[2690,909.555]],["content/195",[34,3.408,53,3.063,84,4.178,86,1.63,93,3.462,108,4.178,115,4.81,131,3.253,135,3.462,191,4.81,239,2.409,286,5.727,319,2.928,333,3.888,336,4.178,374,2.889,543,3.462,574,4.919,623,5.666,624,2.16,644,7.02,675,3.888,784,7.075,827,5.155,828,7.834,977,5.421,1198,9.956,1440,5.568,1477,5.155,1563,7.834,1697,5.899,1705,5.899,2138,5.421,2283,5.797,2363,5.284,2365,6.78,2366,9.046,2616,6.522,2690,10.957,2815,5.899,3070,6.293,3308,4.052,3319,7.075,3327,3.518,3396,8.369,3466,11.374,3483,7.383,3545,12.336,3597,12.319,3665,7.075,3875,9.046,4353,4.815,4437,4.919,4538,6.522,4546,15.039,4547,12.319,4548,15.039,4549,7.834,4550,12.319,4551,12.319,4552,9.046,4554,9.046,4555,9.046,4677,9.046,4938,7.834,5200,12.319,5320,13.753,5321,10.099,5322,10.099,5323,10.099,5324,10.099]],["keywords/195",[]],["title/196",[3415,909.555]],["content/196",[2,4.741,3,2.356,6,4.357,8,4.045,16,3.783,22,1.99,23,2.699,27,3.704,34,4.686,47,6.296,53,5.416,66,3.296,86,0.962,93,5.55,98,1.99,108,3.358,116,1.736,135,4.042,140,5.877,142,4.107,145,1.601,153,3.917,154,2.969,160,3.629,162,4.045,173,5.449,185,3.524,190,2.575,206,6.615,215,3.783,216,1.713,222,3.557,289,3.917,305,6.169,319,2.846,333,3.125,374,2.322,402,2.696,409,6.078,417,2.969,449,4.473,451,5.687,456,2.827,481,4.143,512,7.455,524,2.827,543,2.782,623,3.979,624,1.736,629,4.892,642,6.712,664,4.892,798,3.741,833,3.488,975,4.246,1198,7.455,1258,7.105,1401,7.917,1432,3.358,1440,4.475,1477,4.143,1517,4.892,1556,3.866,1593,5.854,1712,3.953,1981,4.892,2026,3.866,2346,8.262,2360,4.741,2613,9.147,2618,6.296,2643,4.741,2697,6.296,2706,5.242,2815,4.741,2825,4.603,2961,11.824,3070,10.525,3308,3.055,3309,4.045,3327,5.309,3376,7.27,3402,4.741,3415,11.834,3498,4.892,3566,6.296,3579,7.658,3731,6.922,3862,10.204,3928,7.27,4222,7.107,4247,8.07,4282,5.963,4333,6.712,4353,2.499,4437,5.743,4553,6.296,4841,6.296,5277,7.27,5325,8.116,5326,8.116,5327,8.116,5328,8.116,5329,8.116,5330,8.116,5331,8.116,5332,17.429,5333,8.116,5334,8.116,5335,8.116,5336,8.116]],["keywords/196",[]],["title/197",[764,547.25]],["content/197",[20,4.047,25,4.334,34,2.865,41,3.797,53,3.695,74,3.269,86,1.844,93,2.911,104,3.269,125,2.911,131,2.735,135,2.911,145,2.403,154,3.106,162,6.072,206,4.045,286,4.816,319,2.974,333,3.269,357,4.773,404,3.327,409,5.93,417,5.212,484,4.232,485,5.291,524,2.958,543,2.911,624,1.816,635,3.797,725,2.614,764,3.58,833,6.689,877,2.576,1177,4.816,1181,5.291,1198,4.558,1349,4.682,1592,4.816,1696,4.96,2341,5.949,2455,9.45,2815,4.96,2950,7.606,3308,2.2,3310,10.644,3327,5.741,3334,7.606,3344,3.958,3360,4.558,3379,11.079,3396,6.072,3402,8.322,3579,7.856,3592,5.701,3699,8.951,3731,6.072,3773,5.949,3823,5.949,4247,6.072,4287,7.023,4353,3.75,4427,7.023,4437,5.934,4549,12.784,4601,15.365,4664,7.023,5096,7.606,5337,12.183,5338,8.492,5339,16.481,5340,14.247,5341,14.247,5342,15.566,5343,12.183,5344,8.492,5345,15.566,5346,12.183,5347,12.183,5348,8.492,5349,8.492,5350,8.492,5351,8.492,5352,8.492,5353,8.492,5354,8.492]],["keywords/197",[]],["title/198",[131,343.638,975,558.161]],["content/198",[18,2.633,21,4.244,93,3.582,108,6.584,131,5.485,135,3.582,137,4.977,162,8.487,206,4.977,297,7.678,319,2.552,333,4.023,359,6.104,409,5.064,431,4.579,447,3.888,511,6.512,526,4.168,605,4.49,623,3.526,624,3.404,628,8.642,630,3.888,833,4.49,975,10.192,1189,4.094,1198,8.543,1204,8.642,1251,8.106,1432,4.323,1566,6.749,1592,5.926,1705,6.104,1749,11.64,1977,7.016,2029,7.678,2092,7.678,2367,9.36,2616,6.749,2643,6.104,2651,8.642,2654,6.749,2706,6.749,2835,7.016,3308,3.647,3309,5.208,3339,6.749,3360,5.609,3379,9.09,3396,7.932,3425,15.252,3449,8.642,3482,8.106,3563,7.321,3577,6.749,4260,8.642,4353,4.9,4416,8.483,4437,8.294,4729,9.36,5114,8.106,5355,10.45,5356,10.45,5357,10.45,5358,10.45,5359,10.45,5360,10.45,5361,10.45,5362,10.45,5363,10.45,5364,10.45,5365,10.45,5366,14.075,5367,10.45,5368,10.45,5369,10.45]],["keywords/198",[]],["title/199",[2400,782.439]],["content/199",[2,4.661,23,3.149,41,3.568,53,4.172,86,1.792,93,2.735,97,6.19,100,2.871,116,1.707,131,2.57,142,2.779,154,2.919,185,2.385,206,3.801,219,2.651,229,4.073,239,1.903,252,3.977,275,4.123,319,2.968,357,6.578,386,3.886,402,3.869,409,2.871,444,5.591,455,5.591,499,2.692,596,5.295,623,4.641,624,1.707,629,4.809,637,4.661,764,3.364,784,11.764,789,10.432,822,4.809,833,6.498,877,2.42,1026,9.034,1135,3.497,1163,4.972,1198,7.383,1258,7.826,1333,3.182,1350,4.175,1376,4.818,1466,5.69,1511,4.283,1534,4.4,1556,3.801,1592,4.525,1593,3.364,1600,5.153,1685,4.525,2065,5.863,2072,6.19,2150,11.374,2327,6.599,2400,11.101,2570,11.764,2612,7.147,3151,7.147,3308,2.068,3309,3.977,3327,4.791,3344,5.428,3384,8.883,3445,5.863,3450,5.591,3541,6.19,3572,5.863,3731,6.855,3831,5.357,4226,10.105,4229,10.432,4247,3.977,4341,7.819,4353,5.169,4431,6.599,4437,7.365,4456,6.19,4597,7.147,4672,7.147,5164,6.599,5370,7.979,5371,7.979,5372,7.979,5373,7.979,5374,7.979,5375,7.979,5376,7.979,5377,7.979,5378,7.979,5379,7.979,5380,7.979,5381,11.647,5382,7.979,5383,7.979,5384,7.979,5385,7.979,5386,7.979,5387,7.979]],["keywords/199",[]]],"invertedIndex":[["",{"_index":319,"title":{},"content":{"6":{"position":[[296,1],[332,1],[343,1],[439,1],[532,1],[556,1],[769,1],[785,1],[793,1],[800,1],[806,1],[808,1],[816,1],[827,1],[860,1],[866,1],[870,3],[874,1],[900,1],[905,1],[913,1],[915,1],[917,1],[925,1],[929,1],[935,3],[939,1],[965,1],[969,1],[1005,1],[1011,1],[1036,1],[1045,1],[1069,1],[1074,1]]},"7":{"position":[[275,1],[290,2],[293,2],[302,1],[328,1],[343,1],[347,1],[358,1],[384,1],[389,1],[440,1],[454,2],[476,2],[491,1],[493,1],[495,2],[565,1],[613,1],[637,1],[661,1],[678,1],[733,1],[787,1],[840,1],[851,1],[886,1],[890,1],[902,1],[938,1],[942,1],[962,1],[964,2],[1000,1],[1034,1],[1089,1],[1155,1],[1157,2],[1166,1],[1179,1]]},"8":{"position":[[87,1],[97,1],[102,1],[171,1],[198,2]]},"9":{"position":[[431,1],[557,1],[581,1],[666,1],[730,1],[747,1],[781,1],[795,1]]},"10":{"position":[[140,2],[151,1],[168,1],[205,1],[311,1],[386,1],[417,1],[455,1],[465,1]]},"11":{"position":[[348,1],[358,1],[373,1],[414,1],[416,1],[453,1],[488,2],[491,2],[512,1]]},"12":{"position":[[230,1],[268,1],[304,1],[349,1],[359,1],[374,1],[376,1],[411,1],[447,2],[450,2],[472,1],[580,1]]},"13":{"position":[[532,1],[544,1],[568,1],[573,1],[585,1],[595,1],[614,1],[728,1],[734,1],[772,1],[798,1],[829,1],[841,1],[897,1],[1024,1],[1054,1],[1112,1],[1148,1],[1268,1],[1294,1],[1319,1],[1364,1],[1456,1],[1527,1],[1543,1],[1669,1],[1776,1],[1789,1]]},"14":{"position":[[1349,1],[1369,1],[1374,1],[1398,1],[1403,1],[1415,1],[1425,1],[1455,1],[1585,1],[1591,1],[1629,1],[1655,1],[1686,1],[1695,1],[1771,1],[1802,1],[1818,1],[1848,1],[1876,2],[1915,1],[2033,1],[2058,1],[2088,1],[2146,1],[2182,1],[2340,1],[2366,1],[2391,1],[2436,1],[2528,1],[2599,1],[2626,1],[2752,1],[2859,1],[2872,1]]},"15":{"position":[[718,1],[738,1],[743,1],[767,1],[772,1],[784,1],[794,1],[826,1],[954,1],[972,1],[978,1],[1016,1],[1076,1],[1085,1],[1181,68],[1250,1],[1334,1],[1354,1],[1375,1],[1393,1],[1409,1],[1439,1],[1456,68],[1544,2],[1583,1],[1701,1],[1726,1],[1756,1],[1814,1],[1850,1],[2012,1],[2038,1],[2063,1],[2108,1],[2200,1],[2271,1],[2300,1],[2426,1],[2533,1],[2546,1]]},"17":{"position":[[152,1],[204,1],[231,1],[242,1],[257,1],[342,1]]},"18":{"position":[[85,1]]},"19":{"position":[[257,1],[286,1],[344,1],[364,1]]},"20":{"position":[[240,1],[280,1],[588,1],[621,1],[644,1],[699,1],[708,1],[1071,1],[1091,1],[1106,1],[1112,1],[1176,1],[1209,1],[1220,1],[1279,1],[1289,1],[1350,1],[1381,1],[1460,1],[1483,1],[1537,1],[1573,1],[1616,1],[1660,1],[1762,1],[1770,1],[1797,1],[1884,1],[1902,1],[1915,1],[1920,1],[1954,1],[1972,1],[1989,1],[2026,1],[2028,1],[2030,1],[2066,2],[2069,1],[2110,3],[2114,1],[2116,1],[2134,1],[2156,2],[2159,1],[2193,1],[2195,1],[2205,1],[2296,1],[2414,1],[2489,1],[2503,1],[2598,1],[2619,1],[2627,1],[2649,1],[2734,1]]},"22":{"position":[[291,1],[293,2],[343,2],[420,1],[439,1],[453,2],[515,1],[544,2],[605,1],[699,1],[712,1],[724,1],[781,1],[783,2],[817,1],[908,1],[995,1],[1065,2],[1210,1],[1230,1],[1246,1],[1250,1],[1257,1],[1259,2],[1262,1],[1358,1],[1360,2],[1409,2],[1475,1],[1504,2],[1537,1],[1585,1],[1609,1],[1615,2],[1686,1],[1849,1],[1919,2],[1942,1],[1987,2],[2014,1],[2059,2],[2085,1],[2130,2],[2155,1],[2200,2],[2224,1],[2264,2],[2316,1],[2351,1],[2402,1],[2420,1],[2493,1],[2668,1],[2720,1],[2780,1],[2842,1],[2879,1],[2921,1],[2974,1],[3041,1]]},"23":{"position":[[220,1],[288,1],[368,1],[436,1],[503,1],[573,1]]},"24":{"position":[[457,1],[505,1],[555,1],[557,2],[596,1],[629,1],[665,1],[700,1],[727,1],[766,1],[809,1],[853,1],[899,1],[964,1],[1023,1],[1104,1],[1172,1],[1174,2],[1214,1],[1236,1],[1257,1],[1342,1],[1409,1],[1456,1],[1469,2],[1490,2],[1505,2],[1526,2],[1612,1],[1614,2],[1630,1],[1632,2],[1646,1],[1648,2],[1662,1],[1807,1],[1891,1],[2031,1],[2144,1],[2234,1]]},"25":{"position":[[182,1],[230,1],[280,1],[282,2],[321,1],[351,1],[385,1],[421,1],[446,1],[483,1],[527,1],[572,1],[619,1],[684,1],[743,1],[824,1],[892,1],[894,2],[934,1],[956,1],[977,1],[1062,1],[1129,1],[1176,1],[1189,2],[1210,2],[1225,2],[1246,2],[1329,1],[1331,2],[1345,1],[1347,2],[1366,1],[1368,2],[1382,1],[1531,1],[1615,1],[1755,1],[1868,1],[1958,1]]},"28":{"position":[[879,1],[938,1],[988,1],[1043,1],[1249,1],[1329,1],[1384,1],[1481,1],[1546,1],[1766,1],[1886,1],[1888,1],[1970,1],[2018,1],[2077,1],[3049,1],[3129,1],[3179,1],[3272,1],[3332,1],[3673,1],[3732,1]]},"30":{"position":[[1211,1],[1269,1],[1324,1],[1352,1],[1379,1],[1405,1],[1615,1],[1695,1],[1750,1],[1842,1],[1983,1],[2054,1],[2964,1],[3044,1],[3099,1],[3191,1],[3268,1],[3392,1],[3480,1],[3548,1],[3747,1],[4888,1],[4968,1],[5018,1],[5106,1],[5237,1],[5304,1],[6032,1],[6112,1],[6167,1],[6260,1],[6337,1],[6467,1],[6555,1],[6622,1],[6827,1],[8413,1],[8479,1],[8511,1],[8547,1],[8587,1],[8619,1],[8621,1],[8710,1],[8719,1],[8721,2],[8724,1],[8804,1],[8873,1],[8889,1],[8898,1],[8939,1],[8967,1],[8983,1],[8992,1],[9069,1],[9088,1],[9148,1],[9210,1],[9277,1],[9303,1],[9412,1],[9458,1],[9534,1],[9610,1],[9650,1],[9652,2],[9720,2],[9860,1],[9944,1],[10128,3],[10140,1],[10197,1],[10251,1],[10301,1],[10352,1]]},"32":{"position":[[484,1],[536,1],[586,1],[1609,1],[1660,1]]},"34":{"position":[[1032,1],[1064,1],[1136,1],[1225,1],[1241,1],[1263,1],[1319,2],[1346,1],[1422,1],[1487,1],[1510,2],[1595,1],[1653,1],[1710,1],[1760,1],[1809,1],[1818,1],[1870,1],[1885,1],[1959,2],[2068,1],[2087,1],[2114,1],[2204,1],[2233,1],[2241,1],[2259,1],[2276,1],[2291,2],[2345,2],[2361,1],[2435,2],[2522,1],[2537,2],[2582,1],[2630,1],[2639,1],[2710,1],[2752,1],[2819,1],[2840,1],[3184,1],[3310,1],[3701,1]]},"39":{"position":[[543,1],[545,2],[562,1],[590,1],[595,1],[675,1],[695,1],[738,1],[860,1],[876,1],[898,1],[937,1],[953,1],[985,1],[1062,1],[1085,1],[1100,1],[1173,1],[1283,1],[1300,1],[1327,1],[1415,1],[1453,1],[1461,1],[1479,1],[1496,1],[1508,1],[1565,2],[1581,1],[1654,1],[1734,1],[1746,1],[1782,1],[1873,1],[2015,1],[2054,1],[2078,1],[2087,1],[2214,1],[2279,1],[2305,1],[2406,1],[2454,1],[2478,1],[2616,1],[2640,1],[2684,1],[2743,1],[2808,1],[2874,1],[2987,1],[3105,1],[3107,2],[3139,1],[3173,1],[3255,1]]},"40":{"position":[[116,1],[1650,1],[2618,1]]},"43":{"position":[[357,1],[455,1],[480,1],[527,1],[542,1],[588,1]]},"44":{"position":[[210,1],[230,1],[232,2],[272,2],[457,1],[535,1],[608,1],[640,1],[662,2],[708,1],[1336,1],[1342,2],[1389,3],[1468,1],[1480,2]]},"45":{"position":[[1991,1],[2040,1],[2073,1],[2107,1],[2181,1],[2827,1],[2860,1],[2887,1],[2961,1]]},"46":{"position":[[592,1]]},"47":{"position":[[107,1],[145,1],[181,1]]},"51":{"position":[[128,1],[161,1],[175,1],[239,1],[275,1],[460,1],[486,1],[531,1],[578,1],[635,1],[670,1],[1090,1],[1125,1],[1160,3],[1177,1],[1207,1],[1224,2],[1227,3],[1275,1],[1277,2],[1320,1],[1363,2],[1383,1],[1435,1],[1685,1],[1718,1],[2091,1],[2266,1],[2298,2],[2301,4],[2317,1],[2349,1],[2393,2],[2396,6],[2416,1],[2489,1],[3652,1],[3694,1],[3708,1],[3722,1],[3747,2],[3750,4],[3971,1],[4122,1],[4160,1],[4181,1]]},"52":{"position":[[159,1],[200,1],[240,1],[282,1],[322,1],[365,1],[397,1],[745,1],[757,1],[798,1],[829,1],[883,1],[896,1],[918,1],[934,1],[980,1],[1011,2],[1014,3],[1033,2],[1036,4],[1049,1],[1091,2],[1094,1],[1096,1],[1098,1],[1114,1],[1127,1],[1146,1]]},"53":{"position":[[190,1],[339,1],[660,1],[712,2],[752,1],[867,1],[1094,2],[1144,1],[1149,1],[1283,1],[1347,1],[1574,1]]},"57":{"position":[[165,1]]},"60":{"position":[[136,1]]},"61":{"position":[[1525,1],[1576,1],[1578,1],[1580,1],[1704,1],[1765,1],[1779,1],[1792,1],[1794,3],[1798,1],[2149,1],[2206,1],[2254,1],[2315,1]]},"62":{"position":[[466,1],[543,2],[557,1],[581,1],[613,1],[640,1],[682,1],[770,1],[918,1],[965,1],[1037,1],[1094,1],[1096,1],[1098,1],[1100,1],[1151,1],[1223,1],[1250,1],[1336,1],[1422,1],[1507,2],[1513,3]]},"64":{"position":[[793,1],[836,1],[873,2],[907,2],[943,1],[958,1],[976,1],[994,1],[1026,1],[1484,1],[1513,1],[1540,1],[1559,1],[1561,3],[1585,1],[1604,1],[1640,1],[1666,1],[1698,1]]},"65":{"position":[[596,1],[625,1],[647,1],[665,1],[687,1],[829,1],[846,2],[879,1],[916,1],[1596,1],[1628,1],[1681,1],[1718,2],[1752,2],[1789,1],[1806,2],[1843,1],[1876,1],[2323,1],[2359,1],[2376,2],[2397,1],[2436,1]]},"68":{"position":[[499,1],[539,1],[589,1]]},"70":{"position":[[279,1],[453,1],[617,2],[636,1],[664,1],[699,1],[706,1],[710,1],[732,1],[963,1],[1023,1],[1030,1],[1070,1],[1110,1],[1137,1],[1174,1]]},"71":{"position":[[379,1],[553,1],[717,2],[736,1],[764,1],[799,1],[806,1],[810,1],[832,1],[1213,1],[1253,1],[1261,1],[1288,1],[1325,1]]},"74":{"position":[[570,1],[610,1],[628,1],[647,2],[665,1],[687,1]]},"76":{"position":[[217,1],[275,1],[347,1],[388,1],[430,1],[438,1],[502,1],[563,1],[629,1],[692,1],[719,1],[764,1],[1002,1],[1061,1],[1110,1],[1142,1],[1215,1],[1254,1],[1281,1],[1331,1],[1360,1],[1422,1],[1473,1],[1514,1],[1548,1],[1607,1],[1678,2],[1707,1],[1734,2],[1763,1],[1952,1],[1967,1],[1971,1],[2010,1],[2037,1],[2067,1],[2097,1],[2143,1],[2172,1],[2191,1],[2207,1],[2216,1],[2280,1],[2344,1],[2459,2],[2478,1],[2490,1],[2496,2],[2520,3],[2609,1],[2645,1],[2714,1],[2733,1],[2749,1],[2787,1],[2831,1],[2868,1],[2887,1],[2903,1],[2928,1],[2938,1],[2984,1],[3030,1],[3072,1],[3122,1],[3177,1],[3196,1],[3212,1],[3237,1],[3263,2],[3268,1]]},"78":{"position":[[167,1],[200,1],[231,1],[288,1],[307,1],[322,1],[429,1],[596,1]]},"88":{"position":[[601,1],[655,1],[705,1],[753,1],[778,1],[800,1],[956,1],[990,1],[1077,1],[1099,1],[1197,1],[1230,1],[1259,1],[1417,1],[1487,1],[1748,1],[1816,1],[2688,1],[2717,1],[2734,1],[2745,1],[3150,1]]},"90":{"position":[[369,1],[429,1],[489,1],[536,1],[593,1],[643,1],[675,1],[762,1],[832,1],[896,1],[923,1],[940,1],[1024,1],[1032,1],[1062,1],[1104,1],[1150,1],[1190,1],[1243,1],[1279,1],[1319,1],[1352,1],[1374,1],[1556,1],[1705,1],[1798,1],[1839,1],[2147,1],[2217,1],[2281,1],[2308,1],[2325,1],[2409,1],[2417,1],[2447,1],[2489,1],[2535,1],[2575,1],[2628,1],[2664,1],[2707,1],[2729,1],[2849,1],[2942,1],[2983,1],[3224,1],[3287,1],[3343,1],[3403,1],[3463,1],[3523,1],[3592,1],[3660,1],[3693,1],[3726,1],[3759,1],[3773,1],[3797,1],[3853,1],[3990,1],[4039,1],[4129,1],[4305,1],[4317,1],[4397,1],[4410,1],[4634,1]]},"91":{"position":[[417,1],[471,1],[547,1],[606,1],[631,1],[919,1],[1001,1],[1062,1],[1089,1],[1738,1],[1775,1],[1932,1],[1974,1],[2014,1],[2033,3],[2083,1],[2116,1],[2180,1],[2212,1],[2288,1],[2290,2],[2458,1],[2506,1],[2540,1],[2588,1],[2640,1],[2689,1],[2773,1],[2818,1],[2873,1],[2890,1],[2908,1],[2963,1],[3016,1],[3069,2],[3124,1],[3190,1],[3253,1],[3373,1],[3398,1],[3419,1],[3421,2],[3529,1],[3580,1],[3673,1],[3735,1],[3811,1],[3888,1],[3963,1],[4039,1],[4099,1],[4145,1],[4229,2],[4238,2],[4325,1],[4406,61],[5143,1],[5216,61],[5520,1],[5599,61]]},"92":{"position":[[271,1],[318,1],[352,1],[400,1],[452,1],[501,1],[585,1],[630,1],[685,1],[702,1],[720,1],[775,1],[828,1],[881,2],[936,1],[1002,1],[1065,1],[1179,61],[1737,61],[1896,61]]},"93":{"position":[[1503,1],[1527,1],[1540,1],[1542,2],[1627,1],[1629,2],[1678,2],[1707,1],[1770,1],[1847,1],[1912,1],[1975,1],[2093,1],[2162,1],[2220,2],[2249,1],[2355,1],[2404,2],[2445,1],[2483,1],[2556,1],[2577,1],[2600,1],[2763,1],[2795,1],[2830,1],[2927,1],[3005,1],[3198,1],[3225,2],[3238,1],[3259,2],[3306,1],[3400,1],[3505,1],[3626,1],[4016,1],[4070,1],[4120,1],[4168,1],[4193,1],[4215,1],[4345,1],[4387,1],[4427,1],[4446,3],[4496,1],[4529,1],[4586,1],[4626,1],[4666,1],[4668,2],[4687,1],[4689,2],[4743,1],[4753,3],[4762,1],[4764,1],[4797,1],[4819,1],[4821,2],[4835,1],[4866,1],[4910,1],[4950,1],[5064,1],[5158,1],[5168,3],[5177,1],[5179,1],[5212,1],[5234,1],[5236,2],[5250,1],[5281,1],[5325,1],[5365,1],[5492,1],[5587,1]]},"96":{"position":[[724,1],[794,1],[1143,1],[1208,1],[1221,1],[1282,3],[1673,1],[1759,1],[2219,1],[2307,1]]},"97":{"position":[[1554,1],[1583,1],[1627,1],[1629,1],[2007,1],[3584,1],[3602,1],[3633,1],[3710,1],[3759,1],[3761,1],[3763,2],[3822,1],[3836,1],[3878,1],[4247,4],[5053,1],[5058,1],[5107,1],[5109,4]]},"103":{"position":[[526,1],[563,1],[576,1],[581,1],[601,1],[609,1],[622,1],[627,1],[928,1],[1007,1],[1029,1],[1079,1],[1145,1],[1199,1],[1229,2],[1257,1],[1297,1],[1360,1],[1400,1],[1610,2],[1714,1],[1750,1],[2069,1]]},"105":{"position":[[529,1],[585,1],[629,1],[653,1],[713,1],[780,1],[804,1],[861,1],[885,1],[895,1],[959,1],[1022,1],[1046,1],[1053,1],[1092,1],[1138,1],[1169,1],[1171,1],[1330,1],[1411,1],[1482,1],[1532,1],[1574,1],[1597,1],[1683,1],[1772,2],[1807,1],[1898,1],[2707,1],[2908,1],[3180,1]]},"109":{"position":[[255,1],[294,1],[322,1],[405,1],[423,1],[448,1],[466,1]]},"110":{"position":[[268,1],[470,1],[498,1]]},"111":{"position":[[334,1],[401,2],[444,2],[494,1]]},"112":{"position":[[615,1],[686,1]]},"113":{"position":[[287,2],[354,2],[421,2],[460,1],[462,2],[519,2],[577,2],[601,2],[724,1],[736,1],[738,2],[805,2],[871,2],[956,1],[998,2],[1061,2],[1127,2],[1182,2],[1237,2],[1275,1],[1277,2],[1362,1],[1422,2],[1503,1],[1505,2],[1605,1],[1619,2],[1739,2],[1795,1],[1906,2],[1970,2],[2036,2],[2110,2],[2190,1],[2262,2],[2406,1]]},"115":{"position":[[119,1],[121,2],[215,2],[250,1],[378,1],[450,2],[527,2],[600,2],[675,2],[705,1],[730,2],[733,1],[811,3],[838,1],[1119,1],[1124,1],[1137,1],[1163,2],[1166,1],[1168,1],[1170,18],[1239,1],[1466,1],[1471,1],[1484,1],[1510,2],[1513,1],[1515,1],[1517,18],[1619,1],[1749,1],[1754,1],[1767,1],[1793,2],[1796,1],[1798,1],[1800,18],[1896,1],[2034,1],[2207,1],[2212,1],[2225,1],[2251,2],[2254,1],[2256,1],[2258,18],[2383,1],[2444,1]]},"116":{"position":[[219,1],[221,2],[310,2],[350,1],[478,1],[567,1],[593,2],[665,2],[724,1],[750,2],[753,1],[831,3],[859,1],[1071,1],[1076,1],[1089,1],[1115,2],[1118,1],[1120,1],[1122,18],[1191,1],[1371,1],[1376,1],[1389,1],[1415,2],[1418,1],[1420,1],[1422,18],[1524,1],[1654,1],[1659,1],[1672,1],[1698,2],[1701,1],[1703,1],[1705,18],[1801,1],[1939,1],[2065,1],[2070,1],[2083,1],[2109,2],[2112,1],[2114,1],[2116,18],[2241,1],[2302,1]]},"117":{"position":[[1011,1],[1013,2],[1139,1],[1362,1],[1412,2],[1521,2],[1581,1],[1607,2],[1610,1],[1612,2],[1715,2],[1748,1],[1851,3],[1879,1]]},"121":{"position":[[2212,1],[2224,1]]},"125":{"position":[[4277,3],[5268,1],[5385,1],[5387,1],[5625,1],[5816,1],[5933,1],[8614,1],[8649,1],[8679,1],[8695,1],[9085,1],[9118,1],[9146,1],[11693,1]]},"127":{"position":[[592,1],[633,1],[641,1],[680,2],[709,1],[711,1],[811,1],[1242,1],[1283,1],[1291,1],[1306,1],[1362,1],[1364,1]]},"128":{"position":[[256,2],[270,1],[278,1],[299,1],[481,1],[544,1],[592,1],[667,1],[781,1],[840,1],[1129,2],[1142,1],[1150,1],[1170,1],[1290,1],[1358,1],[1425,1],[1537,1]]},"129":{"position":[[428,1],[444,1],[566,1],[595,1],[1440,1],[1449,1],[1462,1],[1501,1],[1522,1],[1524,1],[1540,1],[1553,1],[1561,1],[1568,2],[1571,2],[1644,1],[1752,2],[1934,1],[1978,1],[2284,3],[2374,4],[2392,1],[2517,1],[2560,1],[2619,1]]},"133":{"position":[[328,1]]},"134":{"position":[[81,3]]},"136":{"position":[[221,3],[363,1],[373,1],[469,3],[492,1]]},"140":{"position":[[18,1],[41,1],[55,1]]},"141":{"position":[[18,1],[52,1],[76,1]]},"142":{"position":[[34,1],[47,1]]},"144":{"position":[[152,1],[213,1],[215,2],[251,2],[278,1],[290,1],[298,1],[323,2],[376,2],[425,1]]},"145":{"position":[[128,1],[148,1],[156,1],[181,2],[265,2],[325,2],[385,2],[447,3],[451,1]]},"146":{"position":[[156,1],[176,1],[178,2],[239,1],[283,2],[379,2],[438,2],[505,1]]},"147":{"position":[[263,1],[312,1],[324,1],[326,2],[389,2],[447,2],[501,2],[567,2],[654,1]]},"152":{"position":[[485,1],[487,2],[575,2],[633,2],[692,1],[719,1],[723,2],[730,2],[774,2],[832,2],[889,2],[944,1],[983,2],[986,2],[1041,2],[1104,1],[1116,1],[1126,1],[1173,1],[1219,1],[1311,1],[1370,1],[1407,1],[1453,1],[1476,1],[1537,1],[1574,1],[1622,1],[1653,1],[1655,1]]},"153":{"position":[[546,1],[562,1],[597,1],[621,1],[662,1],[681,1],[716,1],[741,1],[757,1],[759,2],[824,2],[888,2],[955,2],[1005,1],[1026,1]]},"155":{"position":[[1355,1],[1357,2],[1400,1],[1417,1],[1419,2],[1461,1],[1479,1],[1481,2],[1524,1],[1542,1],[1544,2],[1603,1]]},"156":{"position":[[639,1],[641,2],[694,1],[926,1],[928,2],[1016,2],[1069,1],[1092,2],[1145,2],[1209,1],[1256,1],[1302,1],[1394,1],[1453,1],[1490,1],[1536,1],[1559,1],[1620,1],[1657,1],[1705,1],[1736,1],[1738,1]]},"163":{"position":[[910,1],[974,1],[978,1],[991,1],[1004,1],[1006,1],[1070,1],[1074,1],[1095,1],[1097,1],[1099,1],[1101,1],[1103,1],[1105,1],[1107,1],[1109,1],[1111,1],[1113,1],[1115,1],[1117,1],[1119,1],[1121,1],[1123,1],[1125,1],[1127,1],[1129,1],[1131,1],[1133,1],[1135,1],[1137,1],[1139,1],[1141,1],[1143,1],[1145,1],[1147,1],[1149,1],[1151,1],[1153,1],[1155,1],[1157,1],[1159,1],[1161,1],[1165,1],[1180,1],[1182,1],[1184,1],[1186,1],[1188,1],[1190,1],[1192,1],[1194,1],[1196,1],[1198,1],[1200,1],[1202,1],[1204,1],[1206,1],[1208,1],[1210,1],[1212,1],[1214,1],[1216,1],[1218,1],[1220,1],[1222,1],[1224,1],[1226,1],[1228,1],[1230,1],[1232,1],[1234,1],[1236,1],[1238,1],[1240,1],[1242,1],[1244,1],[1246,1],[1251,1],[1270,1],[1272,1],[1274,1],[1276,1],[1278,1],[1280,1],[1282,1],[1284,1],[1286,1],[1288,1],[1290,1],[1292,1],[1294,1],[1296,1],[1298,1],[1300,1],[1302,1],[1304,1],[1306,1],[1308,1],[1310,1],[1312,1],[1314,1],[1316,1],[1318,1],[1320,1],[1322,1],[1324,1],[1326,1],[1328,1],[1330,1],[1332,1],[1334,1],[1336,1],[1341,1],[1359,1],[1361,1],[1363,1],[1365,1],[1367,1],[1369,1],[1371,1],[1373,1],[1375,1],[1377,1],[1379,1],[1381,1],[1383,1],[1385,1],[1387,1],[1389,1],[1391,1],[1393,1],[1395,1],[1397,1],[1399,1],[1401,1],[1403,1],[1405,1],[1407,1],[1409,1],[1411,1],[1413,1],[1415,1],[1417,1],[1419,1],[1421,1],[1423,1],[1425,1],[1430,1],[1445,1],[1447,1],[1449,1],[1451,1],[1453,1],[1455,1],[1457,1],[1459,1],[1461,1],[1463,1],[1465,1],[1467,1],[1469,1],[1471,1],[1473,1],[1475,1],[1477,1],[1479,1],[1481,1],[1483,1],[1485,1],[1487,1],[1489,1],[1491,1],[1493,1],[1495,1],[1497,1],[1499,1],[1501,1],[1503,1],[1505,1],[1507,1],[1509,1],[1511,1],[1516,1],[1529,1],[1531,1],[1533,1],[1535,1],[1537,1],[1539,1],[1541,1],[1543,1],[1545,1],[1547,1],[1549,1],[1551,1],[1553,1],[1555,1],[1557,1],[1559,1],[1561,1],[1563,1],[1565,1],[1567,1],[1569,1],[1571,1],[1573,1],[1575,1],[1577,1],[1579,1],[1581,1],[1583,1],[1585,1],[1587,1],[1589,1],[1591,1],[1593,1],[1595,1],[1597,1],[1611,1],[1613,1],[1615,3],[1619,1],[1709,1],[1826,1],[1832,1],[1845,1],[1941,2],[1944,1],[1946,1],[2067,1],[2130,1]]},"165":{"position":[[638,1],[656,1],[677,1],[699,1]]},"179":{"position":[[431,1],[433,2],[484,2],[563,1],[575,1],[586,1],[606,2],[686,2],[743,1],[887,1],[951,1],[971,1],[983,1],[985,2],[1089,2],[1167,1],[1266,1],[1291,1],[1293,2],[1400,2],[1457,2],[1517,2],[1607,1]]},"180":{"position":[[398,1],[456,1],[458,2],[501,1],[521,1]]},"181":{"position":[[90,1],[136,1],[138,2],[203,1],[212,1],[258,1],[260,2],[331,1],[340,1],[349,1]]},"183":{"position":[[315,1],[361,1],[363,2],[402,1],[452,1],[461,1],[507,1],[509,2],[548,1],[598,1],[607,1],[616,1]]},"184":{"position":[[164,1],[173,1],[202,1],[213,1],[215,2],[255,2],[283,2],[305,1],[321,1],[379,1],[523,1],[532,1],[548,1],[580,1],[591,1],[599,1],[601,1],[603,1],[632,1],[661,1],[728,1],[1022,2],[1144,1]]},"185":{"position":[[669,1],[701,1],[703,2],[818,1],[829,1],[856,2]]},"186":{"position":[[203,2],[319,1],[344,1],[346,2],[415,2],[499,2],[562,2],[664,1]]},"188":{"position":[[836,1],[904,1],[1067,1],[1074,1],[1081,1],[1087,1],[1091,1],[1120,1],[1126,1],[1132,1],[1136,1],[1184,1],[1257,1],[1318,1],[1378,1],[1555,1],[1651,1],[2025,1],[2063,1],[2104,1],[2142,1],[2185,1],[2431,1],[2474,1],[2914,1],[2969,1],[3010,1]]},"189":{"position":[[971,1],[1033,1],[1137,1],[1143,1],[1149,1],[1153,1],[1182,1],[1188,1],[1194,1],[1198,1],[1211,1],[1271,1],[1407,1],[1413,1],[1419,1],[1423,1],[1452,1],[1458,1],[1464,1],[1468,1],[1481,1],[1543,1],[1745,1],[2094,1],[2134,1],[2375,1],[2417,1],[2664,1],[2704,1]]},"192":{"position":[[128,1],[146,1],[160,1],[182,1],[203,1],[205,2],[259,2],[300,1],[308,1],[321,2],[324,2],[382,1],[390,1],[403,2],[406,2],[462,2],[527,1],[534,1],[556,2],[559,1]]},"193":{"position":[[919,1],[937,1],[939,2],[985,2],[1033,2],[1104,1],[1106,2],[1158,2],[1208,2],[1237,2],[1288,2],[1337,1],[1351,1],[1365,1],[1379,1],[1386,2],[1423,1],[1435,1],[1458,1],[1470,1],[1495,1],[1503,1],[1520,1],[1530,2],[1587,2],[1637,2],[1692,2],[1736,1],[1762,1],[1774,1],[1782,1],[1795,2],[1809,1],[1817,1],[1830,2],[1841,1],[1849,1],[1862,2],[1877,1],[1926,1],[1961,1],[2224,1],[2242,1],[2244,2],[2313,2],[2373,2],[2508,1],[2517,1],[2531,1],[2545,1],[2559,1],[2576,1],[2590,1],[2615,1],[2629,1],[2656,1],[2664,1],[2681,1],[2691,1],[2717,1],[2729,1],[2737,1],[2750,2],[2764,1],[2772,1],[2785,2],[2796,1],[2804,1],[2817,2],[2832,1],[2881,1],[2916,1],[3190,1],[3208,1],[3210,2],[3279,1],[3288,1],[3302,1],[3316,1],[3330,1],[3347,1],[3359,1],[3382,1],[3394,1],[3419,1],[3427,1],[3444,1],[3454,1],[3456,2],[3593,1],[3602,1],[3616,1],[3630,1],[3644,1],[3661,1],[3673,1],[3696,1],[3708,1],[3733,1],[3741,1],[3758,1],[3768,1]]},"194":{"position":[[231,1],[255,1],[273,1],[297,1],[321,1],[329,1],[355,1],[381,1],[392,1],[399,2],[410,1],[429,1]]},"195":{"position":[[177,2],[228,1],[244,1],[246,2],[294,1],[318,1],[320,2],[376,1],[395,1],[397,2],[462,2],[519,2],[608,1],[633,1],[645,1],[647,2],[697,2],[759,2],[821,1],[842,1]]},"196":{"position":[[970,1],[978,1],[984,2],[1041,2],[1100,2],[1129,2],[1132,1],[1137,1],[1139,1],[1160,1],[1188,1],[1549,1],[1557,1],[1576,1],[1599,1],[1751,1],[1759,1],[1778,1],[1801,1]]},"197":{"position":[[306,1],[341,1],[343,2],[400,1],[408,1],[435,1],[469,1],[485,1],[487,1],[489,2],[547,1],[556,1],[584,1],[618,1],[627,1],[629,1],[631,2],[691,2],[745,2],[809,2],[870,2],[968,1],[970,2],[1026,2],[1079,2],[1130,1],[1145,1],[1164,1],[1166,2],[1221,2],[1258,2],[1321,1],[1332,1],[1339,2],[1348,1],[1360,1],[1367,2],[1414,1]]},"198":{"position":[[1007,1],[1027,1],[1029,2],[1142,1],[1162,1]]},"199":{"position":[[151,1],[162,1],[167,2],[198,1],[228,1],[234,2],[246,1],[260,1],[315,1],[326,1],[331,2],[388,1],[396,1],[402,2],[408,1],[422,1],[1099,2],[1170,2],[1270,1],[1282,1],[1287,2],[1354,1],[1358,2],[1364,1],[1366,1],[1413,1],[1425,1],[1430,2],[1510,1],[1514,2],[1520,1],[1522,1],[1571,1],[1583,1],[1588,2],[1651,2],[1690,1],[1694,2],[1700,1],[1702,1]]}},"keywords":{}}],["0",{"_index":357,"title":{},"content":{"6":{"position":[[829,3]]},"8":{"position":[[110,4],[195,2]]},"9":{"position":[[664,1],[702,1],[769,1]]},"13":{"position":[[730,1]]},"14":{"position":[[1587,1]]},"15":{"position":[[956,1],[974,1]]},"20":{"position":[[1657,2],[1725,1]]},"22":{"position":[[1248,1],[1922,2]]},"24":{"position":[[1380,1],[1403,2],[1427,1],[1450,2],[1472,1],[1493,3],[1529,3]]},"25":{"position":[[1100,1],[1123,2],[1147,1],[1170,2],[1192,1],[1213,3],[1249,3]]},"30":{"position":[[5639,1]]},"34":{"position":[[1185,1]]},"43":{"position":[[757,1]]},"44":{"position":[[111,1],[499,1],[527,3],[546,3],[1118,2]]},"76":{"position":[[780,2],[1954,1],[1969,1],[2499,2],[2930,1],[3239,1]]},"85":{"position":[[273,3]]},"90":{"position":[[4847,2],[5001,1]]},"91":{"position":[[3103,3]]},"92":{"position":[[915,3]]},"103":{"position":[[678,3],[1100,3]]},"110":{"position":[[474,2]]},"128":{"position":[[734,1]]},"163":{"position":[[838,1],[846,1],[866,1],[886,1],[906,1],[976,1]]},"172":{"position":[[183,2]]},"188":{"position":[[1069,2],[1083,1],[1603,1],[1701,1],[3125,1],[3573,2],[3583,1]]},"189":{"position":[[1139,1],[1409,1],[2818,1],[3117,2],[3127,1]]},"192":{"position":[[313,2],[319,1]]},"197":{"position":[[1337,1],[1365,1]]},"199":{"position":[[164,2],[200,2],[328,2],[1284,2],[1427,2],[1585,2]]}},"keywords":{}}],["0.00044165797556096868",{"_index":734,"title":{},"content":{"18":{"position":[[338,23]]}},"keywords":{}}],["0.00093418904454400551",{"_index":732,"title":{},"content":{"18":{"position":[[276,23]]}},"keywords":{}}],["0.00098431254720448159",{"_index":733,"title":{},"content":{"18":{"position":[[307,23]]}},"keywords":{}}],["0.0010319531629488911",{"_index":731,"title":{},"content":{"18":{"position":[[246,22]]}},"keywords":{}}],["0.0016320202164526894",{"_index":730,"title":{},"content":{"18":{"position":[[216,22]]}},"keywords":{}}],["0.0053519259698605499",{"_index":759,"title":{},"content":{"19":{"position":[[561,22]]}},"keywords":{}}],["0.02",{"_index":2786,"title":{},"content":{"81":{"position":[[183,5]]}},"keywords":{}}],["0.022622210057414487",{"_index":757,"title":{},"content":{"19":{"position":[[502,21]]}},"keywords":{}}],["0.026950946344858676",{"_index":758,"title":{},"content":{"19":{"position":[[531,21]]}},"keywords":{}}],["0.027303529817677398",{"_index":756,"title":{},"content":{"19":{"position":[[473,21]]}},"keywords":{}}],["0.034774627850375328",{"_index":773,"title":{},"content":{"20":{"position":[[451,21]]}},"keywords":{}}],["0.035851524605672758",{"_index":774,"title":{},"content":{"20":{"position":[[480,21]]}},"keywords":{}}],["0.043551495607375035",{"_index":770,"title":{},"content":{"20":{"position":[[364,21]]}},"keywords":{}}],["0.043598",{"_index":1926,"title":{},"content":{"44":{"position":[[849,8]]}},"keywords":{}}],["0.044894389686214398",{"_index":771,"title":{},"content":{"20":{"position":[[393,21]]}},"keywords":{}}],["0.051424517867144637",{"_index":772,"title":{},"content":{"20":{"position":[[422,21]]}},"keywords":{}}],["0.08",{"_index":2782,"title":{},"content":{"79":{"position":[[182,5]]}},"keywords":{}}],["0.08304813163696423",{"_index":1669,"title":{},"content":{"34":{"position":[[3864,19]]}},"keywords":{}}],["0.09",{"_index":2783,"title":{},"content":{"80":{"position":[[204,5]]}},"keywords":{}}],["0.10578734457846127",{"_index":755,"title":{},"content":{"19":{"position":[[445,20]]}},"keywords":{}}],["0.180602",{"_index":1924,"title":{},"content":{"44":{"position":[[836,8]]}},"keywords":{}}],["0.2.17",{"_index":4152,"title":{},"content":{"125":{"position":[[7904,6]]}},"keywords":{}}],["0.2.21",{"_index":4151,"title":{},"content":{"125":{"position":[[7884,6]]}},"keywords":{}}],["0.30",{"_index":2779,"title":{},"content":{"78":{"position":[[978,5]]}},"keywords":{}}],["0.4.4",{"_index":3956,"title":{},"content":{"122":{"position":[[1219,5]]}},"keywords":{}}],["0.451493",{"_index":1155,"title":{},"content":{"25":{"position":[[2493,8]]}},"keywords":{}}],["0.455224",{"_index":1108,"title":{},"content":{"24":{"position":[[2770,8]]},"25":{"position":[[2484,8]]}},"keywords":{}}],["0.462687",{"_index":1107,"title":{},"content":{"24":{"position":[[2761,8]]}},"keywords":{}}],["0.464945",{"_index":1109,"title":{},"content":{"24":{"position":[[2779,8]]}},"keywords":{}}],["0.476015",{"_index":1110,"title":{},"content":{"24":{"position":[[2788,8]]}},"keywords":{}}],["0.483395",{"_index":1156,"title":{},"content":{"25":{"position":[[2502,8]]}},"keywords":{}}],["0.501845",{"_index":1151,"title":{},"content":{"25":{"position":[[2421,8]]}},"keywords":{}}],["0.512915",{"_index":1157,"title":{},"content":{"25":{"position":[[2511,8]]}},"keywords":{}}],["0.522388",{"_index":1100,"title":{},"content":{"24":{"position":[[2689,8]]}},"keywords":{}}],["0.529851",{"_index":1150,"title":{},"content":{"25":{"position":[[2412,8]]}},"keywords":{}}],["0.531365",{"_index":1160,"title":{},"content":{"25":{"position":[[2545,8]]}},"keywords":{}}],["0.533582",{"_index":1149,"title":{},"content":{"25":{"position":[[2403,8]]}},"keywords":{}}],["0.535055",{"_index":1154,"title":{},"content":{"25":{"position":[[2461,8],[2470,8],[2589,8],[2598,8]]}},"keywords":{}}],["0.538745",{"_index":1161,"title":{},"content":{"25":{"position":[[2554,8]]}},"keywords":{}}],["0.542435",{"_index":1152,"title":{},"content":{"25":{"position":[[2430,8]]}},"keywords":{}}],["0.544776",{"_index":1099,"title":{},"content":{"24":{"position":[[2680,8]]}},"keywords":{}}],["0.582090",{"_index":1158,"title":{},"content":{"25":{"position":[[2527,8]]}},"keywords":{}}],["0.585821",{"_index":1162,"title":{},"content":{"25":{"position":[[2571,8]]}},"keywords":{}}],["0.589552",{"_index":1153,"title":{},"content":{"25":{"position":[[2443,8]]}},"keywords":{}}],["0.590406",{"_index":1102,"title":{},"content":{"24":{"position":[[2707,8]]}},"keywords":{}}],["0.597015",{"_index":1115,"title":{},"content":{"24":{"position":[[2857,8]]}},"keywords":{}}],["0.601476",{"_index":1101,"title":{},"content":{"24":{"position":[[2698,8]]}},"keywords":{}}],["0.604478",{"_index":1104,"title":{},"content":{"24":{"position":[[2729,8],[2848,8]]}},"keywords":{}}],["0.608209",{"_index":1112,"title":{},"content":{"24":{"position":[[2813,8]]},"25":{"position":[[2452,8],[2580,8]]}},"keywords":{}}],["0.611940",{"_index":1103,"title":{},"content":{"24":{"position":[[2720,8]]}},"keywords":{}}],["0.615672",{"_index":1111,"title":{},"content":{"24":{"position":[[2804,8]]}},"keywords":{}}],["0.626866",{"_index":1159,"title":{},"content":{"25":{"position":[[2536,8]]}},"keywords":{}}],["0.6894803101560001",{"_index":1663,"title":{},"content":{"34":{"position":[[3472,18]]}},"keywords":{}}],["0.797048",{"_index":1113,"title":{},"content":{"24":{"position":[[2822,8]]}},"keywords":{}}],["0.804428",{"_index":1105,"title":{},"content":{"24":{"position":[[2738,8]]}},"keywords":{}}],["0.811808",{"_index":1116,"title":{},"content":{"24":{"position":[[2866,8]]}},"keywords":{}}],["0.830258",{"_index":1114,"title":{},"content":{"24":{"position":[[2831,8]]}},"keywords":{}}],["0.841328",{"_index":1106,"title":{},"content":{"24":{"position":[[2747,8]]}},"keywords":{}}],["0.848708",{"_index":1117,"title":{},"content":{"24":{"position":[[2875,8]]}},"keywords":{}}],["0.870236869207003",{"_index":2122,"title":{},"content":{"51":{"position":[[2116,17]]}},"keywords":{}}],["0.905159",{"_index":1922,"title":{},"content":{"44":{"position":[[823,8]]}},"keywords":{}}],["0.937329",{"_index":1927,"title":{},"content":{"44":{"position":[[862,8]]}},"keywords":{}}],["0.959372",{"_index":1928,"title":{},"content":{"44":{"position":[[875,8]]}},"keywords":{}}],["0.960837",{"_index":1930,"title":{},"content":{"44":{"position":[[888,8],[901,8]]}},"keywords":{}}],["0.9608561656706882",{"_index":1948,"title":{},"content":{"44":{"position":[[1646,18]]}},"keywords":{}}],["005",{"_index":3052,"title":{},"content":{"90":{"position":[[4403,6]]}},"keywords":{}}],["00:00:00",{"_index":2441,"title":{},"content":{"62":{"position":[[1634,8]]}},"keywords":{}}],["01",{"_index":2440,"title":{},"content":{"62":{"position":[[1628,2],[1631,2]]},"76":{"position":[[1256,3]]},"90":{"position":[[4311,5]]}},"keywords":{}}],["02",{"_index":3053,"title":{},"content":{"90":{"position":[[4416,5]]}},"keywords":{}}],["025",{"_index":3048,"title":{},"content":{"90":{"position":[[4324,6]]}},"keywords":{}}],["02f}s".format(end",{"_index":2759,"title":{},"content":{"78":{"position":[[382,25]]}},"keywords":{}}],["03",{"_index":2442,"title":{},"content":{"62":{"position":[[1651,2]]}},"keywords":{}}],["05",{"_index":807,"title":{},"content":{"20":{"position":[[1093,3]]},"90":{"position":[[4466,5],[4583,5],[4689,6]]}},"keywords":{}}],["055",{"_index":3059,"title":{},"content":{"90":{"position":[[4519,6]]}},"keywords":{}}],["05:13:42",{"_index":1501,"title":{},"content":{"30":{"position":[[10185,8]]}},"keywords":{}}],["05:30:51",{"_index":1503,"title":{},"content":{"30":{"position":[[10239,8]]}},"keywords":{}}],["05:48:30",{"_index":1504,"title":{},"content":{"30":{"position":[[10289,8]]}},"keywords":{}}],["06",{"_index":645,"title":{},"content":{"14":{"position":[[1427,3]]}},"keywords":{}}],["06:08:32",{"_index":1505,"title":{},"content":{"30":{"position":[[10340,8]]}},"keywords":{}}],["06:25:21",{"_index":1506,"title":{},"content":{"30":{"position":[[10378,8]]}},"keywords":{}}],["07",{"_index":562,"title":{},"content":{"13":{"position":[[597,3]]},"15":{"position":[[796,3]]},"90":{"position":[[4628,5]]}},"keywords":{}}],["085",{"_index":3060,"title":{},"content":{"90":{"position":[[4532,6]]}},"keywords":{}}],["0:.2f}%".format(expected_drawdown",{"_index":859,"title":{},"content":{"20":{"position":[[2692,41]]}},"keywords":{}}],["0:00:58.715714",{"_index":2038,"title":{},"content":{"46":{"position":[[682,14]]}},"keywords":{}}],["0:20:29",{"_index":3170,"title":{},"content":{"91":{"position":[[5292,7],[5306,7]]}},"keywords":{}}],["0:20:51",{"_index":3185,"title":{},"content":{"92":{"position":[[1813,7],[1827,7]]}},"keywords":{}}],["0:21:38",{"_index":3161,"title":{},"content":{"91":{"position":[[4482,7],[4496,7]]}},"keywords":{}}],["0:22:51",{"_index":3180,"title":{},"content":{"92":{"position":[[1255,7],[1269,7]]}},"keywords":{}}],["0:26:26",{"_index":3174,"title":{},"content":{"91":{"position":[[5675,7],[5689,7]]}},"keywords":{}}],["0:26:56",{"_index":3186,"title":{},"content":{"92":{"position":[[1972,7],[1986,7]]}},"keywords":{}}],["0:horizon*2+1",{"_index":3038,"title":{},"content":{"90":{"position":[[3903,16]]}},"keywords":{}}],["0x00",{"_index":4778,"title":{},"content":{"163":{"position":[[1718,5],[1724,5],[1730,6]]}},"keywords":{}}],["0x00000006",{"_index":4770,"title":{},"content":{"163":{"position":[[993,10]]}},"keywords":{}}],["0x00007f499effd700",{"_index":5208,"title":{},"content":{"188":{"position":[[3704,18]]}},"keywords":{}}],["0x06",{"_index":4777,"title":{},"content":{"163":{"position":[[1711,6]]}},"keywords":{}}],["0x18e59dc28d0>",{"_index":2115,"title":{},"content":{"51":{"position":[[1830,17]]}},"keywords":{}}],["0xab555145c708dad2",{"_index":3696,"title":{},"content":{"110":{"position":[[436,20]]}},"keywords":{}}],["1",{"_index":358,"title":{"44":{"position":[[29,1]]},"46":{"position":[[16,2]]},"70":{"position":[[10,2]]},"78":{"position":[[8,2]]},"91":{"position":[[11,2]]},"96":{"position":[[6,2]]},"108":{"position":[[5,2]]},"115":{"position":[[8,2]]},"140":{"position":[[8,2]]}},"content":{"6":{"position":[[868,1]]},"7":{"position":[[423,2]]},"9":{"position":[[452,2],[499,2],[745,1]]},"11":{"position":[[196,1],[434,1],[494,2]]},"12":{"position":[[392,1],[453,2]]},"13":{"position":[[1940,2]]},"14":{"position":[[708,2],[852,2],[1845,2],[1904,2],[3012,2]]},"15":{"position":[[353,2],[468,1],[1436,2],[1572,2],[2683,2]]},"20":{"position":[[216,1],[646,3],[1073,2],[1282,1],[1569,3],[1818,1],[1918,1]]},"22":{"position":[[1682,3],[1990,2],[2267,1]]},"24":{"position":[[1508,3]]},"25":{"position":[[1228,3]]},"28":{"position":[[1296,2],[1331,2],[1334,2],[3096,2],[3131,2],[3134,2]]},"30":{"position":[[1662,2],[1697,2],[1700,2],[3011,2],[3046,2],[3049,2],[4935,2],[4970,2],[4973,2],[5643,2],[6079,2],[6114,2],[6117,2],[9344,2]]},"32":{"position":[[1590,2],[1800,2],[1880,2]]},"33":{"position":[[919,3],[1213,2]]},"34":{"position":[[1258,1],[1872,1],[2348,1],[3148,2]]},"38":{"position":[[563,2],[934,1]]},"39":{"position":[[893,1],[1087,1],[1131,3],[1568,1],[1612,3],[1959,3],[2032,2],[3156,2],[3159,2],[3217,2],[3220,3]]},"40":{"position":[[2278,1],[3563,1]]},"43":{"position":[[583,2],[631,3],[728,1]]},"44":{"position":[[116,1],[501,2],[531,3]]},"45":{"position":[[1609,1],[2009,2]]},"52":{"position":[[1136,2]]},"61":{"position":[[1706,1]]},"62":{"position":[[142,2],[598,2],[601,2],[1395,3],[1572,3]]},"65":{"position":[[627,1],[695,2],[2340,2],[2343,2]]},"70":{"position":[[307,1],[481,1],[1025,1]]},"71":{"position":[[407,1],[581,1],[1400,1]]},"76":{"position":[[2462,1],[3266,1]]},"79":{"position":[[55,1]]},"80":{"position":[[48,1]]},"85":{"position":[[277,3],[290,4]]},"88":{"position":[[1458,3],[1480,3],[1787,3],[2849,3]]},"90":{"position":[[920,2],[979,2],[982,3],[1048,1],[1627,1],[1776,1],[2057,2],[2102,2],[2305,2],[2364,2],[2367,3],[2433,1],[2920,1],[3159,2],[4399,3],[4492,1],[4636,2],[4640,4]]},"91":{"position":[[3067,1],[3400,3],[4021,3]]},"92":{"position":[[879,1]]},"93":{"position":[[2180,2]]},"97":{"position":[[1774,2]]},"98":{"position":[[457,1]]},"105":{"position":[[1173,3],[1177,3],[1181,3],[1189,3],[1970,2],[2004,3],[2041,3],[2936,2]]},"109":{"position":[[425,1]]},"110":{"position":[[487,2]]},"111":{"position":[[404,1]]},"127":{"position":[[813,1]]},"129":{"position":[[2503,1]]},"163":{"position":[[840,1],[848,1],[868,1],[888,1],[908,1]]},"188":{"position":[[1034,2],[1076,2],[3623,2]]},"189":{"position":[[1123,2],[1145,1],[1393,2],[1415,1],[3154,2]]},"192":{"position":[[395,2]]},"193":{"position":[[1787,2],[2742,2]]}},"keywords":{}}],["1%the",{"_index":1588,"title":{},"content":{"33":{"position":[[1162,5]]}},"keywords":{}}],["1'",{"_index":1802,"title":{},"content":{"40":{"position":[[644,3]]}},"keywords":{}}],["1)*(t",{"_index":572,"title":{},"content":{"13":{"position":[[879,5]]},"14":{"position":[[1748,5],[2904,7]]},"15":{"position":[[1138,5],[2578,7]]}},"keywords":{}}],["1)*t",{"_index":600,"title":{},"content":{"13":{"position":[[1822,6]]}},"keywords":{}}],["1)\\cdot",{"_index":466,"title":{},"content":{"9":{"position":[[439,7]]}},"keywords":{}}],["1.0",{"_index":4483,"title":{},"content":{"148":{"position":[[325,3]]}},"keywords":{}}],["1.0.2",{"_index":4403,"title":{},"content":{"136":{"position":[[984,6]]}},"keywords":{}}],["1.0.3",{"_index":4405,"title":{},"content":{"136":{"position":[[1031,6]]}},"keywords":{}}],["1.0049",{"_index":506,"title":{},"content":{"10":{"position":[[592,7],[620,6]]}},"keywords":{}}],["1.01",{"_index":1660,"title":{},"content":{"34":{"position":[[3369,5]]},"39":{"position":[[3229,5]]}},"keywords":{}}],["1.02",{"_index":1667,"title":{},"content":{"34":{"position":[[3760,5]]},"39":{"position":[[2568,5]]}},"keywords":{}}],["1.21",{"_index":325,"title":{},"content":{"6":{"position":[[355,5],[842,5]]}},"keywords":{}}],["1.28",{"_index":4351,"title":{},"content":{"132":{"position":[[531,4]]}},"keywords":{}}],["1.31",{"_index":4482,"title":{},"content":{"148":{"position":[[262,4]]}},"keywords":{}}],["1.32",{"_index":4707,"title":{},"content":{"160":{"position":[[3761,5]]}},"keywords":{}}],["1.45",{"_index":326,"title":{},"content":{"6":{"position":[[361,5],[848,5]]}},"keywords":{}}],["1.69",{"_index":327,"title":{},"content":{"6":{"position":[[367,5],[854,5]]}},"keywords":{}}],["1.72",{"_index":2498,"title":{},"content":{"64":{"position":[[2070,4]]}},"keywords":{}}],["1.854949900247809",{"_index":1668,"title":{},"content":{"34":{"position":[[3820,17]]}},"keywords":{}}],["1.85x",{"_index":1670,"title":{},"content":{"34":{"position":[[3923,5]]}},"keywords":{}}],["1.94",{"_index":2807,"title":{},"content":{"82":{"position":[[982,5]]}},"keywords":{}}],["1/12",{"_index":2584,"title":{},"content":{"70":{"position":[[358,6],[378,6],[398,6],[418,4],[494,6],[514,6],[534,6],[554,6],[1043,5],[1049,5],[1055,5],[1061,5],[1072,6],[1079,5],[1085,5],[1091,5]]},"71":{"position":[[439,6],[459,6],[479,6],[499,6],[613,6],[633,6],[653,6],[673,6],[1221,5],[1227,5],[1233,5],[1239,5]]},"79":{"position":[[87,5],[93,5],[99,5],[105,5],[123,5],[129,5],[135,5],[141,5]]},"80":{"position":[[109,5],[115,5],[121,5],[127,5],[139,6],[146,5],[162,5],[168,6]]}},"keywords":{}}],["1/3",{"_index":2583,"title":{},"content":{"70":{"position":[[320,5],[339,5],[574,5],[593,3],[1032,5],[1038,4],[1097,4],[1102,4]]},"71":{"position":[[420,5],[519,3],[594,5],[693,3],[1215,5],[1245,4]]},"79":{"position":[[111,5],[117,5],[147,5]]},"80":{"position":[[133,5],[152,4],[157,4]]}},"keywords":{}}],["1/9",{"_index":2776,"title":{},"content":{"78":{"position":[[830,4],[835,4],[840,5],[862,4],[867,4],[872,5]]},"82":{"position":[[188,4],[193,4],[214,5],[220,4],[225,4]]}},"keywords":{}}],["1/`change`)^12",{"_index":2700,"title":{},"content":{"76":{"position":[[1185,15]]}},"keywords":{}}],["10",{"_index":1264,"title":{},"content":{"28":{"position":[[1948,4]]},"34":{"position":[[3186,2],[3375,3],[3766,3]]},"39":{"position":[[2574,3],[3235,3]]},"76":{"position":[[2492,3]]},"78":{"position":[[794,3]]},"91":{"position":[[968,6]]},"93":{"position":[[5085,2]]},"103":{"position":[[583,2],[624,2]]},"121":{"position":[[2318,2]]},"167":{"position":[[203,2]]}},"keywords":{}}],["10):datetime(2016",{"_index":3092,"title":{},"content":{"91":{"position":[[1026,18]]}},"keywords":{}}],["10,000",{"_index":2787,"title":{},"content":{"82":{"position":[[57,6]]}},"keywords":{}}],["10.0",{"_index":3225,"title":{},"content":{"93":{"position":[[2382,5]]}},"keywords":{}}],["10.5",{"_index":3465,"title":{},"content":{"101":{"position":[[72,4]]}},"keywords":{}}],["10.65",{"_index":4869,"title":{},"content":{"168":{"position":[[281,6]]}},"keywords":{}}],["100",{"_index":353,"title":{},"content":{"6":{"position":[[787,3],[802,3],[818,3],[862,3]]},"15":{"position":[[306,4]]},"20":{"position":[[2429,3],[2506,3],[2651,3]]},"22":{"position":[[1688,3]]},"23":{"position":[[158,4]]},"34":{"position":[[3088,3],[3364,4],[3755,4]]},"39":{"position":[[2563,4],[3224,4]]},"50":{"position":[[218,3]]},"91":{"position":[[4384,4],[5194,4],[5577,4]]},"92":{"position":[[1157,4],[1715,4],[1874,4]]},"121":{"position":[[2214,3]]}},"keywords":{}}],["100%coupon",{"_index":639,"title":{},"content":{"14":{"position":[[1259,10]]}},"keywords":{}}],["100.00",{"_index":621,"title":{},"content":{"13":{"position":[[2293,7]]}},"keywords":{}}],["100.09",{"_index":695,"title":{},"content":{"15":{"position":[[3031,7]]}},"keywords":{}}],["100.6",{"_index":362,"title":{},"content":{"6":{"position":[[907,5]]}},"keywords":{}}],["1000",{"_index":2777,"title":{},"content":{"78":{"position":[[892,5]]},"82":{"position":[[267,5]]},"181":{"position":[[92,5],[179,5],[306,5],[437,4]]},"183":{"position":[[317,5],[709,5]]}},"keywords":{}}],["1000*p",{"_index":1723,"title":{},"content":{"39":{"position":[[583,6]]}},"keywords":{}}],["10000",{"_index":2562,"title":{},"content":{"68":{"position":[[525,6],[565,6]]},"70":{"position":[[1127,6],[1154,6]]},"71":{"position":[[1278,6],[1305,6]]},"82":{"position":[[897,6]]}},"keywords":{}}],["100000",{"_index":371,"title":{},"content":{"6":{"position":[[1038,6]]}},"keywords":{}}],["1007n",{"_index":4889,"title":{},"content":{"169":{"position":[[425,6]]}},"keywords":{}}],["102.2",{"_index":320,"title":{},"content":{"6":{"position":[[298,6],[771,5]]}},"keywords":{}}],["1024",{"_index":3496,"title":{},"content":{"102":{"position":[[1009,4],[1238,4]]},"103":{"position":[[1174,4],[1778,5],[1784,5],[2101,5]]},"105":{"position":[[1245,6],[1258,6],[1271,6],[1317,6],[2238,5],[2279,5],[2321,5],[2481,6]]}},"keywords":{}}],["103.2805",{"_index":606,"title":{},"content":{"13":{"position":[[1943,10]]}},"keywords":{}}],["103.3260",{"_index":616,"title":{},"content":{"13":{"position":[[2167,10]]}},"keywords":{}}],["103.37421610015554",{"_index":618,"title":{},"content":{"13":{"position":[[2226,18]]}},"keywords":{}}],["103.3796",{"_index":609,"title":{},"content":{"13":{"position":[[1999,10]]}},"keywords":{}}],["103.4099",{"_index":614,"title":{},"content":{"13":{"position":[[2111,10]]}},"keywords":{}}],["103.4752",{"_index":611,"title":{},"content":{"13":{"position":[[2055,10]]}},"keywords":{}}],["105.9959",{"_index":656,"title":{},"content":{"14":{"position":[[3127,10]]}},"keywords":{}}],["106.0071",{"_index":654,"title":{},"content":{"14":{"position":[[3071,10]]}},"keywords":{}}],["106.0168",{"_index":660,"title":{},"content":{"14":{"position":[[3239,10]]}},"keywords":{}}],["106.02850857209883",{"_index":662,"title":{},"content":{"14":{"position":[[3298,18]]}},"keywords":{}}],["106.0562",{"_index":652,"title":{},"content":{"14":{"position":[[3015,10]]}},"keywords":{}}],["106.0665",{"_index":658,"title":{},"content":{"14":{"position":[[3183,10]]}},"keywords":{}}],["108.8087",{"_index":692,"title":{},"content":{"15":{"position":[[2910,10]]}},"keywords":{}}],["108.8612",{"_index":684,"title":{},"content":{"15":{"position":[[2686,10]]}},"keywords":{}}],["108.91052564051816",{"_index":694,"title":{},"content":{"15":{"position":[[2969,18]]}},"keywords":{}}],["108.9175",{"_index":688,"title":{},"content":{"15":{"position":[[2798,10]]}},"keywords":{}}],["108.9426",{"_index":690,"title":{},"content":{"15":{"position":[[2854,10]]}},"keywords":{}}],["109.0226",{"_index":686,"title":{},"content":{"15":{"position":[[2742,10]]}},"keywords":{}}],["10th",{"_index":3487,"title":{},"content":{"101":{"position":[[1046,4]]}},"keywords":{}}],["11",{"_index":1266,"title":{},"content":{"28":{"position":[[1966,3]]},"30":{"position":[[9371,3]]},"34":{"position":[[3355,3],[3746,3]]},"74":{"position":[[389,2],[667,4]]},"90":{"position":[[3368,2]]}},"keywords":{}}],["111",{"_index":1907,"title":{},"content":{"44":{"position":[[312,3],[331,3]]},"45":{"position":[[355,4]]}},"keywords":{}}],["111.000000",{"_index":1921,"title":{},"content":{"44":{"position":[[807,10]]}},"keywords":{}}],["116n",{"_index":4891,"title":{},"content":{"169":{"position":[[442,5]]}},"keywords":{}}],["12",{"_index":422,"title":{},"content":{"7":{"position":[[892,2]]},"28":{"position":[[1299,4],[1337,4],[3099,4],[3137,4]]},"30":{"position":[[1390,3],[1665,4],[1703,4],[3014,4],[3052,4],[4938,4],[4976,4],[6082,4],[6120,4],[9109,2],[9347,4],[9379,4]]},"68":{"position":[[789,2]]},"71":{"position":[[1485,2]]},"74":{"position":[[421,3],[689,2]]},"85":{"position":[[345,2],[422,2]]},"88":{"position":[[1552,5],[1879,5],[2999,5],[3388,5]]},"91":{"position":[[764,5],[1230,5]]},"113":{"position":[[2363,4]]},"115":{"position":[[768,4]]},"116":{"position":[[788,4]]},"117":{"position":[[1810,4]]},"163":{"position":[[1248,2]]}},"keywords":{}}],["12.32",{"_index":4886,"title":{},"content":{"169":{"position":[[394,6]]}},"keywords":{}}],["12.366942",{"_index":3643,"title":{},"content":{"105":{"position":[[2429,9]]}},"keywords":{}}],["1216n",{"_index":4880,"title":{},"content":{"169":{"position":[[333,6]]}},"keywords":{}}],["122.332071",{"_index":1458,"title":{},"content":{"30":{"position":[[8560,11]]}},"keywords":{}}],["124.5",{"_index":866,"title":{},"content":{"20":{"position":[[2895,7]]}},"keywords":{}}],["128",{"_index":3599,"title":{},"content":{"105":{"position":[[1239,5],[1278,5],[2232,5],[2357,5]]}},"keywords":{}}],["128934900",{"_index":2505,"title":{},"content":{"65":{"position":[[718,9]]}},"keywords":{}}],["13",{"_index":2513,"title":{},"content":{"65":{"position":[[1130,2],[1208,2]]},"78":{"position":[[444,3]]}},"keywords":{}}],["138.108597",{"_index":3619,"title":{},"content":{"105":{"position":[[1983,10]]}},"keywords":{}}],["14",{"_index":3516,"title":{},"content":{"103":{"position":[[578,2]]},"113":{"position":[[2401,4]]},"115":{"position":[[806,4]]},"116":{"position":[[826,4]]},"117":{"position":[[1846,4]]},"179":{"position":[[700,2]]}},"keywords":{}}],["14.31",{"_index":4873,"title":{},"content":{"168":{"position":[[320,6]]}},"keywords":{}}],["14.80",{"_index":4865,"title":{},"content":{"168":{"position":[[233,6]]}},"keywords":{}}],["14.86",{"_index":363,"title":{},"content":{"6":{"position":[[919,5]]}},"keywords":{}}],["140",{"_index":2139,"title":{},"content":{"51":{"position":[[3004,3]]},"52":{"position":[[747,3]]}},"keywords":{}}],["15",{"_index":2922,"title":{},"content":{"88":{"position":[[2871,4]]},"121":{"position":[[2321,2]]}},"keywords":{}}],["15.37",{"_index":356,"title":{},"content":{"6":{"position":[[810,5]]}},"keywords":{}}],["15.62",{"_index":340,"title":{},"content":{"6":{"position":[[558,6]]}},"keywords":{}}],["150",{"_index":3918,"title":{},"content":{"121":{"position":[[2202,3]]}},"keywords":{}}],["1500",{"_index":3273,"title":{},"content":{"93":{"position":[[4545,4]]}},"keywords":{}}],["1535n",{"_index":4875,"title":{},"content":{"168":{"position":[[336,6]]}},"keywords":{}}],["1583n",{"_index":4885,"title":{},"content":{"169":{"position":[[387,6]]}},"keywords":{}}],["16",{"_index":2504,"title":{},"content":{"65":{"position":[[667,2],[689,3]]},"105":{"position":[[573,2],[1206,4],[2115,4],[2735,3]]},"128":{"position":[[478,2]]},"163":{"position":[[1338,2]]},"192":{"position":[[240,2],[353,2]]}},"keywords":{}}],["16.431797",{"_index":3620,"title":{},"content":{"105":{"position":[[1994,9]]}},"keywords":{}}],["16.715032",{"_index":3625,"title":{},"content":{"105":{"position":[[2068,9]]}},"keywords":{}}],["1640",{"_index":4579,"title":{},"content":{"155":{"position":[[1382,4]]}},"keywords":{}}],["1650",{"_index":4582,"title":{},"content":{"155":{"position":[[1444,4]]}},"keywords":{}}],["1660",{"_index":4585,"title":{},"content":{"155":{"position":[[1506,4]]}},"keywords":{}}],["1672",{"_index":4588,"title":{},"content":{"155":{"position":[[1569,4]]}},"keywords":{}}],["16mmm",{"_index":2502,"title":{},"content":{"65":{"position":[[598,6]]}},"keywords":{}}],["17",{"_index":2146,"title":{},"content":{"51":{"position":[[3310,3]]}},"keywords":{}}],["17.097543",{"_index":3635,"title":{},"content":{"105":{"position":[[2222,9]]}},"keywords":{}}],["17.263611",{"_index":3627,"title":{},"content":{"105":{"position":[[2096,9]]}},"keywords":{}}],["17.263672",{"_index":3632,"title":{},"content":{"105":{"position":[[2173,9],[2254,9]]}},"keywords":{}}],["17.265625",{"_index":3642,"title":{},"content":{"105":{"position":[[2419,9]]}},"keywords":{}}],["1724195340",{"_index":2495,"title":{},"content":{"64":{"position":[[1933,10]]}},"keywords":{}}],["173n",{"_index":4887,"title":{},"content":{"169":{"position":[[413,5]]}},"keywords":{}}],["1751n",{"_index":4863,"title":{},"content":{"168":{"position":[[219,6]]}},"keywords":{}}],["18",{"_index":2923,"title":{},"content":{"88":{"position":[[2919,4]]},"91":{"position":[[518,6]]},"97":{"position":[[5055,2]]}},"keywords":{}}],["18):datetime(2016",{"_index":3080,"title":{},"content":{"91":{"position":[[570,18]]}},"keywords":{}}],["18.870387",{"_index":3637,"title":{},"content":{"105":{"position":[[2305,9]]}},"keywords":{}}],["18.92",{"_index":4882,"title":{},"content":{"169":{"position":[[347,6]]}},"keywords":{}}],["1828n",{"_index":4867,"title":{},"content":{"168":{"position":[[267,6]]}},"keywords":{}}],["18:20",{"_index":4962,"title":{},"content":{"173":{"position":[[1301,7]]}},"keywords":{}}],["1992",{"_index":2452,"title":{},"content":{"64":{"position":[[240,5],[408,4],[1103,4],[1363,5]]}},"keywords":{}}],["1:m",{"_index":433,"title":{},"content":{"7":{"position":[[1168,3]]}},"keywords":{}}],["1].count",{"_index":1937,"title":{},"content":{"44":{"position":[[1345,10]]}},"keywords":{}}],["1]['close",{"_index":1034,"title":{},"content":{"24":{"position":[[644,11]]}},"keywords":{}}],["1st",{"_index":2445,"title":{},"content":{"62":{"position":[[1747,3]]},"64":{"position":[[235,4],[2044,3]]},"65":{"position":[[2173,3]]}},"keywords":{}}],["1}(d_i",{"_index":1546,"title":{},"content":{"32":{"position":[[1717,6]]}},"keywords":{}}],["1}d_i",{"_index":1544,"title":{},"content":{"32":{"position":[[1654,5]]}},"keywords":{}}],["1ω=1sω≥sd⋅∣ω∣≤d∣ω∣≤l",{"_index":791,"title":{},"content":{"20":{"position":[[773,25]]}},"keywords":{}}],["1⃗ω=1s⃗ω≥sd⃗⋅∣ω∣≤d∣ω∣≤l\\begin{align",{"_index":777,"title":{},"content":{"20":{"position":[[545,37]]}},"keywords":{}}],["1−p1",{"_index":1973,"title":{},"content":{"45":{"position":[[765,4]]}},"keywords":{}}],["2",{"_index":608,"title":{"45":{"position":[[29,1]]},"61":{"position":[[15,2]]},"71":{"position":[[10,2]]},"79":{"position":[[8,2]]},"92":{"position":[[11,2]]},"97":{"position":[[6,2]]},"109":{"position":[[5,2]]},"116":{"position":[[8,2]]},"141":{"position":[[8,2]]}},"content":{"13":{"position":[[1996,2]]},"14":{"position":[[963,2],[3068,2]]},"15":{"position":[[414,2],[474,1],[2739,2]]},"22":{"position":[[2062,2]]},"34":{"position":[[3668,2]]},"44":{"position":[[275,2]]},"52":{"position":[[1124,2]]},"61":{"position":[[41,1]]},"64":{"position":[[876,2]]},"65":{"position":[[1721,2],[2471,2]]},"68":{"position":[[795,2]]},"70":{"position":[[326,1],[501,1]]},"71":{"position":[[426,1],[600,1],[1479,1]]},"74":{"position":[[411,1],[612,3]]},"76":{"position":[[1307,2],[1357,2]]},"88":{"position":[[2706,2]]},"90":{"position":[[772,1],[925,2],[1337,2],[2157,1],[2310,2]]},"91":{"position":[[435,2]]},"97":{"position":[[1781,2]]},"105":{"position":[[1185,3],[2008,2]]},"109":{"position":[[468,1]]},"111":{"position":[[447,1]]},"136":{"position":[[959,1]]},"163":{"position":[[842,1],[850,1],[870,1],[890,1]]},"192":{"position":[[401,1]]},"193":{"position":[[1793,1],[2748,1]]}},"keywords":{}}],["2**20",{"_index":3589,"title":{},"content":{"105":{"position":[[887,7],[1140,7],[1599,7]]}},"keywords":{}}],["2.21",{"_index":2328,"title":{},"content":{"58":{"position":[[236,4]]}},"keywords":{}}],["2.5",{"_index":2305,"title":{"57":{"position":[[0,3]]}},"content":{"57":{"position":[[669,3]]},"58":{"position":[[155,3],[381,3]]},"64":{"position":[[48,3]]},"70":{"position":[[638,3]]},"90":{"position":[[4526,5]]}},"keywords":{}}],["2.7",{"_index":364,"title":{},"content":{"6":{"position":[[931,3]]}},"keywords":{}}],["2.84",{"_index":355,"title":{},"content":{"6":{"position":[[795,4]]}},"keywords":{}}],["2.84%rrr",{"_index":322,"title":{},"content":{"6":{"position":[[334,8]]}},"keywords":{}}],["2/2)*t",{"_index":399,"title":{},"content":{"7":{"position":[[466,9]]}},"keywords":{}}],["2/9",{"_index":2775,"title":{},"content":{"78":{"position":[[820,4],[825,4],[846,5],[852,4],[857,4]]},"82":{"position":[[198,4],[203,4],[208,5],[230,4],[235,4],[240,5]]}},"keywords":{}}],["20",{"_index":908,"title":{},"content":{"22":{"position":[[760,4]]},"45":{"position":[[1613,2],[1685,2]]},"53":{"position":[[145,4]]},"105":{"position":[[2591,2]]},"163":{"position":[[1427,2]]},"189":{"position":[[1883,4]]}},"keywords":{}}],["200",{"_index":452,"title":{},"content":{"8":{"position":[[206,4]]}},"keywords":{}}],["2000",{"_index":996,"title":{},"content":{"23":{"position":[[141,5]]},"24":{"position":[[3067,4],[3378,5]]},"82":{"position":[[337,5]]}},"keywords":{}}],["2012",{"_index":1374,"title":{},"content":{"30":{"position":[[2533,4]]}},"keywords":{}}],["2013",{"_index":1282,"title":{},"content":{"28":{"position":[[2424,4],[4037,4]]}},"keywords":{}}],["2015",{"_index":1364,"title":{},"content":{"30":{"position":[[2115,6],[3601,6],[3808,6],[4219,4],[4375,4],[5374,6],[6674,6],[6887,6],[7165,5]]},"40":{"position":[[1090,4],[1250,5]]}},"keywords":{}}],["2016",{"_index":1256,"title":{},"content":{"28":{"position":[[1780,5]]},"30":{"position":[[1366,5]]},"62":{"position":[[145,4],[168,5],[1623,4],[1646,4]]},"64":{"position":[[425,4],[1120,4],[2048,5]]},"65":{"position":[[759,4],[1251,4]]}},"keywords":{}}],["2048",{"_index":3601,"title":{},"content":{"105":{"position":[[1284,6],[1297,6],[1310,6],[1324,5],[2363,5],[2403,5],[2445,5],[2488,5]]}},"keywords":{}}],["2068",{"_index":2515,"title":{},"content":{"65":{"position":[[1271,5],[1403,4],[1932,5],[2074,5]]}},"keywords":{}}],["2070",{"_index":2528,"title":{},"content":{"65":{"position":[[2177,5],[2536,4]]}},"keywords":{}}],["2083",{"_index":1946,"title":{},"content":{"44":{"position":[[1619,4]]}},"keywords":{}}],["21",{"_index":2003,"title":{},"content":{"45":{"position":[[2196,3],[2976,3]]},"193":{"position":[[3518,2]]}},"keywords":{}}],["2185n",{"_index":4871,"title":{},"content":{"168":{"position":[[306,6]]}},"keywords":{}}],["22",{"_index":5100,"title":{},"content":{"181":{"position":[[282,2]]},"193":{"position":[[3525,2]]}},"keywords":{}}],["22147.004400281654",{"_index":2778,"title":{},"content":{"78":{"position":[[933,18]]}},"keywords":{}}],["229",{"_index":5302,"title":{},"content":{"193":{"position":[[2351,3]]}},"keywords":{}}],["23",{"_index":2534,"title":{},"content":{"65":{"position":[[2474,3]]}},"keywords":{}}],["23:59:00",{"_index":2443,"title":{},"content":{"62":{"position":[[1657,9]]}},"keywords":{}}],["23rd",{"_index":2538,"title":{},"content":{"65":{"position":[[2530,5]]}},"keywords":{}}],["24",{"_index":4282,"title":{},"content":{"129":{"position":[[536,2],[728,2],[1936,2]]},"152":{"position":[[664,2]]},"163":{"position":[[1513,2]]},"184":{"position":[[307,3],[596,2]]},"196":{"position":[[980,3]]}},"keywords":{}}],["24.736506",{"_index":3645,"title":{},"content":{"105":{"position":[[2471,9]]}},"keywords":{}}],["2423n",{"_index":4876,"title":{},"content":{"168":{"position":[[343,6]]}},"keywords":{}}],["25",{"_index":451,"title":{},"content":{"8":{"position":[[201,4],[234,4]]},"30":{"position":[[5984,4],[6350,3]]},"34":{"position":[[3853,2],[3962,2]]},"44":{"position":[[858,3]]},"179":{"position":[[620,2],[1006,2],[1119,2]]},"196":{"position":[[1214,2]]}},"keywords":{}}],["250",{"_index":368,"title":{},"content":{"6":{"position":[[1007,3]]},"20":{"position":[[1108,3]]},"82":{"position":[[114,3]]}},"keywords":{}}],["2500000000",{"_index":2310,"title":{},"content":{"57":{"position":[[167,10]]}},"keywords":{}}],["251",{"_index":5241,"title":{},"content":{"189":{"position":[[1824,3]]}},"keywords":{}}],["253",{"_index":5239,"title":{},"content":{"189":{"position":[[1778,3],[1806,3]]}},"keywords":{}}],["256",{"_index":3597,"title":{},"content":{"105":{"position":[[1211,5],[1222,5],[1233,5],[1252,5],[1291,5],[2120,4],[2158,4],[2197,4],[2273,5],[2397,5],[2739,4],[3212,4]]},"195":{"position":[[180,3],[323,3]]}},"keywords":{}}],["258",{"_index":5240,"title":{},"content":{"189":{"position":[[1791,3]]}},"keywords":{}}],["2599n",{"_index":4881,"title":{},"content":{"169":{"position":[[340,6]]}},"keywords":{}}],["26",{"_index":2879,"title":{},"content":{"88":{"position":[[1548,3],[2942,4],[2995,3]]},"91":{"position":[[1048,4],[1226,3]]}},"keywords":{}}],["268",{"_index":1095,"title":{},"content":{"24":{"position":[[2528,3],[2532,3],[2548,3],[2552,3],[2569,3],[2573,3],[2592,3],[2596,3],[2616,3],[2620,3]]},"25":{"position":[[2251,3],[2255,3],[2271,3],[2275,3],[2292,3],[2296,3],[2315,3],[2319,3],[2339,3],[2343,3]]}},"keywords":{}}],["27",{"_index":2892,"title":{},"content":{"88":{"position":[[1875,3],[3269,4],[3384,3]]},"90":{"position":[[4060,3]]},"91":{"position":[[592,4],[760,3]]}},"keywords":{}}],["271",{"_index":1096,"title":{},"content":{"24":{"position":[[2536,3],[2540,3],[2556,3],[2560,3],[2577,3],[2581,3],[2600,3],[2604,3],[2624,3],[2628,3]]},"25":{"position":[[2259,3],[2263,3],[2279,3],[2283,3],[2300,3],[2304,3],[2323,3],[2327,3],[2347,3],[2351,3]]}},"keywords":{}}],["273n",{"_index":4866,"title":{},"content":{"168":{"position":[[261,5]]}},"keywords":{}}],["279",{"_index":5252,"title":{},"content":{"189":{"position":[[2563,3]]}},"keywords":{}}],["28",{"_index":2535,"title":{},"content":{"65":{"position":[[2481,3]]},"88":{"position":[[3313,4]]}},"keywords":{}}],["2836n",{"_index":4868,"title":{},"content":{"168":{"position":[[274,6]]}},"keywords":{}}],["286n",{"_index":4892,"title":{},"content":{"169":{"position":[[448,5]]}},"keywords":{}}],["29",{"_index":1659,"title":{},"content":{"34":{"position":[[3359,4],[3750,4]]},"181":{"position":[[289,2]]}},"keywords":{}}],["29)]['value'].sum",{"_index":2470,"title":{},"content":{"64":{"position":[[910,19]]},"65":{"position":[[1755,19]]}},"keywords":{}}],["2943n",{"_index":4864,"title":{},"content":{"168":{"position":[[226,6]]}},"keywords":{}}],["2f",{"_index":602,"title":{},"content":{"13":{"position":[[1873,7]]}},"keywords":{}}],["2f"",{"_index":604,"title":{},"content":{"13":{"position":[[1891,13]]},"14":{"position":[[2972,13]]},"15":{"position":[[2643,13]]}},"keywords":{}}],["2fs"",{"_index":538,"title":{},"content":{"12":{"position":[[626,12]]}},"keywords":{}}],["2fs\\n"",{"_index":592,"title":{},"content":{"13":{"position":[[1613,14]]},"14":{"position":[[2696,14]]},"15":{"position":[[2370,14]]}},"keywords":{}}],["2x",{"_index":1701,"title":{},"content":{"38":{"position":[[975,2]]}},"keywords":{}}],["3",{"_index":418,"title":{"80":{"position":[[8,2]]},"110":{"position":[[5,2]]},"117":{"position":[[8,2]]},"142":{"position":[[8,2]]}},"content":{"7":{"position":[[827,2]]},"13":{"position":[[2052,2]]},"14":{"position":[[1045,2],[1166,2],[3124,2]]},"15":{"position":[[2795,2]]},"22":{"position":[[2133,2]]},"24":{"position":[[389,1]]},"26":{"position":[[181,1]]},"38":{"position":[[983,1],[1110,1]]},"44":{"position":[[550,3]]},"53":{"position":[[450,1]]},"57":{"position":[[569,1]]},"58":{"position":[[726,1]]},"62":{"position":[[630,2]]},"63":{"position":[[71,1]]},"64":{"position":[[287,1]]},"66":{"position":[[240,1]]},"70":{"position":[[345,1],[521,1]]},"71":{"position":[[446,1],[620,1]]},"74":{"position":[[630,3]]},"80":{"position":[[77,1]]},"88":{"position":[[1455,2],[1784,2],[2846,2],[3243,2]]},"91":{"position":[[5009,1],[5522,1],[5728,1],[5906,1]]},"92":{"position":[[1603,1]]},"96":{"position":[[119,1]]},"163":{"position":[[844,1],[852,1],[872,1],[892,1]]},"193":{"position":[[1822,2],[2777,2]]}},"keywords":{}}],["3.4",{"_index":2329,"title":{},"content":{"58":{"position":[[252,3]]}},"keywords":{}}],["3.5",{"_index":2608,"title":{},"content":{"71":{"position":[[738,3],[766,3]]}},"keywords":{}}],["3.91",{"_index":4877,"title":{},"content":{"168":{"position":[[350,5]]}},"keywords":{}}],["3.96",{"_index":5246,"title":{},"content":{"189":{"position":[[2246,4]]}},"keywords":{}}],["3/1/2016",{"_index":2886,"title":{},"content":{"88":{"position":[[1677,8]]}},"keywords":{}}],["3/5/2016",{"_index":2894,"title":{},"content":{"88":{"position":[[1984,8]]}},"keywords":{}}],["30",{"_index":718,"title":{},"content":{"17":{"position":[[233,2]]},"30":{"position":[[9375,3]]},"88":{"position":[[3246,4]]},"123":{"position":[[679,2]]}},"keywords":{}}],["300",{"_index":3176,"title":{},"content":{"91":{"position":[[5823,5]]}},"keywords":{}}],["3000",{"_index":2792,"title":{},"content":{"82":{"position":[[407,5]]},"93":{"position":[[1223,4],[2943,4],[3082,4]]}},"keywords":{}}],["300kb",{"_index":4404,"title":{},"content":{"136":{"position":[[1014,5]]}},"keywords":{}}],["306",{"_index":5303,"title":{},"content":{"193":{"position":[[2379,3]]}},"keywords":{}}],["31",{"_index":2395,"title":{},"content":{"62":{"position":[[164,3],[633,3],[1654,2]]},"115":{"position":[[1121,2],[1468,2],[1751,2],[2209,2]]}},"keywords":{}}],["31st",{"_index":2446,"title":{},"content":{"62":{"position":[[1765,5]]}},"keywords":{}}],["32",{"_index":3545,"title":{},"content":{"103":{"position":[[2097,3]]},"105":{"position":[[726,2],[1201,4],[1217,4],[2082,3],[2153,4]]},"153":{"position":[[558,3],[617,3],[677,3],[737,3]]},"192":{"position":[[500,2]]},"195":{"position":[[240,3],[314,3],[391,3],[629,3]]}},"keywords":{}}],["32.375",{"_index":869,"title":{},"content":{"20":{"position":[[2985,8]]}},"keywords":{}}],["32.981380",{"_index":3622,"title":{},"content":{"105":{"position":[[2031,9]]}},"keywords":{}}],["33",{"_index":2144,"title":{},"content":{"51":{"position":[[3297,3],[3351,4]]},"116":{"position":[[1073,2],[1373,2],[1656,2],[2067,2]]}},"keywords":{}}],["34.527161",{"_index":3624,"title":{},"content":{"105":{"position":[[2058,9]]}},"keywords":{}}],["34.527344",{"_index":3634,"title":{},"content":{"105":{"position":[[2212,9],[2295,9]]}},"keywords":{}}],["34.531250",{"_index":3644,"title":{},"content":{"105":{"position":[[2461,9]]}},"keywords":{}}],["3497n",{"_index":4872,"title":{},"content":{"168":{"position":[[313,6]]}},"keywords":{}}],["35.79154",{"_index":1451,"title":{},"content":{"30":{"position":[[8481,10]]}},"keywords":{}}],["355n",{"_index":4870,"title":{},"content":{"168":{"position":[[300,5]]}},"keywords":{}}],["358",{"_index":5193,"title":{},"content":{"188":{"position":[[2620,3]]}},"keywords":{}}],["36.790387773552119",{"_index":867,"title":{},"content":{"20":{"position":[[2911,20]]}},"keywords":{}}],["365",{"_index":5172,"title":{},"content":{"188":{"position":[[1590,3],[1616,3]]}},"keywords":{}}],["366n",{"_index":4883,"title":{},"content":{"169":{"position":[[375,5]]}},"keywords":{}}],["369",{"_index":1877,"title":{},"content":{"43":{"position":[[668,3],[1128,3]]},"45":{"position":[[348,3]]}},"keywords":{}}],["36:6",{"_index":3776,"title":{},"content":{"115":{"position":[[1037,4],[1384,4],[2125,4]]}},"keywords":{}}],["37.800940",{"_index":3638,"title":{},"content":{"105":{"position":[[2347,9]]}},"keywords":{}}],["372",{"_index":5176,"title":{},"content":{"188":{"position":[[1634,3],[2587,3]]}},"keywords":{}}],["381",{"_index":5178,"title":{},"content":{"188":{"position":[[1688,3],[1714,3]]}},"keywords":{}}],["388",{"_index":5179,"title":{},"content":{"188":{"position":[[1732,3]]}},"keywords":{}}],["39",{"_index":5212,"title":{},"content":{"188":{"position":[[3869,2]]}},"keywords":{}}],["39.940753336615096)]"",{"_index":868,"title":{},"content":{"20":{"position":[[2940,26]]}},"keywords":{}}],["3f}%".format(expected_return",{"_index":856,"title":{},"content":{"20":{"position":[[2541,38]]}},"keywords":{}}],["4",{"_index":613,"title":{"81":{"position":[[8,2]]},"111":{"position":[[5,2]]}},"content":{"13":{"position":[[2108,2]]},"14":{"position":[[3180,2]]},"15":{"position":[[2851,2]]},"22":{"position":[[2203,2]]},"23":{"position":[[66,1]]},"28":{"position":[[1086,3]]},"65":{"position":[[311,1],[789,1],[1051,1],[1160,1]]},"70":{"position":[[365,1],[541,1]]},"71":{"position":[[466,1],[640,1]]},"80":{"position":[[83,2]]},"88":{"position":[[1545,2],[1872,2],[2868,2],[2916,2],[2939,2],[2992,2],[3266,2],[3310,2],[3381,2]]},"91":{"position":[[515,2],[567,2],[589,2],[757,2],[965,2],[1023,2],[1045,2],[1223,2]]},"97":{"position":[[1802,1]]},"105":{"position":[[744,1],[1193,3],[1197,3],[2045,2],[2078,3],[2939,2]]},"115":{"position":[[2469,1]]},"116":{"position":[[2327,1]]},"128":{"position":[[538,3],[651,2],[885,3],[1535,1],[1618,1]]},"163":{"position":[[854,1],[874,1],[894,1],[1072,1],[1706,2]]},"181":{"position":[[159,1]]},"193":{"position":[[1828,1],[2783,1]]}},"keywords":{}}],["4%bless",{"_index":1961,"title":{},"content":{"45":{"position":[[188,11]]}},"keywords":{}}],["4.05",{"_index":4894,"title":{},"content":{"169":{"position":[[460,5]]}},"keywords":{}}],["4.274846",{"_index":3631,"title":{},"content":{"105":{"position":[[2144,8]]}},"keywords":{}}],["4.34",{"_index":870,"title":{},"content":{"20":{"position":[[3018,6]]}},"keywords":{}}],["4.5",{"_index":2589,"title":{},"content":{"70":{"position":[[666,3]]},"90":{"position":[[4319,4]]}},"keywords":{}}],["40",{"_index":3044,"title":{},"content":{"90":{"position":[[4119,4]]}},"keywords":{}}],["40.78306",{"_index":1454,"title":{},"content":{"30":{"position":[[8513,10]]}},"keywords":{}}],["400",{"_index":3181,"title":{},"content":{"92":{"position":[[1375,4]]}},"keywords":{}}],["4000",{"_index":2794,"title":{},"content":{"82":{"position":[[477,5]]}},"keywords":{}}],["404",{"_index":3320,"title":{},"content":{"96":{"position":[[256,3]]}},"keywords":{}}],["413n",{"_index":4862,"title":{},"content":{"168":{"position":[[213,5]]}},"keywords":{}}],["42.098687",{"_index":1460,"title":{},"content":{"30":{"position":[[8589,11]]}},"keywords":{}}],["42.935064321851307",{"_index":865,"title":{},"content":{"20":{"position":[[2865,20]]}},"keywords":{}}],["421n",{"_index":4888,"title":{},"content":{"169":{"position":[[419,5]]}},"keywords":{}}],["47.60621",{"_index":1457,"title":{},"content":{"30":{"position":[[8549,10]]}},"keywords":{}}],["47578",{"_index":3159,"title":{},"content":{"91":{"position":[[4389,6],[4399,6],[5199,6],[5209,6],[5582,6],[5592,6]]},"92":{"position":[[1162,6],[1172,6],[1720,6],[1730,6],[1879,6],[1889,6]]}},"keywords":{}}],["4760716",{"_index":2527,"title":{},"content":{"65":{"position":[[2115,7]]}},"keywords":{}}],["48",{"_index":2516,"title":{},"content":{"65":{"position":[[1303,2]]}},"keywords":{}}],["48041640",{"_index":2514,"title":{},"content":{"65":{"position":[[1176,8]]}},"keywords":{}}],["481",{"_index":4599,"title":{},"content":{"156":{"position":[[666,3]]}},"keywords":{}}],["49",{"_index":323,"title":{},"content":{"6":{"position":[[345,5],[833,4]]}},"keywords":{}}],["49.517493",{"_index":3646,"title":{},"content":{"105":{"position":[[2514,9]]}},"keywords":{}}],["4b392b#4b392b",{"_index":2226,"title":{},"content":{"53":{"position":[[715,14]]}},"keywords":{}}],["4differentimplement",{"_index":3945,"title":{},"content":{"122":{"position":[[757,25]]}},"keywords":{}}],["4f",{"_index":591,"title":{},"content":{"13":{"position":[[1588,7]]},"14":{"position":[[2671,7]]},"15":{"position":[[2345,7]]}},"keywords":{}}],["5",{"_index":365,"title":{"82":{"position":[[8,2]]},"112":{"position":[[5,2]]}},"content":{"6":{"position":[[967,1],[1071,2]]},"11":{"position":[[139,1],[297,1]]},"13":{"position":[[2164,2],[2211,1]]},"14":{"position":[[3236,2],[3283,1]]},"15":{"position":[[2907,2],[2954,1]]},"30":{"position":[[3282,2],[7234,2]]},"33":{"position":[[946,3]]},"34":{"position":[[3462,1],[3566,1]]},"51":{"position":[[3304,2]]},"65":{"position":[[2478,2]]},"70":{"position":[[385,1],[561,1]]},"71":{"position":[[486,1],[660,1]]},"78":{"position":[[450,2]]},"88":{"position":[[1477,2],[1806,2],[1809,3],[3333,2],[3336,3]]},"90":{"position":[[3340,2],[4057,2],[4307,2],[4412,3],[4515,3]]},"91":{"position":[[4340,1],[4548,1],[5962,1]]},"97":{"position":[[1788,1]]},"103":{"position":[[629,1]]},"121":{"position":[[2180,2]]},"163":{"position":[[856,1],[876,1],[896,1]]},"193":{"position":[[1854,2],[2809,2]]}},"keywords":{}}],["5%you",{"_index":1586,"title":{},"content":{"33":{"position":[[1110,6]]}},"keywords":{}}],["5.0",{"_index":4764,"title":{},"content":{"163":{"position":[[459,3]]}},"keywords":{}}],["5.05",{"_index":610,"title":{},"content":{"13":{"position":[[2027,5]]}},"keywords":{}}],["5.18",{"_index":612,"title":{},"content":{"13":{"position":[[2083,5]]}},"keywords":{}}],["5.32",{"_index":617,"title":{},"content":{"13":{"position":[[2195,5]]}},"keywords":{}}],["5.34",{"_index":539,"title":{},"content":{"12":{"position":[[672,5]]}},"keywords":{}}],["5.37",{"_index":615,"title":{},"content":{"13":{"position":[[2139,5]]}},"keywords":{}}],["5.59",{"_index":607,"title":{},"content":{"13":{"position":[[1971,5]]}},"keywords":{}}],["5.590373200042106",{"_index":1662,"title":{},"content":{"34":{"position":[[3429,17]]}},"keywords":{}}],["5.62",{"_index":5187,"title":{},"content":{"188":{"position":[[2270,4]]}},"keywords":{}}],["5.6x",{"_index":1664,"title":{},"content":{"34":{"position":[[3523,4]]}},"keywords":{}}],["5.72",{"_index":653,"title":{},"content":{"14":{"position":[[3043,5]]}},"keywords":{}}],["5.81",{"_index":661,"title":{},"content":{"14":{"position":[[3267,5]]}},"keywords":{}}],["5.8337945679814904",{"_index":864,"title":{},"content":{"20":{"position":[[2836,20]]}},"keywords":{}}],["5.85",{"_index":655,"title":{},"content":{"14":{"position":[[3099,5]]}},"keywords":{}}],["5.87",{"_index":657,"title":{},"content":{"14":{"position":[[3155,5]]}},"keywords":{}}],["5.89",{"_index":685,"title":{},"content":{"15":{"position":[[2714,5]]}},"keywords":{}}],["5.90",{"_index":687,"title":{},"content":{"15":{"position":[[2770,5]]}},"keywords":{}}],["5.92",{"_index":689,"title":{},"content":{"15":{"position":[[2826,5]]}},"keywords":{}}],["5.93",{"_index":659,"title":{},"content":{"14":{"position":[[3211,5]]}},"keywords":{}}],["5.94",{"_index":691,"title":{},"content":{"15":{"position":[[2882,5]]}},"keywords":{}}],["5/1/2016"",{"_index":2887,"title":{},"content":{"88":{"position":[[1688,16]]}},"keywords":{}}],["5/18/2016",{"_index":3214,"title":{},"content":{"93":{"position":[[2036,9]]}},"keywords":{}}],["5/19/2016",{"_index":3213,"title":{},"content":{"93":{"position":[[1964,10]]}},"keywords":{}}],["5/5/2016",{"_index":2895,"title":{},"content":{"88":{"position":[[1995,10]]}},"keywords":{}}],["50",{"_index":672,"title":{},"content":{"15":{"position":[[377,4]]},"24":{"position":[[341,3]]},"30":{"position":[[1191,4]]},"44":{"position":[[871,3]]},"49":{"position":[[329,3],[370,3]]},"51":{"position":[[3375,4]]}},"keywords":{}}],["500",{"_index":846,"title":{},"content":{"20":{"position":[[2290,5]]},"23":{"position":[[100,3]]},"24":{"position":[[3362,3]]},"150":{"position":[[534,4]]},"161":{"position":[[1352,3]]}},"keywords":{}}],["5000",{"_index":2796,"title":{},"content":{"82":{"position":[[547,5]]}},"keywords":{}}],["51131",{"_index":1945,"title":{},"content":{"44":{"position":[[1589,6]]}},"keywords":{}}],["512",{"_index":3600,"title":{},"content":{"105":{"position":[[1265,5],[1304,5],[2315,5],[2439,5]]}},"keywords":{}}],["522",{"_index":5254,"title":{},"content":{"189":{"position":[[2849,3]]}},"keywords":{}}],["524",{"_index":5253,"title":{},"content":{"189":{"position":[[2805,3],[2831,3]]}},"keywords":{}}],["539n",{"_index":4879,"title":{},"content":{"169":{"position":[[327,5]]}},"keywords":{}}],["541",{"_index":5245,"title":{},"content":{"189":{"position":[[2233,3],[2280,3]]}},"keywords":{}}],["545",{"_index":5247,"title":{},"content":{"189":{"position":[[2262,3]]}},"keywords":{}}],["545.0354060154496",{"_index":2799,"title":{},"content":{"82":{"position":[[658,17]]}},"keywords":{}}],["546.7574874775273",{"_index":2795,"title":{},"content":{"82":{"position":[[518,17]]}},"keywords":{}}],["547.7803673440676",{"_index":2791,"title":{},"content":{"82":{"position":[[378,17]]}},"keywords":{}}],["547.9805613193807",{"_index":2793,"title":{},"content":{"82":{"position":[[448,17]]}},"keywords":{}}],["549.400679551826",{"_index":2806,"title":{},"content":{"82":{"position":[[939,16]]}},"keywords":{}}],["549.5798007672656",{"_index":2797,"title":{},"content":{"82":{"position":[[588,17]]}},"keywords":{}}],["549.9306537114975",{"_index":2803,"title":{},"content":{"82":{"position":[[798,17]]}},"keywords":{}}],["55",{"_index":5336,"title":{},"content":{"196":{"position":[[1625,2]]}},"keywords":{}}],["550.1134504086606",{"_index":2801,"title":{},"content":{"82":{"position":[[728,17]]}},"keywords":{}}],["550.7075182119111",{"_index":2805,"title":{},"content":{"82":{"position":[[868,17]]}},"keywords":{}}],["551",{"_index":5249,"title":{},"content":{"189":{"position":[[2516,3]]}},"keywords":{}}],["551.6995384525453",{"_index":2790,"title":{},"content":{"82":{"position":[[308,17]]}},"keywords":{}}],["559",{"_index":5251,"title":{},"content":{"189":{"position":[[2545,3]]}},"keywords":{}}],["5:28",{"_index":2539,"title":{},"content":{"65":{"position":[[2544,4]]}},"keywords":{}}],["6",{"_index":561,"title":{"113":{"position":[[5,2]]}},"content":{"13":{"position":[[575,2]]},"14":{"position":[[1405,2]]},"15":{"position":[[774,2]]},"30":{"position":[[7194,2]]},"40":{"position":[[475,2],[2011,2],[2955,2]]},"45":{"position":[[2470,2],[3250,2]]},"64":{"position":[[458,1],[774,1],[960,1]]},"70":{"position":[[405,1],[580,1]]},"71":{"position":[[506,1],[680,1]]},"76":{"position":[[1304,2],[1354,2],[2027,2],[2054,2]]},"79":{"position":[[61,2]]},"80":{"position":[[54,2]]},"81":{"position":[[131,3],[150,3]]},"88":{"position":[[3551,2]]},"90":{"position":[[4240,3]]},"91":{"position":[[460,2],[4322,2]]},"163":{"position":[[858,1],[878,1],[898,1]]},"175":{"position":[[264,1]]},"193":{"position":[[1860,1],[2815,1]]}},"keywords":{}}],["6%capit",{"_index":641,"title":{},"content":{"14":{"position":[[1290,9]]}},"keywords":{}}],["6"",{"_index":954,"title":{},"content":{"22":{"position":[[1807,7]]},"71":{"position":[[1406,9]]}},"keywords":{}}],["6.00",{"_index":4890,"title":{},"content":{"169":{"position":[[432,5]]}},"keywords":{}}],["6.06",{"_index":693,"title":{},"content":{"15":{"position":[[2938,5]]}},"keywords":{}}],["6.185015",{"_index":3641,"title":{},"content":{"105":{"position":[[2388,8]]}},"keywords":{}}],["6000",{"_index":2798,"title":{},"content":{"82":{"position":[[617,5]]}},"keywords":{}}],["603",{"_index":2132,"title":{},"content":{"51":{"position":[[2551,3],[2579,3]]}},"keywords":{}}],["63",{"_index":1164,"title":{},"content":{"25":{"position":[[2753,3]]}},"keywords":{}}],["64",{"_index":3598,"title":{},"content":{"105":{"position":[[1228,4],[2192,4],[3208,3]]},"192":{"position":[[693,2]]}},"keywords":{}}],["641",{"_index":5186,"title":{},"content":{"188":{"position":[[2257,3]]}},"keywords":{}}],["645",{"_index":5189,"title":{},"content":{"188":{"position":[[2304,3]]}},"keywords":{}}],["647",{"_index":5188,"title":{},"content":{"188":{"position":[[2286,3]]}},"keywords":{}}],["659n",{"_index":4893,"title":{},"content":{"169":{"position":[[454,5]]}},"keywords":{}}],["667",{"_index":5198,"title":{},"content":{"188":{"position":[[3112,3],[3138,3]]}},"keywords":{}}],["672",{"_index":5199,"title":{},"content":{"188":{"position":[[3156,3]]}},"keywords":{}}],["69",{"_index":1666,"title":{},"content":{"34":{"position":[[3595,4]]}},"keywords":{}}],["69.054298",{"_index":3618,"title":{},"content":{"105":{"position":[[1973,9]]}},"keywords":{}}],["69.054306",{"_index":3621,"title":{},"content":{"105":{"position":[[2011,9],[2021,9]]}},"keywords":{}}],["69.054321",{"_index":3623,"title":{},"content":{"105":{"position":[[2048,9]]}},"keywords":{}}],["69.054443",{"_index":3626,"title":{},"content":{"105":{"position":[[2086,9]]}},"keywords":{}}],["69.054688",{"_index":3629,"title":{},"content":{"105":{"position":[[2125,9],[2163,9],[2202,9],[2244,9],[2285,9],[2327,9],[2337,9]]}},"keywords":{}}],["69.062500",{"_index":3639,"title":{},"content":{"105":{"position":[[2369,9],[2409,9],[2451,9],[2494,9],[2504,9]]}},"keywords":{}}],["6\\}pij​∈(0,1);i,j∈{1,…,6",{"_index":2822,"title":{},"content":{"85":{"position":[[303,26]]}},"keywords":{}}],["6x",{"_index":1700,"title":{},"content":{"38":{"position":[[921,2]]}},"keywords":{}}],["7",{"_index":1260,"title":{},"content":{"28":{"position":[[1899,3]]},"30":{"position":[[9341,2]]},"68":{"position":[[522,2],[562,2],[724,1]]},"70":{"position":[[708,1],[1288,1]]},"71":{"position":[[808,1]]},"163":{"position":[[860,1],[880,1],[900,1]]}},"keywords":{}}],["7.77",{"_index":5250,"title":{},"content":{"189":{"position":[[2529,4]]}},"keywords":{}}],["70",{"_index":642,"title":{},"content":{"14":{"position":[[1317,3]]},"15":{"position":[[325,3]]},"196":{"position":[[1827,2]]}},"keywords":{}}],["70%coupon",{"_index":640,"title":{},"content":{"14":{"position":[[1279,10]]}},"keywords":{}}],["7000",{"_index":2800,"title":{},"content":{"82":{"position":[[687,5]]}},"keywords":{}}],["717",{"_index":5191,"title":{},"content":{"188":{"position":[[2574,3]]}},"keywords":{}}],["718",{"_index":5192,"title":{},"content":{"188":{"position":[[2602,3]]}},"keywords":{}}],["73",{"_index":4516,"title":{},"content":{"152":{"position":[[683,2]]}},"keywords":{}}],["73.971249",{"_index":1455,"title":{},"content":{"30":{"position":[[8524,10]]}},"keywords":{}}],["737n",{"_index":4884,"title":{},"content":{"169":{"position":[[381,5]]}},"keywords":{}}],["75",{"_index":1929,"title":{},"content":{"44":{"position":[[884,3]]}},"keywords":{}}],["75.917974",{"_index":1461,"title":{},"content":{"30":{"position":[[8601,10]]}},"keywords":{}}],["773609400",{"_index":2474,"title":{},"content":{"64":{"position":[[1072,9]]}},"keywords":{}}],["774",{"_index":2476,"title":{},"content":{"64":{"position":[[1145,3]]}},"keywords":{}}],["775,804,660",{"_index":2496,"title":{},"content":{"64":{"position":[[1987,11]]}},"keywords":{}}],["775804660",{"_index":2494,"title":{},"content":{"64":{"position":[[1901,9]]}},"keywords":{}}],["78.781117",{"_index":1452,"title":{},"content":{"30":{"position":[[8492,10]]}},"keywords":{}}],["7983)browser",{"_index":4206,"title":{},"content":{"125":{"position":[[11127,14]]}},"keywords":{}}],["8",{"_index":644,"title":{},"content":{"14":{"position":[[1376,2]]},"15":{"position":[[745,2]]},"28":{"position":[[1914,3]]},"34":{"position":[[3990,2]]},"40":{"position":[[306,3],[1840,3],[2783,3]]},"53":{"position":[[199,1],[1429,1]]},"65":{"position":[[2080,1]]},"91":{"position":[[1539,1],[4998,1],[5063,1],[5145,1],[5372,1],[5969,1]]},"92":{"position":[[1597,1]]},"127":{"position":[[643,2],[1293,2]]},"128":{"position":[[280,2],[503,3],[542,1],[1152,2],[1423,1]]},"129":{"position":[[911,2],[947,1],[1150,2],[1566,1],[2621,1],[2648,3]]},"163":{"position":[[862,1],[882,1],[902,1],[1163,1]]},"172":{"position":[[497,2]]},"185":{"position":[[834,2]]},"195":{"position":[[249,1],[400,1]]}},"keywords":{}}],["8.481735",{"_index":3628,"title":{},"content":{"105":{"position":[[2106,8]]}},"keywords":{}}],["8.542909",{"_index":3633,"title":{},"content":{"105":{"position":[[2183,8]]}},"keywords":{}}],["8.631836",{"_index":3630,"title":{},"content":{"105":{"position":[[2135,8]]}},"keywords":{}}],["8.632812",{"_index":3640,"title":{},"content":{"105":{"position":[[2379,8]]}},"keywords":{}}],["8.__str__",{"_index":4329,"title":{},"content":{"129":{"position":[[2408,13],[2454,11],[2505,11]]}},"keywords":{}}],["8.to_str",{"_index":4279,"title":{},"content":{"129":{"position":[[430,13]]},"130":{"position":[[469,13]]}},"keywords":{}}],["80",{"_index":673,"title":{},"content":{"15":{"position":[[438,4]]},"26":{"position":[[664,3]]}},"keywords":{}}],["8000",{"_index":2802,"title":{},"content":{"82":{"position":[[757,5]]}},"keywords":{}}],["8139060",{"_index":2444,"title":{},"content":{"62":{"position":[[1667,7]]}},"keywords":{}}],["86400",{"_index":2380,"title":{},"content":{"61":{"position":[[1697,6]]}},"keywords":{}}],["890",{"_index":5216,"title":{},"content":{"188":{"position":[[4013,3]]}},"keywords":{}}],["9",{"_index":324,"title":{},"content":{"6":{"position":[[351,3],[838,3]]},"28":{"position":[[1932,3]]},"90":{"position":[[4622,4]]},"163":{"position":[[864,1],[884,1],[904,1]]},"172":{"position":[[511,2]]}},"keywords":{}}],["9.430644",{"_index":3636,"title":{},"content":{"105":{"position":[[2264,8]]}},"keywords":{}}],["9000",{"_index":2804,"title":{},"content":{"82":{"position":[[827,5]]}},"keywords":{}}],["91n",{"_index":4874,"title":{},"content":{"168":{"position":[[331,4]]}},"keywords":{}}],["926",{"_index":5214,"title":{},"content":{"188":{"position":[[3934,3]]}},"keywords":{}}],["95.00",{"_index":620,"title":{},"content":{"13":{"position":[[2275,7]]}},"keywords":{}}],["96",{"_index":2456,"title":{},"content":{"64":{"position":[[441,2],[945,2]]}},"keywords":{}}],["96mmm",{"_index":2465,"title":{},"content":{"64":{"position":[[733,6]]}},"keywords":{}}],["97.44",{"_index":663,"title":{},"content":{"14":{"position":[[3363,6]]}},"keywords":{}}],["99.9th",{"_index":4859,"title":{},"content":{"168":{"position":[[177,6]]},"169":{"position":[[291,6]]}},"keywords":{}}],["99th",{"_index":4857,"title":{},"content":{"168":{"position":[[167,4]]},"169":{"position":[[281,4]]}},"keywords":{}}],["_",{"_index":3374,"title":{},"content":{"97":{"position":[[1561,3],[3656,2]]},"103":{"position":[[1730,2],[1733,2],[2049,2],[2052,2]]},"105":{"position":[[2687,2],[2690,2],[2888,2],[2891,2],[3160,2],[3163,2]]},"188":{"position":[[1553,1],[1649,1]]},"189":{"position":[[1743,1]]}},"keywords":{}}],["__abs__",{"_index":4311,"title":{},"content":{"129":{"position":[[2132,11]]}},"keywords":{}}],["__add__",{"_index":4312,"title":{},"content":{"129":{"position":[[2144,10]]}},"keywords":{}}],["__and__",{"_index":4313,"title":{},"content":{"129":{"position":[[2155,10]]}},"keywords":{}}],["__class__",{"_index":4314,"title":{},"content":{"129":{"position":[[2166,12]]}},"keywords":{}}],["__cmp__",{"_index":4315,"title":{},"content":{"129":{"position":[[2179,10]]}},"keywords":{}}],["__coerce__",{"_index":4316,"title":{},"content":{"129":{"position":[[2190,13]]}},"keywords":{}}],["__delattr__",{"_index":4317,"title":{},"content":{"129":{"position":[[2204,14]]}},"keywords":{}}],["__div__",{"_index":4318,"title":{},"content":{"129":{"position":[[2219,10]]}},"keywords":{}}],["__divmod__",{"_index":4319,"title":{},"content":{"129":{"position":[[2230,13]]}},"keywords":{}}],["__doc__",{"_index":4320,"title":{},"content":{"129":{"position":[[2244,10]]}},"keywords":{}}],["__float__",{"_index":4321,"title":{},"content":{"129":{"position":[[2255,12]]}},"keywords":{}}],["__floordiv__",{"_index":4322,"title":{},"content":{"129":{"position":[[2268,15]]}},"keywords":{}}],["__init__",{"_index":931,"title":{},"content":{"22":{"position":[[1268,8]]}},"keywords":{}}],["__init__(self",{"_index":932,"title":{},"content":{"22":{"position":[[1281,14]]},"93":{"position":[[1549,14]]}},"keywords":{}}],["__setattr__",{"_index":4323,"title":{},"content":{"129":{"position":[[2288,14]]}},"keywords":{}}],["__sizeof__",{"_index":4324,"title":{},"content":{"129":{"position":[[2303,13]]}},"keywords":{}}],["__str__",{"_index":4325,"title":{},"content":{"129":{"position":[[2317,10]]}},"keywords":{}}],["__sub__",{"_index":4326,"title":{},"content":{"129":{"position":[[2328,10]]}},"keywords":{}}],["__subclasshook__",{"_index":4327,"title":{},"content":{"129":{"position":[[2339,19]]}},"keywords":{}}],["__truediv__",{"_index":4328,"title":{},"content":{"129":{"position":[[2359,14]]}},"keywords":{}}],["_a",{"_index":4548,"title":{},"content":{"153":{"position":[[548,3],[599,3],[664,3],[718,3]]},"195":{"position":[[230,3],[296,3],[378,3],[610,3]]}},"keywords":{}}],["_bootstrap",{"_index":5217,"title":{},"content":{"188":{"position":[[4020,10]]}},"keywords":{}}],["_bootstrap_inn",{"_index":5215,"title":{},"content":{"188":{"position":[[3941,16]]}},"keywords":{}}],["_dist_1",{"_index":5293,"title":{},"content":{"193":{"position":[[1869,7],[2824,7]]}},"keywords":{}}],["_dist_2",{"_index":5296,"title":{},"content":{"193":{"position":[[1918,7],[2873,7]]}},"keywords":{}}],["_i",{"_index":5164,"title":{},"content":{"188":{"position":[[1099,2]]},"189":{"position":[[1161,2],[1431,2]]},"199":{"position":[[1478,4]]}},"keywords":{}}],["_x",{"_index":4554,"title":{},"content":{"153":{"position":[[914,5],[1002,2]]},"195":{"position":[[818,2]]}},"keywords":{}}],["a"flamegraph"",{"_index":4378,"title":{},"content":{"135":{"position":[[92,24]]}},"keywords":{}}],["a.i",{"_index":5285,"title":{},"content":{"193":{"position":[[1367,4],[2547,4],[2617,4],[2631,4],[3318,4],[3632,4]]}},"keywords":{}}],["a.x",{"_index":5282,"title":{},"content":{"193":{"position":[[1339,4],[2519,4],[2578,4],[2592,4],[3290,4],[3604,4]]}},"keywords":{}}],["a=440",{"_index":63,"title":{},"content":{"1":{"position":[[702,5]]}},"keywords":{}}],["aa",{"_index":4915,"title":{},"content":{"172":{"position":[[1176,2]]}},"keywords":{}}],["aac",{"_index":3478,"title":{},"content":{"101":{"position":[[591,3]]},"106":{"position":[[437,3]]}},"keywords":{}}],["aamaz",{"_index":2275,"title":{},"content":{"53":{"position":[[1499,8]]}},"keywords":{}}],["aapl",{"_index":2875,"title":{},"content":{"88":{"position":[[1412,4],[2756,4],[2876,5],[2947,5]]},"91":{"position":[[1501,4]]}},"keywords":{}}],["aapl[datetime(2016",{"_index":3091,"title":{},"content":{"91":{"position":[[1003,19]]}},"keywords":{}}],["aapl_plot",{"_index":3088,"title":{},"content":{"91":{"position":[[909,9],[975,10]]}},"keywords":{}}],["aapl_plot.legend(loc=3",{"_index":3097,"title":{},"content":{"91":{"position":[[1319,23]]}},"keywords":{}}],["aapl_plot.plot(aapl_truncated.index",{"_index":3095,"title":{},"content":{"91":{"position":[[1117,36]]}},"keywords":{}}],["aapl_plot.set_title('aapl",{"_index":3098,"title":{},"content":{"91":{"position":[[1343,25]]}},"keywords":{}}],["aapl_plot.vlines(date2num(datetime(2016",{"_index":3096,"title":{},"content":{"91":{"position":[[1182,40]]}},"keywords":{}}],["aapl_trunc",{"_index":3090,"title":{},"content":{"91":{"position":[[986,14]]}},"keywords":{}}],["aapl_truncated['close']/2",{"_index":3094,"title":{},"content":{"91":{"position":[[1091,25]]}},"keywords":{}}],["aapl_truncated['open']/2",{"_index":3093,"title":{},"content":{"91":{"position":[[1064,24]]}},"keywords":{}}],["abandon",{"_index":169,"title":{},"content":{"3":{"position":[[675,9]]},"97":{"position":[[2636,7]]}},"keywords":{}}],["abil",{"_index":280,"title":{},"content":{"4":{"position":[[1098,7]]},"46":{"position":[[162,7]]}},"keywords":{}}],["abort",{"_index":3785,"title":{},"content":{"115":{"position":[[2453,8]]},"116":{"position":[[2311,8]]}},"keywords":{}}],["aboutlong",{"_index":3906,"title":{},"content":{"121":{"position":[[1645,9]]}},"keywords":{}}],["abov",{"_index":474,"title":{},"content":{"9":{"position":[[696,5]]},"13":{"position":[[181,5],[263,5]]},"14":{"position":[[336,5],[406,5],[724,5],[868,5],[1061,5]]},"20":{"position":[[878,5]]},"30":{"position":[[1185,5],[2289,6]]},"33":{"position":[[44,5]]},"40":{"position":[[3384,5]]},"43":{"position":[[1113,6]]},"72":{"position":[[402,5]]},"83":{"position":[[19,6]]},"88":{"position":[[3572,6]]},"90":{"position":[[5062,5]]},"125":{"position":[[8840,5]]},"176":{"position":[[825,5]]},"189":{"position":[[1671,6]]}},"keywords":{}}],["above)project",{"_index":4207,"title":{},"content":{"125":{"position":[[11250,14]]}},"keywords":{}}],["above,std::vec",{"_index":4695,"title":{},"content":{"160":{"position":[[2497,14]]}},"keywords":{}}],["acc_df",{"_index":1916,"title":{},"content":{"44":{"position":[[701,6]]}},"keywords":{}}],["acc_df.describ",{"_index":1919,"title":{},"content":{"44":{"position":[[772,17]]}},"keywords":{}}],["acccur",{"_index":1171,"title":{},"content":{"26":{"position":[[239,9]]}},"keywords":{}}],["accept",{"_index":3431,"title":{},"content":{"97":{"position":[[5917,6]]},"101":{"position":[[995,10]]},"125":{"position":[[4224,7]]},"166":{"position":[[706,6]]},"176":{"position":[[1615,10]]},"182":{"position":[[659,10]]}},"keywords":{}}],["accept_prob",{"_index":2740,"title":{},"content":{"76":{"position":[[3018,11],[3109,12]]}},"keywords":{}}],["access",{"_index":2350,"title":{},"content":{"61":{"position":[[134,6],[354,6],[716,6],[763,6],[953,6],[1196,6]]},"62":{"position":[[36,6]]},"97":{"position":[[5525,6]]},"113":{"position":[[405,6]]},"115":{"position":[[2813,8]]},"121":{"position":[[520,6]]},"128":{"position":[[612,6]]},"160":{"position":[[2359,6]]},"173":{"position":[[2103,8]]},"174":{"position":[[620,6]]},"180":{"position":[[208,9]]},"185":{"position":[[150,6]]},"188":{"position":[[4247,7]]},"190":{"position":[[320,6]]}},"keywords":{}}],["access_token",{"_index":2391,"title":{},"content":{"61":{"position":[[2302,12]]},"62":{"position":[[51,13],[490,15],[506,13]]}},"keywords":{}}],["accident",{"_index":823,"title":{},"content":{"20":{"position":[[1625,12]]},"160":{"position":[[1408,12]]}},"keywords":{}}],["accomplish",{"_index":2230,"title":{},"content":{"53":{"position":[[810,15],[1740,15]]},"86":{"position":[[595,11]]},"101":{"position":[[319,10]]},"160":{"position":[[2186,12]]},"164":{"position":[[1278,13]]},"186":{"position":[[155,10]]}},"keywords":{}}],["accord",{"_index":2536,"title":{},"content":{"65":{"position":[[2487,9]]},"75":{"position":[[1203,9]]}},"keywords":{}}],["account",{"_index":1437,"title":{},"content":{"30":{"position":[[7778,7]]},"43":{"position":[[959,9]]},"64":{"position":[[339,7]]},"76":{"position":[[1569,7]]},"86":{"position":[[419,8]]},"90":{"position":[[3243,7]]}},"keywords":{}}],["accur",{"_index":1014,"title":{},"content":{"24":{"position":[[55,8],[345,9],[3224,8]]},"25":{"position":[[2772,8]]},"26":{"position":[[86,8]]},"45":{"position":[[980,8]]},"65":{"position":[[147,8]]},"91":{"position":[[5127,9]]},"193":{"position":[[1042,9]]}},"keywords":{}}],["accuraci",{"_index":1098,"title":{},"content":{"24":{"position":[[2643,9]]},"25":{"position":[[2366,9],[2757,8]]},"26":{"position":[[641,8]]},"44":{"position":[[631,8],[746,10],[1525,9],[1636,9]]},"45":{"position":[[1736,8]]},"89":{"position":[[771,8]]}},"keywords":{}}],["accuracy"",{"_index":2008,"title":{},"content":{"45":{"position":[[2286,15],[3066,15]]}},"keywords":{}}],["accuracy:"",{"_index":1092,"title":{},"content":{"24":{"position":[[2416,16]]},"25":{"position":[[2139,16]]}},"keywords":{}}],["accuracycount",{"_index":1920,"title":{},"content":{"44":{"position":[[793,13]]}},"keywords":{}}],["accus",{"_index":2946,"title":{},"content":{"89":{"position":[[220,6]]}},"keywords":{}}],["achiev",{"_index":1174,"title":{},"content":{"26":{"position":[[630,7]]},"117":{"position":[[2034,7]]}},"keywords":{}}],["acknowledg",{"_index":3314,"title":{},"content":{"96":{"position":[[29,11]]},"175":{"position":[[870,14]]}},"keywords":{}}],["aconst",{"_index":5128,"title":{},"content":{"184":{"position":[[918,6]]}},"keywords":{}}],["acquir",{"_index":4901,"title":{},"content":{"172":{"position":[[306,8]]},"188":{"position":[[1388,8],[2388,7]]},"189":{"position":[[2938,9]]}},"keywords":{}}],["acquire/releaseth",{"_index":5220,"title":{},"content":{"188":{"position":[[4176,18]]}},"keywords":{}}],["acquisit",{"_index":4560,"title":{},"content":{"155":{"position":[[329,11]]}},"keywords":{}}],["act",{"_index":3574,"title":{},"content":{"105":{"position":[[157,4]]},"113":{"position":[[851,4]]}},"keywords":{}}],["action",{"_index":2905,"title":{},"content":{"88":{"position":[[2424,7]]},"113":{"position":[[2567,7]]},"127":{"position":[[1625,7]]},"179":{"position":[[354,7]]},"188":{"position":[[818,7]]},"193":{"position":[[874,6]]}},"keywords":{}}],["activ",{"_index":181,"title":{},"content":{"3":{"position":[[905,8]]},"62":{"position":[[863,11]]},"188":{"position":[[578,6],[1970,6]]}},"keywords":{}}],["activities/heart/date/{0}/1d/1min.json",{"_index":2412,"title":{},"content":{"62":{"position":[[716,40]]}},"keywords":{}}],["actual",{"_index":22,"title":{"76":{"position":[[4,6]]}},"content":{"1":{"position":[[241,8]]},"2":{"position":[[94,6],[513,8]]},"7":{"position":[[800,8]]},"10":{"position":[[576,6]]},"11":{"position":[[52,8]]},"12":{"position":[[20,8]]},"13":{"position":[[57,8]]},"22":{"position":[[111,6]]},"24":{"position":[[1075,8],[2996,6]]},"25":{"position":[[795,8]]},"26":{"position":[[200,6]]},"28":{"position":[[803,8]]},"29":{"position":[[196,8]]},"30":{"position":[[563,8],[738,8],[4067,8],[7279,8]]},"34":{"position":[[130,8],[280,8],[754,8]]},"35":{"position":[[162,8],[407,8]]},"38":{"position":[[1300,6]]},"40":{"position":[[743,8]]},"43":{"position":[[1264,8]]},"45":{"position":[[919,8],[1262,8],[1535,6],[3557,8]]},"46":{"position":[[173,8],[445,8]]},"49":{"position":[[641,6]]},"51":{"position":[[2000,8],[2241,8],[2767,8],[2957,6],[3563,8]]},"52":{"position":[[43,8]]},"62":{"position":[[16,8],[86,6],[1788,6]]},"73":{"position":[[498,6]]},"74":{"position":[[144,8]]},"76":{"position":[[96,8],[620,8]]},"77":{"position":[[212,6]]},"82":{"position":[[1037,6]]},"86":{"position":[[984,8]]},"90":{"position":[[56,6]]},"91":{"position":[[1714,8]]},"95":{"position":[[329,8]]},"96":{"position":[[1823,8]]},"97":{"position":[[745,6],[2728,8],[4180,8],[6319,8]]},"102":{"position":[[1462,8]]},"103":{"position":[[148,8],[1274,6],[1552,8]]},"106":{"position":[[78,8],[254,8]]},"108":{"position":[[178,8]]},"109":{"position":[[48,8]]},"111":{"position":[[18,8]]},"112":{"position":[[67,8],[409,8],[596,6],[1744,8]]},"113":{"position":[[103,8],[626,6],[1306,6],[1626,8]]},"116":{"position":[[3214,8]]},"117":{"position":[[449,6],[1681,6],[1933,8]]},"120":{"position":[[398,8]]},"121":{"position":[[197,8],[371,6],[2334,8]]},"125":{"position":[[6316,8],[6911,8]]},"130":{"position":[[486,8]]},"160":{"position":[[2515,8]]},"163":{"position":[[375,8],[2444,8]]},"165":{"position":[[426,8]]},"167":{"position":[[60,8]]},"172":{"position":[[1879,8]]},"176":{"position":[[1170,8]]},"188":{"position":[[4493,8]]},"193":{"position":[[1396,6]]},"196":{"position":[[123,8]]}},"keywords":{}}],["actual_word",{"_index":2100,"title":{},"content":{"51":{"position":[[1194,12]]}},"keywords":{}}],["actualu64",{"_index":5345,"title":{},"content":{"197":{"position":[[537,9],[574,9],[1224,11],[1350,9]]}},"keywords":{}}],["ad",{"_index":193,"title":{},"content":{"3":{"position":[[1129,5]]},"121":{"position":[[2636,5]]},"123":{"position":[[1059,6]]},"166":{"position":[[21,5]]},"189":{"position":[[471,5],[605,6]]}},"keywords":{}}],["adapt",{"_index":5138,"title":{},"content":{"186":{"position":[[219,7]]}},"keywords":{}}],["add",{"_index":285,"title":{},"content":{"4":{"position":[[1220,4]]},"7":{"position":[[87,3]]},"128":{"position":[[1609,3]]},"129":{"position":[[719,3]]},"133":{"position":[[251,3]]},"161":{"position":[[1239,3],[1289,3]]},"185":{"position":[[579,3]]},"193":{"position":[[1649,3]]}},"keywords":{}}],["addit",{"_index":1403,"title":{},"content":{"30":{"position":[[4425,8],[5860,8]]},"86":{"position":[[431,9]]},"125":{"position":[[4411,10]]},"172":{"position":[[2145,8]]},"173":{"position":[[1005,8]]}},"keywords":{}}],["addition",{"_index":343,"title":{},"content":{"6":{"position":[[599,12]]},"66":{"position":[[285,13]]},"83":{"position":[[304,13]]},"85":{"position":[[400,13]]},"90":{"position":[[3379,13]]}},"keywords":{}}],["address",{"_index":1592,"title":{},"content":{"34":{"position":[[182,8]]},"160":{"position":[[2241,10],[3343,7],[3632,7]]},"165":{"position":[[135,7]]},"166":{"position":[[221,9]]},"170":{"position":[[169,9]]},"178":{"position":[[497,7]]},"180":{"position":[[270,8]]},"181":{"position":[[654,7]]},"190":{"position":[[37,7],[420,7]]},"197":{"position":[[1006,7]]},"198":{"position":[[127,9]]},"199":{"position":[[789,8]]}},"keywords":{}}],["adjust",{"_index":3039,"title":{},"content":{"90":{"position":[[3920,10]]}},"keywords":{}}],["admit",{"_index":1312,"title":{},"content":{"29":{"position":[[11,5]]}},"keywords":{}}],["admittedli",{"_index":3872,"title":{},"content":{"121":{"position":[[99,10]]}},"keywords":{}}],["advanc",{"_index":2901,"title":{},"content":{"88":{"position":[[2256,7]]}},"keywords":{}}],["advantag",{"_index":1690,"title":{},"content":{"38":{"position":[[256,9]]},"97":{"position":[[2700,9]]},"125":{"position":[[1102,9]]}},"keywords":{}}],["advent",{"_index":4350,"title":{},"content":{"132":{"position":[[516,6]]}},"keywords":{}}],["advic",{"_index":1682,"title":{},"content":{"36":{"position":[[137,6]]}},"keywords":{}}],["affect",{"_index":4635,"title":{},"content":{"159":{"position":[[817,6]]},"160":{"position":[[1899,6]]},"176":{"position":[[281,7]]}},"keywords":{}}],["affin",{"_index":4947,"title":{},"content":{"173":{"position":[[691,8],[803,8],[1843,8]]}},"keywords":{}}],["afirst",{"_index":4820,"title":{},"content":{"165":{"position":[[41,6]]}},"keywords":{}}],["aftermov",{"_index":3916,"title":{},"content":{"121":{"position":[[2118,11]]}},"keywords":{}}],["afternoon",{"_index":3026,"title":{},"content":{"90":{"position":[[3502,9]]}},"keywords":{}}],["afterward",{"_index":1857,"title":{},"content":{"41":{"position":[[637,10]]},"76":{"position":[[823,10]]},"193":{"position":[[230,10]]}},"keywords":{}}],["again",{"_index":1320,"title":{},"content":{"29":{"position":[[442,5]]},"34":{"position":[[608,5]]},"38":{"position":[[1019,5]]},"39":{"position":[[135,6]]},"45":{"position":[[3368,5]]},"57":{"position":[[138,8]]},"83":{"position":[[605,5]]},"88":{"position":[[2161,6]]},"91":{"position":[[5869,6]]},"97":{"position":[[278,6]]},"98":{"position":[[948,6]]},"115":{"position":[[656,6]]},"125":{"position":[[1352,8]]},"128":{"position":[[1243,6],[1562,6]]},"129":{"position":[[406,6]]},"161":{"position":[[432,6]]}},"keywords":{}}],["again???"",{"_index":5085,"title":{},"content":{"179":{"position":[[1589,17]]}},"keywords":{}}],["against",{"_index":1609,"title":{},"content":{"34":{"position":[[1167,7]]},"38":{"position":[[577,7]]},"45":{"position":[[2713,7]]},"57":{"position":[[483,8]]},"112":{"position":[[430,8]]},"125":{"position":[[7806,7]]},"158":{"position":[[482,7]]}},"keywords":{}}],["agent",{"_index":911,"title":{},"content":{"22":{"position":[[846,6],[888,5]]},"93":{"position":[[2454,7]]}},"keywords":{}}],["agent"",{"_index":918,"title":{},"content":{"22":{"position":[[949,12],[2447,12]]}},"keywords":{}}],["aggreg",{"_index":4878,"title":{},"content":{"169":{"position":[[127,12],[144,11]]}},"keywords":{}}],["ago",{"_index":3957,"title":{},"content":{"122":{"position":[[1239,4]]}},"keywords":{}}],["agre",{"_index":2324,"title":{},"content":{"58":{"position":[[173,6]]},"193":{"position":[[625,5]]}},"keywords":{}}],["ahead",{"_index":309,"title":{},"content":{"6":{"position":[[95,5]]},"8":{"position":[[10,5]]},"15":{"position":[[562,5]]},"30":{"position":[[866,5]]},"43":{"position":[[197,5]]},"52":{"position":[[513,5]]},"57":{"position":[[637,5]]},"60":{"position":[[73,5]]},"103":{"position":[[377,5]]},"172":{"position":[[2116,5]]}},"keywords":{}}],["ala",{"_index":3856,"title":{},"content":{"120":{"position":[[664,5]]}},"keywords":{}}],["alac",{"_index":3472,"title":{},"content":{"101":{"position":[[379,5]]}},"keywords":{}}],["alchemi",{"_index":4645,"title":{},"content":{"160":{"position":[[11,7]]}},"keywords":{}}],["alejandro",{"_index":2958,"title":{},"content":{"89":{"position":[[918,9]]}},"keywords":{}}],["alert",{"_index":3806,"title":{},"content":{"116":{"position":[[871,6]]}},"keywords":{}}],["algebra",{"_index":2833,"title":{},"content":{"86":{"position":[[854,7]]}},"keywords":{}}],["algorithm",{"_index":697,"title":{"16":{"position":[[16,9]]},"51":{"position":[[4,10]]},"103":{"position":[[12,10]]}},"content":{"40":{"position":[[2509,9]]},"73":{"position":[[177,10],[295,10],[574,10]]},"75":{"position":[[83,10],[373,10],[1106,9]]},"76":{"position":[[1819,9]]},"83":{"position":[[82,9],[340,9]]},"85":{"position":[[20,9]]},"86":{"position":[[51,10],[151,10],[614,9],[763,9],[1038,9]]},"102":{"position":[[1094,10]]},"103":{"position":[[169,10],[789,9]]},"106":{"position":[[275,9]]},"172":{"position":[[465,10],[565,10]]}},"keywords":{}}],["alias",{"_index":2707,"title":{},"content":{"76":{"position":[[1406,8]]}},"keywords":{}}],["alive!"",{"_index":4082,"title":{},"content":{"125":{"position":[[3462,13]]}},"keywords":{}}],["all_word",{"_index":2096,"title":{},"content":{"51":{"position":[[1115,9],[2280,9]]}},"keywords":{}}],["all_words.count(h",{"_index":2129,"title":{},"content":{"51":{"position":[[2469,19]]}},"keywords":{}}],["all_words[i+1",{"_index":2107,"title":{},"content":{"51":{"position":[[1385,15]]}},"keywords":{}}],["allday",{"_index":2869,"title":{},"content":{"88":{"position":[[1222,7]]}},"keywords":{}}],["alloc",{"_index":4353,"title":{"133":{"position":[[22,10]]},"138":{"position":[[27,11]]},"139":{"position":[[7,11]]},"151":{"position":[[0,11]]},"154":{"position":[[0,11]]},"158":{"position":[[8,11]]},"159":{"position":[[0,11]]},"160":{"position":[[0,11]]},"177":{"position":[[0,11]]},"191":{"position":[[0,11]]}},"content":{"132":{"position":[[550,9],[609,9],[653,12],[828,10]]},"133":{"position":[[64,9]]},"135":{"position":[[266,9],[415,11],[482,11]]},"136":{"position":[[34,11],[126,11],[727,10],[900,11]]},"137":{"position":[[46,9]]},"139":{"position":[[33,11],[186,8],[514,10],[789,9],[889,11],[983,10]]},"140":{"position":[[244,9]]},"141":{"position":[[164,8],[269,12]]},"142":{"position":[[143,9]]},"143":{"position":[[63,10],[104,10],[579,10]]},"144":{"position":[[50,9]]},"145":{"position":[[187,11]]},"146":{"position":[[198,10],[311,10],[399,10]]},"147":{"position":[[532,10]]},"148":{"position":[[91,10],[136,9],[305,11]]},"152":{"position":[[114,11],[179,10],[514,8],[910,10]]},"155":{"position":[[469,9],[528,5],[849,11]]},"156":{"position":[[214,8],[493,8],[786,9],[955,8]]},"157":{"position":[[123,9],[262,11],[634,9],[720,11]]},"158":{"position":[[285,10]]},"159":{"position":[[250,9],[398,11],[562,11],[619,9],[824,10],[935,10],[951,11],[1001,8],[1081,8]]},"160":{"position":[[1669,5],[3487,10]]},"164":{"position":[[360,9],[467,8],[1033,9],[1373,8]]},"165":{"position":[[454,11]]},"166":{"position":[[866,10]]},"168":{"position":[[134,9]]},"172":{"position":[[275,10],[696,11],[831,9],[971,9],[1049,8],[1222,10]]},"193":{"position":[[1221,10],[2132,9],[2419,11]]},"194":{"position":[[134,10],[206,11],[694,11]]},"195":{"position":[[42,10],[504,8],[740,10]]},"196":{"position":[[1923,11]]},"197":{"position":[[265,9],[1548,10]]},"198":{"position":[[496,11],[798,9],[909,11]]},"199":{"position":[[533,9],[771,9],[826,9],[1055,11],[1332,10],[1629,8]]}},"keywords":{}}],["alloc(&self",{"_index":4530,"title":{},"content":{"152":{"position":[[1323,16]]},"156":{"position":[[1406,16]]}},"keywords":{}}],["alloc::string::tostring>::to_string@plt",{"_index":4289,"title":{},"content":{"129":{"position":[[633,42]]}},"keywords":{}}],["alloc_count",{"_index":4625,"title":{},"content":{"158":{"position":[[340,15]]}},"keywords":{}}],["allocate/dealloc",{"_index":4913,"title":{},"content":{"172":{"position":[[844,19]]}},"keywords":{}}],["allocated.cel",{"_index":4633,"title":{},"content":{"159":{"position":[[704,14]]}},"keywords":{}}],["allocated.inlin",{"_index":4634,"title":{},"content":{"159":{"position":[[777,18]]}},"keywords":{}}],["allocation."",{"_index":4533,"title":{},"content":{"152":{"position":[[1433,19]]},"156":{"position":[[1516,19]]}},"keywords":{}}],["allocation/drop",{"_index":4413,"title":{},"content":{"139":{"position":[[113,19]]}},"keywords":{}}],["allow",{"_index":377,"title":{},"content":{"7":{"position":[[67,6]]},"20":{"position":[[104,5]]},"45":{"position":[[1118,6]]},"61":{"position":[[112,5],[923,6]]},"73":{"position":[[640,6]]},"76":{"position":[[656,5],[2978,5]]},"95":{"position":[[134,6]]},"97":{"position":[[1386,6],[5264,6]]},"113":{"position":[[1102,5]]},"116":{"position":[[14,6]]},"117":{"position":[[121,6]]},"121":{"position":[[1292,7]]},"132":{"position":[[624,6]]},"141":{"position":[[99,5]]},"159":{"position":[[450,7]]},"173":{"position":[[565,7]]},"174":{"position":[[884,6]]},"179":{"position":[[508,6]]},"184":{"position":[[799,7]]},"186":{"position":[[41,8],[407,7]]},"188":{"position":[[700,7]]}},"keywords":{}}],["along",{"_index":2297,"title":{},"content":{"55":{"position":[[52,5]]},"112":{"position":[[1040,5]]},"150":{"position":[[625,5]]}},"keywords":{}}],["alpha",{"_index":876,"title":{"22":{"position":[[38,6]]}},"content":{},"keywords":{}}],["alpha=.5",{"_index":2999,"title":{},"content":{"90":{"position":[[1599,9],[1748,9],[2892,9]]}},"keywords":{}}],["alreadi",{"_index":977,"title":{},"content":{"22":{"position":[[2772,7]]},"30":{"position":[[9617,7]]},"43":{"position":[[184,7]]},"51":{"position":[[3483,7]]},"60":{"position":[[6,7]]},"93":{"position":[[1063,7]]},"122":{"position":[[343,7]]},"124":{"position":[[620,7]]},"125":{"position":[[1052,7],[1839,7],[2149,7]]},"137":{"position":[[97,7]]},"145":{"position":[[208,7]]},"163":{"position":[[605,7]]},"176":{"position":[[1055,7]]},"195":{"position":[[661,7]]}},"keywords":{}}],["alright",{"_index":2287,"title":{},"content":{"53":{"position":[[2227,8]]},"125":{"position":[[10065,8]]},"161":{"position":[[1581,8]]}},"keywords":{}}],["alsocaptur",{"_index":5328,"title":{},"content":{"196":{"position":[[336,11]]}},"keywords":{}}],["altern",{"_index":2624,"title":{"157":{"position":[[5,13]]}},"content":{"73":{"position":[[371,12]]},"112":{"position":[[711,12]]},"157":{"position":[[294,12],[404,12]]},"158":{"position":[[53,11]]},"172":{"position":[[1210,11]]},"174":{"position":[[820,12]]}},"keywords":{}}],["altogeth",{"_index":4996,"title":{},"content":{"174":{"position":[[1189,10]]}},"keywords":{}}],["alway",{"_index":1204,"title":{},"content":{"28":{"position":[[212,6]]},"172":{"position":[[1001,6]]},"198":{"position":[[873,6]]}},"keywords":{}}],["am/pm",{"_index":3890,"title":{},"content":{"121":{"position":[[994,5]]}},"keywords":{}}],["amaz",{"_index":3846,"title":{},"content":{"118":{"position":[[349,8]]}},"keywords":{}}],["ambiti",{"_index":3991,"title":{},"content":{"124":{"position":[[104,9]]}},"keywords":{}}],["amiss",{"_index":92,"title":{},"content":{"2":{"position":[[258,5]]}},"keywords":{}}],["amongst",{"_index":3560,"title":{},"content":{"104":{"position":[[780,7]]}},"keywords":{}}],["amor",{"_index":5006,"title":{},"content":{"175":{"position":[[355,5]]}},"keywords":{}}],["amount",{"_index":1525,"title":{},"content":{"32":{"position":[[592,6],[1178,6],[1292,6]]},"33":{"position":[[254,6]]},"61":{"position":[[437,6]]},"82":{"position":[[40,6]]},"86":{"position":[[1100,6]]},"101":{"position":[[164,6]]},"106":{"position":[[385,6]]},"125":{"position":[[3383,6]]},"140":{"position":[[120,6]]},"160":{"position":[[219,6],[2853,6]]},"188":{"position":[[1803,6]]}},"keywords":{}}],["amp",{"_index":778,"title":{},"content":{"20":{"position":[[590,5],[623,5],[650,5],[679,5],[718,5]]},"64":{"position":[[879,5]]},"65":{"position":[[1724,5]]},"70":{"position":[[309,5],[328,5],[347,5],[367,5],[387,5],[407,5],[443,5],[483,5],[503,5],[523,5],[543,5],[563,5],[582,5],[642,5]]},"71":{"position":[[409,5],[428,5],[448,5],[468,5],[488,5],[508,5],[543,5],[583,5],[602,5],[622,5],[642,5],[662,5],[682,5],[742,5]]},"74":{"position":[[602,5],[620,5],[641,5],[657,5],[679,5],[1098,6],[1699,6]]},"90":{"position":[[1970,5],[3109,5]]}},"keywords":{}}],["amp;&",{"_index":4078,"title":{},"content":{"125":{"position":[[3146,10],[5257,10],[5374,10],[5614,10],[5805,10],[5922,10]]}},"keywords":{}}],["amp;>",{"_index":1543,"title":{},"content":{"32":{"position":[[1630,9],[1693,9],[1776,9],[1834,9]]}},"keywords":{}}],["amp;'stat",{"_index":3340,"title":{},"content":{"96":{"position":[[1312,13]]}},"keywords":{}}],["amp;[u8",{"_index":4780,"title":{},"content":{"163":{"position":[[1773,10]]}},"keywords":{}}],["amp;[u8]>",{"_index":4782,"title":{},"content":{"163":{"position":[[1812,13]]}},"keywords":{}}],["amp;builder).unwrap",{"_index":3755,"title":{},"content":{"113":{"position":[[1715,23]]}},"keywords":{}}],["amp;cel",{"_index":5078,"title":{},"content":{"179":{"position":[[1054,11],[1155,11]]}},"keywords":{}}],["amp;dyn",{"_index":5346,"title":{},"content":{"197":{"position":[[634,10],[951,8]]}},"keywords":{}}],["amp;end",{"_index":5298,"title":{},"content":{"193":{"position":[[1950,10],[2905,10]]}},"keywords":{}}],["amp;hashmap<u32",{"_index":5385,"title":{},"content":{"199":{"position":[[1541,20]]}},"keywords":{}}],["amp;hashmap::new",{"_index":4392,"title":{},"content":{"136":{"position":[[448,20]]}},"keywords":{}}],["amp;middl",{"_index":5295,"title":{},"content":{"193":{"position":[[1900,13],[2855,13]]}},"keywords":{}}],["amp;mut",{"_index":3329,"title":{},"content":{"96":{"position":[[673,8],[1092,8],[1622,8],[2168,8]]},"97":{"position":[[1565,8],[3659,8],[4445,8],[4881,8]]},"113":{"position":[[1829,8]]},"115":{"position":[[284,8]]},"116":{"position":[[384,8]]},"117":{"position":[[1173,8]]},"144":{"position":[[189,8]]}},"keywords":{}}],["amp;point",{"_index":5280,"title":{},"content":{"193":{"position":[[1067,11],[1082,11],[2471,11],[2486,11],[3556,11],[3571,11]]}},"keywords":{}}],["amp;refcell<u8>",{"_index":5070,"title":{},"content":{"179":{"position":[[407,23],[927,23]]}},"keywords":{}}],["amp;self.messag",{"_index":3427,"title":{},"content":{"97":{"position":[[5661,17]]}},"keywords":{}}],["amp;str",{"_index":4387,"title":{},"content":{"136":{"position":[[285,9]]}},"keywords":{}}],["amp;vec<u32>",{"_index":5381,"title":{},"content":{"199":{"position":[[1249,20],[1392,20]]}},"keywords":{}}],["anafterthought",{"_index":4833,"title":{},"content":{"165":{"position":[[1102,15]]}},"keywords":{}}],["analysi",{"_index":57,"title":{},"content":{"1":{"position":[[642,8]]},"28":{"position":[[136,8],[450,8],[538,9]]},"29":{"position":[[56,9]]},"30":{"position":[[7751,8]]},"45":{"position":[[1103,9]]},"51":{"position":[[1479,8]]},"54":{"position":[[152,8]]},"62":{"position":[[1795,9]]},"65":{"position":[[2134,8]]},"66":{"position":[[453,8],[699,8]]},"91":{"position":[[3236,8]]},"92":{"position":[[31,9],[1048,8]]},"93":{"position":[[1121,8]]},"106":{"position":[[1027,8]]}},"keywords":{}}],["analyt",{"_index":1188,"title":{},"content":{"26":{"position":[[877,9]]}},"keywords":{}}],["analyz",{"_index":2288,"title":{},"content":{"54":{"position":[[66,7]]}},"keywords":{}}],["and_then",{"_index":4479,"title":{},"content":{"147":{"position":[[370,10]]}},"keywords":{}}],["andcach",{"_index":4920,"title":{},"content":{"172":{"position":[[1389,8]]}},"keywords":{}}],["andchar",{"_index":4278,"title":{},"content":{"129":{"position":[[259,7]]}},"keywords":{}}],["andcriterion",{"_index":4543,"title":{},"content":{"153":{"position":[[324,13]]}},"keywords":{}}],["andgap",{"_index":5024,"title":{},"content":{"175":{"position":[[1029,6]]}},"keywords":{}}],["andjavascriptboth",{"_index":5327,"title":{},"content":{"196":{"position":[[264,17]]}},"keywords":{}}],["andmor",{"_index":4826,"title":{},"content":{"165":{"position":[[295,7]]}},"keywords":{}}],["andmutex",{"_index":4608,"title":{},"content":{"157":{"position":[[381,10]]}},"keywords":{}}],["andnetwork",{"_index":4426,"title":{},"content":{"139":{"position":[[648,14]]}},"keywords":{}}],["andshenandoah",{"_index":4910,"title":{},"content":{"172":{"position":[[581,14]]}},"keywords":{}}],["andspin",{"_index":4610,"title":{},"content":{"157":{"position":[[457,8]]}},"keywords":{}}],["andspin::onc",{"_index":4612,"title":{},"content":{"157":{"position":[[517,13]]}},"keywords":{}}],["andstr",{"_index":4594,"title":{},"content":{"156":{"position":[[377,9]]}},"keywords":{}}],["andtim",{"_index":3853,"title":{},"content":{"120":{"position":[[497,8]]}},"keywords":{}}],["andtrait",{"_index":3397,"title":{},"content":{"97":{"position":[[2763,9]]}},"keywords":{}}],["anexampl",{"_index":4163,"title":{},"content":{"125":{"position":[[8368,9]]}},"keywords":{}}],["aninteg",{"_index":4241,"title":{},"content":{"127":{"position":[[1170,9]]}},"keywords":{}}],["anneal",{"_index":2620,"title":{"73":{"position":[[10,10]]},"75":{"position":[[25,10]]},"84":{"position":[[27,10]]},"85":{"position":[[14,11]]}},"content":{"73":{"position":[[285,9],[522,9],[630,9]]},"75":{"position":[[73,9]]},"78":{"position":[[366,9],[962,9]]},"79":{"position":[[166,9]]},"80":{"position":[[188,9]]},"81":{"position":[[167,9]]},"82":{"position":[[966,9]]},"85":{"position":[[64,10],[483,9]]},"86":{"position":[[391,9],[488,9]]}},"keywords":{}}],["annot",{"_index":5160,"title":{},"content":{"188":{"position":[[838,10],[4392,10]]},"189":{"position":[[988,10]]}},"keywords":{}}],["annotationassert",{"_index":5152,"title":{},"content":{"188":{"position":[[362,17]]}},"keywords":{}}],["announc",{"_index":3162,"title":{},"content":{"91":{"position":[[4578,9],[4751,12]]},"92":{"position":[[1398,12],[1449,13]]}},"keywords":{}}],["anoft",{"_index":3967,"title":{},"content":{"123":{"position":[[50,5]]}},"keywords":{}}],["anonym",{"_index":3376,"title":{},"content":{"97":{"position":[[1685,9],[4290,9],[4375,9],[6344,9]]},"196":{"position":[[15,9]]}},"keywords":{}}],["anoth",{"_index":1440,"title":{},"content":{"30":{"position":[[7959,7]]},"40":{"position":[[1465,7]]},"73":{"position":[[857,7]]},"89":{"position":[[101,8]]},"95":{"position":[[360,7]]},"97":{"position":[[1427,7],[1677,7],[4503,7],[4640,7],[5170,7],[5452,7]]},"105":{"position":[[363,7]]},"121":{"position":[[1607,7]]},"125":{"position":[[7062,7]]},"141":{"position":[[364,7]]},"193":{"position":[[180,7]]},"195":{"position":[[751,7]]},"196":{"position":[[799,7]]}},"keywords":{}}],["anownership",{"_index":4671,"title":{},"content":{"160":{"position":[[1097,11]]}},"keywords":{}}],["answer",{"_index":180,"title":{},"content":{"3":{"position":[[881,7]]},"44":{"position":[[1211,7]]},"112":{"position":[[449,6],[531,6]]},"125":{"position":[[608,6]]},"128":{"position":[[95,6]]},"150":{"position":[[932,7]]},"159":{"position":[[110,7]]},"193":{"position":[[245,7]]}},"keywords":{}}],["anti",{"_index":1899,"title":{},"content":{"44":{"position":[[163,4]]}},"keywords":{}}],["anymor",{"_index":2064,"title":{},"content":{"50":{"position":[[65,8]]}},"keywords":{}}],["anyon",{"_index":1837,"title":{},"content":{"40":{"position":[[3390,6]]},"50":{"position":[[183,6]]},"98":{"position":[[499,7]]},"104":{"position":[[1919,6]]},"120":{"position":[[1016,6]]},"125":{"position":[[3549,6]]}},"keywords":{}}],["anyone'sactu",{"_index":4020,"title":{},"content":{"125":{"position":[[573,14]]}},"keywords":{}}],["anyth",{"_index":1576,"title":{},"content":{"33":{"position":[[505,8]]},"51":{"position":[[3089,8]]},"125":{"position":[[2619,9],[10521,8]]},"153":{"position":[[124,9],[900,8]]}},"keywords":{}}],["anyway",{"_index":2669,"title":{},"content":{"75":{"position":[[898,8]]},"76":{"position":[[3009,8]]}},"keywords":{}}],["anywher",{"_index":2327,"title":{},"content":{"58":{"position":[[222,8]]},"181":{"position":[[559,9]]},"199":{"position":[[1221,9]]}},"keywords":{}}],["ap",{"_index":3474,"title":{},"content":{"101":{"position":[[404,6]]}},"keywords":{}}],["aper",{"_index":4855,"title":{},"content":{"168":{"position":[[24,4]]},"169":{"position":[[24,4]]}},"keywords":{}}],["api",{"_index":95,"title":{},"content":{"2":{"position":[[331,3],[532,4]]},"30":{"position":[[8742,3],[9507,4]]},"59":{"position":[[15,3]]},"97":{"position":[[2334,4]]},"117":{"position":[[26,3]]},"125":{"position":[[4436,3],[8755,4],[9689,4],[11142,3]]},"164":{"position":[[1347,3]]},"165":{"position":[[1198,4]]},"188":{"position":[[139,4]]},"189":{"position":[[554,3]]}},"keywords":{}}],["api'",{"_index":4703,"title":{},"content":{"160":{"position":[[3498,5]]}},"keywords":{}}],["api_key",{"_index":1601,"title":{},"content":{"34":{"position":[[1024,7]]},"39":{"position":[[535,7]]}},"keywords":{}}],["api_key=api_key",{"_index":1627,"title":{},"content":{"34":{"position":[[1683,16]]},"39":{"position":[[2245,16]]}},"keywords":{}}],["apikey",{"_index":1462,"title":{},"content":{"30":{"position":[[8712,6],[8891,6],[8985,6]]}},"keywords":{}}],["apion",{"_index":4209,"title":{},"content":{"125":{"position":[[11332,5]]}},"keywords":{}}],["apocalyps",{"_index":4497,"title":{},"content":{"150":{"position":[[481,11]]}},"keywords":{}}],["apolog",{"_index":4380,"title":{},"content":{"135":{"position":[[537,9]]}},"keywords":{}}],["app",{"_index":29,"title":{"125":{"position":[[19,4]]}},"content":{"1":{"position":[[326,3]]},"3":{"position":[[371,3],[407,3]]},"125":{"position":[[1472,3],[1479,3],[1730,5],[3578,4],[3833,3],[6224,4],[6263,3],[7026,3],[9739,3],[11526,3]]}},"keywords":{}}],["app"",{"_index":225,"title":{},"content":{"4":{"position":[[82,9]]}},"keywords":{}}],["appeal",{"_index":43,"title":{},"content":{"1":{"position":[[508,6]]}},"keywords":{}}],["appear",{"_index":1129,"title":{},"content":{"24":{"position":[[3201,7],[3269,7]]},"25":{"position":[[2618,7]]},"30":{"position":[[7453,7]]},"40":{"position":[[3410,7]]},"64":{"position":[[1955,6]]},"122":{"position":[[1264,7],[1393,7]]}},"keywords":{}}],["append",{"_index":1025,"title":{},"content":{"24":{"position":[[485,9]]},"25":{"position":[[210,9]]}},"keywords":{}}],["appendix",{"_index":1863,"title":{"47":{"position":[[0,9]]}},"content":{"43":{"position":[[250,8]]},"91":{"position":[[1832,8],[2736,8]]},"92":{"position":[[548,8]]},"93":{"position":[[1183,8]]}},"keywords":{}}],["appl",{"_index":2841,"title":{},"content":{"88":{"position":[[238,6],[2269,5],[3618,5]]},"89":{"position":[[267,5],[323,5]]},"105":{"position":[[3130,6],[3140,6]]},"172":{"position":[[2372,6]]}},"keywords":{}}],["appli",{"_index":1307,"title":{"32":{"position":[[0,8]]}},"content":{"28":{"position":[[4025,5]]},"32":{"position":[[195,5]]},"54":{"position":[[161,7]]},"96":{"position":[[1296,7]]},"97":{"position":[[5307,5]]},"105":{"position":[[937,7]]},"106":{"position":[[1060,7]]},"176":{"position":[[796,5]]}},"keywords":{}}],["applic",{"_index":118,"title":{"60":{"position":[[15,12]]}},"content":{"2":{"position":[[670,12]]},"3":{"position":[[615,11],[1063,11]]},"59":{"position":[[111,12]]},"60":{"position":[[36,11]]},"61":{"position":[[118,12],[230,12],[284,12],[383,12],[579,11],[704,11],[742,12],[853,12],[933,11],[1055,11],[1184,11]]},"97":{"position":[[756,12]]},"98":{"position":[[83,12],[808,13]]},"125":{"position":[[231,12],[2945,11],[2993,12],[6345,12],[10103,11],[10800,11]]},"134":{"position":[[133,12]]},"139":{"position":[[414,13]]},"160":{"position":[[2062,12],[2746,11]]},"173":{"position":[[1547,12]]},"174":{"position":[[454,12],[841,12]]},"190":{"position":[[474,12]]}},"keywords":{}}],["application/wasm",{"_index":4093,"title":{},"content":{"125":{"position":[[4313,16]]}},"keywords":{}}],["applicationus",{"_index":4102,"title":{},"content":{"125":{"position":[[4861,14]]}},"keywords":{}}],["approach",{"_index":1976,"title":{},"content":{"45":{"position":[[1044,8]]},"102":{"position":[[33,8]]},"132":{"position":[[331,8]]},"182":{"position":[[80,9]]}},"keywords":{}}],["appropri",{"_index":5264,"title":{},"content":{"190":{"position":[[957,12]]}},"keywords":{}}],["approx",{"_index":2475,"title":{},"content":{"64":{"position":[[1135,9]]}},"keywords":{}}],["approxim",{"_index":1665,"title":{},"content":{"34":{"position":[[3581,13]]},"57":{"position":[[64,13]]},"102":{"position":[[538,11],[793,13]]}},"keywords":{}}],["aprestart",{"_index":4133,"title":{},"content":{"125":{"position":[[6297,9]]}},"keywords":{}}],["apt",{"_index":3667,"title":{},"content":{"108":{"position":[[426,3]]}},"keywords":{}}],["arc::new(0",{"_index":4586,"title":{},"content":{"155":{"position":[[1511,12]]}},"keywords":{}}],["arcan",{"_index":4493,"title":{},"content":{"150":{"position":[[321,6]]}},"keywords":{}}],["area",{"_index":1438,"title":{},"content":{"30":{"position":[[7792,5],[7864,5]]},"90":{"position":[[5023,4]]},"91":{"position":[[4862,4]]},"125":{"position":[[1823,5]]},"130":{"position":[[375,5]]},"135":{"position":[[586,4]]}},"keywords":{}}],["arefresh",{"_index":4716,"title":{},"content":{"160":{"position":[[4054,10]]}},"keywords":{}}],["areher",{"_index":4854,"title":{},"content":{"167":{"position":[[152,8]]}},"keywords":{}}],["aren't",{"_index":286,"title":{},"content":{"4":{"position":[[1250,6]]},"33":{"position":[[346,6]]},"44":{"position":[[1852,6]]},"112":{"position":[[1023,6]]},"125":{"position":[[7337,6]]},"129":{"position":[[163,6]]},"152":{"position":[[126,6]]},"179":{"position":[[287,6]]},"184":{"position":[[868,6]]},"190":{"position":[[246,6],[780,6]]},"195":{"position":[[871,6]]},"197":{"position":[[1536,6]]}},"keywords":{}}],["arg",{"_index":933,"title":{},"content":{"22":{"position":[[1296,6]]},"93":{"position":[[1564,6]]},"127":{"position":[[627,5],[1277,5]]}},"keywords":{}}],["args=[n",{"_index":5181,"title":{},"content":{"188":{"position":[[2091,9],[2132,9],[2461,9],[2502,9],[2997,9],[3040,9]]},"189":{"position":[[2121,9],[2161,9],[2404,9],[2444,9],[2691,9],[2733,9]]}},"keywords":{}}],["argument",{"_index":3862,"title":{"193":{"position":[[9,10]]}},"content":{"120":{"position":[[853,8]]},"189":{"position":[[391,8],[459,8],[733,10]]},"193":{"position":[[398,9],[1303,10],[2016,9],[2968,10]]},"196":{"position":[[49,9],[400,9],[438,9]]}},"keywords":{}}],["arm",{"_index":4399,"title":{},"content":{"136":{"position":[[766,5]]}},"keywords":{}}],["around",{"_index":1806,"title":{},"content":{"40":{"position":[[1225,6],[1256,6],[1439,6],[2489,6]]},"117":{"position":[[2135,6]]},"128":{"position":[[963,6]]},"164":{"position":[[534,6],[1122,6]]},"165":{"position":[[852,6]]},"178":{"position":[[441,6]]},"189":{"position":[[2050,6]]},"193":{"position":[[385,6]]}},"keywords":{}}],["arrang",{"_index":4917,"title":{},"content":{"172":{"position":[[1341,8]]},"193":{"position":[[266,8]]}},"keywords":{}}],["array",{"_index":2690,"title":{"153":{"position":[[4,5]]},"195":{"position":[[0,7]]}},"content":{"76":{"position":[[578,5]]},"90":{"position":[[776,6],[1026,5],[2161,6],[2411,5]]},"159":{"position":[[669,7]]},"195":{"position":[[5,5],[70,5],[999,6]]}},"keywords":{}}],["array([0",{"_index":1874,"title":{},"content":{"43":{"position":[[621,9]]}},"keywords":{}}],["array.shape[1",{"_index":2982,"title":{},"content":{"90":{"position":[[986,15],[2371,15]]}},"keywords":{}}],["arriv",{"_index":3656,"title":{},"content":{"106":{"position":[[849,8]]}},"keywords":{}}],["arrowprops=dict(facecolor='black",{"_index":3049,"title":{},"content":{"90":{"position":[[4331,34]]}},"keywords":{}}],["arrowprops={'facecolor",{"_index":3054,"title":{},"content":{"90":{"position":[[4422,24],[4539,24],[4645,24]]}},"keywords":{}}],["art",{"_index":3858,"title":{},"content":{"120":{"position":[[702,3]]},"150":{"position":[[328,5]]}},"keywords":{}}],["articl",{"_index":881,"title":{},"content":{"22":{"position":[[65,7],[133,8],[220,8],[250,7],[282,8],[1142,8],[3012,8]]},"24":{"position":[[2483,8]]},"25":{"position":[[2206,8]]},"160":{"position":[[63,8]]}},"keywords":{}}],["article_data",{"_index":983,"title":{},"content":{"22":{"position":[[2908,12]]}},"keywords":{}}],["article_df",{"_index":986,"title":{},"content":{"22":{"position":[[3030,10]]},"23":{"position":[[222,10]]}},"keywords":{}}],["article_df.sort_values(by='date').iloc[0]['d",{"_index":1002,"title":{},"content":{"23":{"position":[[290,49]]}},"keywords":{}}],["article_html",{"_index":966,"title":{},"content":{"22":{"position":[[2389,12]]}},"keywords":{}}],["article_html.text",{"_index":973,"title":{},"content":{"22":{"position":[[2629,19]]}},"keywords":{}}],["article_list",{"_index":981,"title":{},"content":{"22":{"position":[[2866,12],[2960,13]]}},"keywords":{}}],["article_page_url",{"_index":905,"title":{},"content":{"22":{"position":[[681,17],[798,18]]}},"keywords":{}}],["articlelistpars",{"_index":921,"title":{},"content":{"22":{"position":[[997,19]]}},"keywords":{}}],["articlelistparser(htmlpars",{"_index":883,"title":{},"content":{"22":{"position":[[149,30]]}},"keywords":{}}],["articlereturnpars",{"_index":969,"title":{},"content":{"22":{"position":[[2495,21]]}},"keywords":{}}],["articlereturnparser(htmlpars",{"_index":924,"title":{},"content":{"22":{"position":[[1094,32]]}},"keywords":{}}],["articles_html",{"_index":915,"title":{},"content":{"22":{"position":[[894,13]]}},"keywords":{}}],["arust",{"_index":4062,"title":{},"content":{"125":{"position":[[2358,5]]}},"keywords":{}}],["ashot",{"_index":4354,"title":{},"content":{"132":{"position":[[774,6]]}},"keywords":{}}],["asid",{"_index":5242,"title":{},"content":{"189":{"position":[[1833,6]]}},"keywords":{}}],["ask",{"_index":1933,"title":{},"content":{"44":{"position":[[1246,5]]},"66":{"position":[[708,4]]},"93":{"position":[[986,3]]},"108":{"position":[[161,3]]},"123":{"position":[[344,3]]}},"keywords":{}}],["asm",{"_index":4719,"title":{},"content":{"160":{"position":[[4201,5]]}},"keywords":{}}],["asm.j",{"_index":4064,"title":{},"content":{"125":{"position":[[2540,6]]}},"keywords":{}}],["aspeci",{"_index":4806,"title":{},"content":{"164":{"position":[[551,8]]}},"keywords":{}}],["assembl",{"_index":4247,"title":{},"content":{"128":{"position":[[71,8],[365,8],[1182,8],[1645,8],[1692,9]]},"129":{"position":[[353,9],[480,9],[747,8]]},"130":{"position":[[566,9]]},"152":{"position":[[669,8]]},"155":{"position":[[1368,8],[1430,8],[1492,8],[1555,8]]},"156":{"position":[[563,8]]},"159":{"position":[[207,9]]},"160":{"position":[[3999,8]]},"163":{"position":[[714,8]]},"181":{"position":[[145,8],[267,8],[609,8]]},"183":{"position":[[370,8],[516,8],[723,8]]},"192":{"position":[[671,9]]},"193":{"position":[[286,8],[992,8],[2188,8],[2296,8],[3105,9]]},"194":{"position":[[760,9]]},"196":{"position":[[711,8],[1013,8],[1223,8],[1634,8],[1836,8]]},"197":{"position":[[799,9],[980,9]]},"199":{"position":[[1119,8]]}},"keywords":{}}],["assert",{"_index":5224,"title":{},"content":{"188":{"position":[[4406,6]]}},"keywords":{}}],["assert_eq!(boxed_reader.get_i",{"_index":3804,"title":{},"content":{"116":{"position":[[793,32]]}},"keywords":{}}],["assert_eq!(boxed_reader.get_x",{"_index":3803,"title":{},"content":{"116":{"position":[[755,32]]}},"keywords":{}}],["assert_eq!(point_reader.get_i",{"_index":3764,"title":{},"content":{"113":{"position":[[2368,32]]},"115":{"position":[[773,32]]}},"keywords":{}}],["assert_eq!(point_reader.get_x",{"_index":3763,"title":{},"content":{"113":{"position":[[2330,32]]},"115":{"position":[[735,32]]}},"keywords":{}}],["assert_eq!(point_root.get_i",{"_index":3835,"title":{},"content":{"117":{"position":[[1815,30]]}},"keywords":{}}],["assert_eq!(point_root.get_x",{"_index":3834,"title":{},"content":{"117":{"position":[[1779,30]]}},"keywords":{}}],["assert_no_alloc",{"_index":4462,"title":{},"content":{"145":{"position":[[410,18]]},"147":{"position":[[577,18]]}},"keywords":{}}],["assert_no_alloc!(async_capac",{"_index":4480,"title":{},"content":{"147":{"position":[[465,35]]}},"keywords":{}}],["assert_no_alloc!(async_capacity().poll().unwrap",{"_index":4481,"title":{},"content":{"147":{"position":[[602,51]]}},"keywords":{}}],["assert_no_alloc!(v.push(5",{"_index":4458,"title":{},"content":{"145":{"position":[[236,28]]}},"keywords":{}}],["asset",{"_index":172,"title":{},"content":{"3":{"position":[[771,5]]},"6":{"position":[[78,7]]},"38":{"position":[[325,7]]}},"keywords":{}}],["assign",{"_index":4260,"title":{},"content":{"128":{"position":[[486,6]]},"129":{"position":[[2580,6]]},"198":{"position":[[836,11]]}},"keywords":{}}],["associ",{"_index":4664,"title":{},"content":{"160":{"position":[[706,10]]},"174":{"position":[[236,10],[570,10]]},"197":{"position":[[169,10]]}},"keywords":{}}],["assum",{"_index":459,"title":{},"content":{"9":{"position":[[126,6],[381,7],[589,7]]},"10":{"position":[[365,8]]},"14":{"position":[[596,6]]},"30":{"position":[[1098,6],[2697,6],[7846,6]]},"33":{"position":[[1201,9]]},"34":{"position":[[393,7],[501,8],[3641,6]]},"46":{"position":[[516,8]]},"90":{"position":[[786,6],[2171,6]]},"91":{"position":[[2575,7],[3892,6]]},"92":{"position":[[387,7]]},"97":{"position":[[3126,8]]},"105":{"position":[[534,6],[706,6]]},"110":{"position":[[270,8]]},"112":{"position":[[617,8]]},"115":{"position":[[124,9]]},"116":{"position":[[224,9]]},"117":{"position":[[1016,9]]},"134":{"position":[[1,8]]},"160":{"position":[[3537,6]]},"193":{"position":[[809,6]]}},"keywords":{}}],["assumpt",{"_index":2745,"title":{},"content":{"77":{"position":[[142,10]]},"116":{"position":[[2878,11]]}},"keywords":{}}],["assur",{"_index":2576,"title":{},"content":{"69":{"position":[[153,9]]}},"keywords":{}}],["astro",{"_index":197,"title":{},"content":{"3":{"position":[[1197,5]]}},"keywords":{}}],["aswebassembl",{"_index":4011,"title":{},"content":{"125":{"position":[[257,13]]}},"keywords":{}}],["async_capac",{"_index":4474,"title":{},"content":{"147":{"position":[[192,16],[429,17]]}},"keywords":{}}],["asynchron",{"_index":4471,"title":{},"content":{"147":{"position":[[98,12]]}},"keywords":{}}],["at.w",{"_index":3710,"title":{},"content":{"111":{"position":[[746,5]]}},"keywords":{}}],["atcrates.io",{"_index":4484,"title":{},"content":{"148":{"position":[[379,11]]}},"keywords":{}}],["athena",{"_index":540,"title":{"13":{"position":[[0,6]]}},"content":{"13":{"position":[[83,6],[96,6],[1261,6],[1529,8],[1860,6],[2262,6]]},"14":{"position":[[76,6]]}},"keywords":{}}],["athread_loc",{"_index":4615,"title":{},"content":{"157":{"position":[[680,14]]}},"keywords":{}}],["atomicbool",{"_index":4527,"title":{},"content":{"152":{"position":[[1208,10]]},"156":{"position":[[1291,10]]}},"keywords":{}}],["atomicbool::new(fals",{"_index":4528,"title":{},"content":{"152":{"position":[[1221,23]]},"156":{"position":[[1304,23]]}},"keywords":{}}],["attack",{"_index":3352,"title":{},"content":{"96":{"position":[[2102,7]]}},"keywords":{}}],["attempt",{"_index":164,"title":{"78":{"position":[[0,7]]},"79":{"position":[[0,7]]},"80":{"position":[[0,7]]},"81":{"position":[[0,7]]},"82":{"position":[[0,7]]},"115":{"position":[[0,7]]},"116":{"position":[[0,7]]},"117":{"position":[[0,7]]}},"content":{"3":{"position":[[591,10],[922,8]]},"44":{"position":[[10,7]]},"45":{"position":[[2758,7]]},"97":{"position":[[2674,8],[3944,7],[4087,9],[5334,7]]},"104":{"position":[[616,8]]},"115":{"position":[[12,8]]},"116":{"position":[[173,7]]},"117":{"position":[[206,9]]},"118":{"position":[[258,8]]},"121":{"position":[[325,9]]},"125":{"position":[[2915,10],[4136,10],[8213,10],[10479,8]]},"160":{"position":[[434,8]]},"165":{"position":[[48,7]]},"176":{"position":[[782,10]]},"188":{"position":[[3381,10],[3491,10]]}},"keywords":{}}],["attent",{"_index":3789,"title":{},"content":{"115":{"position":[[2594,9]]},"132":{"position":[[266,9]]},"161":{"position":[[693,9]]},"176":{"position":[[106,9]]}},"keywords":{}}],["attr",{"_index":889,"title":{},"content":{"22":{"position":[[327,7],[413,6],[503,6],[1394,7],[1456,6]]},"93":{"position":[[1663,7]]}},"keywords":{}}],["attribut",{"_index":676,"title":{},"content":{"15":{"position":[[694,9]]},"133":{"position":[[203,10]]},"152":{"position":[[250,10]]},"175":{"position":[[695,10]]},"193":{"position":[[2104,10]]}},"keywords":{}}],["attrs))[0][1",{"_index":899,"title":{},"content":{"22":{"position":[[555,13],[1518,13]]}},"keywords":{}}],["audienc",{"_index":3390,"title":{},"content":{"97":{"position":[[2187,8],[5884,8]]}},"keywords":{}}],["audio",{"_index":83,"title":{"99":{"position":[[4,5]]},"101":{"position":[[24,5]]}},"content":{"2":{"position":[[132,5],[170,5],[317,5],[808,5]]},"3":{"position":[[988,5],[1371,5]]},"100":{"position":[[35,5],[456,5]]},"101":{"position":[[1,5],[398,5],[1109,5]]},"102":{"position":[[54,6]]},"103":{"position":[[5,5],[99,5],[470,5],[2003,5],[2198,5]]},"104":{"position":[[312,6],[1844,5]]},"105":{"position":[[84,5],[338,5]]},"106":{"position":[[27,5],[395,5],[546,5]]}},"keywords":{}}],["audio(data=reconstructed[start:end",{"_index":3540,"title":{},"content":{"103":{"position":[[1790,36],[2107,36]]},"105":{"position":[[2744,36],[2942,36],[3217,36]]}},"keywords":{}}],["audio(data=tabulasa[start:end",{"_index":3518,"title":{},"content":{"103":{"position":[[647,30]]}},"keywords":{}}],["audio,self",{"_index":4424,"title":{},"content":{"139":{"position":[[623,10]]}},"keywords":{}}],["august",{"_index":1261,"title":{},"content":{"28":{"position":[[1903,10],[4215,7]]},"30":{"position":[[1033,6],[1416,9]]},"40":{"position":[[1243,6],[2496,6],[3176,7]]}},"keywords":{}}],["authent",{"_index":2342,"title":{},"content":{"59":{"position":[[124,14]]},"61":{"position":[[1485,13]]}},"keywords":{}}],["author",{"_index":2390,"title":{},"content":{"61":{"position":[[2287,14]]},"74":{"position":[[930,6]]},"76":{"position":[[287,7]]},"97":{"position":[[507,6]]},"109":{"position":[[314,7]]},"142":{"position":[[204,7]]},"166":{"position":[[34,6]]}},"keywords":{}}],["authtoken=quandl_key",{"_index":2859,"title":{},"content":{"88":{"position":[[880,21]]},"93":{"position":[[4295,21]]}},"keywords":{}}],["auto",{"_index":3712,"title":{},"content":{"112":{"position":[[106,4]]}},"keywords":{}}],["autocal",{"_index":301,"title":{"5":{"position":[[0,12]]}},"content":{"6":{"position":[[23,12]]},"12":{"position":[[103,12]]}},"keywords":{}}],["autom",{"_index":3962,"title":{},"content":{"122":{"position":[[1437,10]]},"139":{"position":[[260,9]]}},"keywords":{}}],["automat",{"_index":542,"title":{},"content":{"13":{"position":[[139,13]]},"14":{"position":[[294,13]]},"75":{"position":[[714,13]]},"76":{"position":[[2833,13]]},"90":{"position":[[3432,13]]},"185":{"position":[[226,13]]}},"keywords":{}}],["avail",{"_index":2340,"title":{},"content":{"59":{"position":[[19,9]]},"62":{"position":[[1709,9]]},"97":{"position":[[2923,9]]},"108":{"position":[[621,10]]},"112":{"position":[[750,10],[1690,9]]},"122":{"position":[[783,10]]},"142":{"position":[[114,10]]},"155":{"position":[[511,9]]},"157":{"position":[[307,10]]},"160":{"position":[[1483,10],[1913,10],[3921,9],[4222,10]]},"161":{"position":[[105,10]]},"175":{"position":[[380,10]]},"176":{"position":[[227,10]]}},"keywords":{}}],["availableov",{"_index":4070,"title":{},"content":{"125":{"position":[[2780,13]]}},"keywords":{}}],["averag",{"_index":739,"title":{},"content":{"19":{"position":[[56,7],[114,7]]},"20":{"position":[[820,7]]},"28":{"position":[[662,7],[2101,7],[2639,7],[2698,7],[2853,7],[3756,7],[4357,7]]},"29":{"position":[[90,7],[114,7]]},"30":{"position":[[988,7],[2078,7],[2321,7],[2389,7],[2897,7],[4040,7],[4518,7],[5328,7],[5558,7],[5876,7],[7369,9]]},"43":{"position":[[1311,7]]},"64":{"position":[[1241,7]]},"91":{"position":[[4614,8],[5428,8]]},"167":{"position":[[192,7]]},"176":{"position":[[1260,7]]}},"keywords":{}}],["avoid",{"_index":4398,"title":{},"content":{"136":{"position":[[721,5]]},"157":{"position":[[256,5]]},"160":{"position":[[3848,5]]},"172":{"position":[[2356,5]]},"175":{"position":[[976,6]]},"188":{"position":[[4045,8]]},"189":{"position":[[536,5]]}},"keywords":{}}],["awar",{"_index":1375,"title":{},"content":{"30":{"position":[[2557,5]]},"150":{"position":[[825,5]]},"179":{"position":[[1792,5]]},"188":{"position":[[3370,5]]}},"keywords":{}}],["away",{"_index":3315,"title":{},"content":{"96":{"position":[[56,4]]},"97":{"position":[[5444,4],[5639,4],[5800,4]]},"98":{"position":[[911,4]]},"121":{"position":[[383,6]]},"122":{"position":[[399,4]]},"125":{"position":[[10900,5]]},"185":{"position":[[398,4]]}},"keywords":{}}],["awesom",{"_index":2215,"title":{},"content":{"53":{"position":[[509,8]]},"175":{"position":[[591,8]]}},"keywords":{}}],["awesome"",{"_index":238,"title":{},"content":{"4":{"position":[[370,15]]}},"keywords":{}}],["ax",{"_index":2863,"title":{},"content":{"88":{"position":[[1059,2],[1074,2],[1407,2],[1484,2],[1813,2]]}},"keywords":{}}],["ax.get_ylim()[0",{"_index":2880,"title":{},"content":{"88":{"position":[[1558,17],[1885,17]]}},"keywords":{}}],["ax.get_ylim()[1",{"_index":2881,"title":{},"content":{"88":{"position":[[1576,17],[1903,17]]}},"keywords":{}}],["ax.plot([date2num(start",{"_index":2907,"title":{},"content":{"88":{"position":[[2475,25],[2578,25]]}},"keywords":{}}],["ax.xaxis.set_major_formatter(weekformatt",{"_index":2874,"title":{},"content":{"88":{"position":[[1356,43]]}},"keywords":{}}],["ax.xaxis.set_major_locator(monday",{"_index":2872,"title":{},"content":{"88":{"position":[[1284,35]]}},"keywords":{}}],["ax.xaxis.set_minor_locator(allday",{"_index":2873,"title":{},"content":{"88":{"position":[[1320,35]]}},"keywords":{}}],["ax=ax_aapl",{"_index":2920,"title":{},"content":{"88":{"position":[[2800,11]]}},"keywords":{}}],["ax=ax_fb",{"_index":2930,"title":{},"content":{"88":{"position":[[3201,9]]}},"keywords":{}}],["ax=non",{"_index":2861,"title":{},"content":{"88":{"position":[[946,9]]}},"keywords":{}}],["ax_aapl",{"_index":2915,"title":{},"content":{"88":{"position":[[2709,7]]}},"keywords":{}}],["ax_aapl.get_ylim()[0",{"_index":2925,"title":{},"content":{"88":{"position":[[3005,22]]},"91":{"position":[[1236,22]]}},"keywords":{}}],["ax_aapl.get_ylim()[1",{"_index":2926,"title":{},"content":{"88":{"position":[[3028,22]]},"91":{"position":[[1259,22]]}},"keywords":{}}],["ax_aapl.legend(loc=2",{"_index":2928,"title":{},"content":{"88":{"position":[[3088,21]]}},"keywords":{}}],["ax_aapl.set_title('aapl",{"_index":2929,"title":{},"content":{"88":{"position":[[3110,23]]}},"keywords":{}}],["ax_aapl.vlines(date2num(datetime(2016",{"_index":2924,"title":{},"content":{"88":{"position":[[2953,38]]}},"keywords":{}}],["ax_fb",{"_index":2917,"title":{},"content":{"88":{"position":[[2728,5]]}},"keywords":{}}],["ax_fb.get_ylim()[0",{"_index":2933,"title":{},"content":{"88":{"position":[[3394,20]]},"91":{"position":[[770,20]]}},"keywords":{}}],["ax_fb.get_ylim()[1",{"_index":2934,"title":{},"content":{"88":{"position":[[3415,20]]},"91":{"position":[[791,20]]}},"keywords":{}}],["ax_fb.legend(loc=2",{"_index":2935,"title":{},"content":{"88":{"position":[[3473,19]]}},"keywords":{}}],["ax_fb.set_title('fb",{"_index":2936,"title":{},"content":{"88":{"position":[[3493,19]]}},"keywords":{}}],["ax_fb.vlines(date2num(datetime(2016",{"_index":2932,"title":{},"content":{"88":{"position":[[3344,36]]}},"keywords":{}}],["axarr",{"_index":2913,"title":{},"content":{"88":{"position":[[2682,5]]},"90":{"position":[[1313,5]]},"91":{"position":[[411,5]]}},"keywords":{}}],["axarr[0",{"_index":2916,"title":{},"content":{"88":{"position":[[2719,8]]},"91":{"position":[[473,8]]}},"keywords":{}}],["axarr[0].errorbar(range(1",{"_index":3006,"title":{},"content":{"90":{"position":[[1871,26]]}},"keywords":{}}],["axarr[0].fill_between(range(0",{"_index":2998,"title":{},"content":{"90":{"position":[[1492,30]]}},"keywords":{}}],["axarr[0].legend(loc=2",{"_index":3009,"title":{},"content":{"90":{"position":[[1982,22]]}},"keywords":{}}],["axarr[0].plot(range(range_begin",{"_index":2996,"title":{},"content":{"90":{"position":[[1388,32]]}},"keywords":{}}],["axarr[0].set_xlim",{"_index":3011,"title":{},"content":{"90":{"position":[[2028,19]]}},"keywords":{}}],["axarr[1",{"_index":2918,"title":{},"content":{"88":{"position":[[2736,8]]},"91":{"position":[[921,8]]}},"keywords":{}}],["axarr[1].fill_between(range(0",{"_index":3002,"title":{},"content":{"90":{"position":[[1641,30]]}},"keywords":{}}],["axarr[1].legend(loc=2",{"_index":3010,"title":{},"content":{"90":{"position":[[2005,22]]}},"keywords":{}}],["axarr[1].plot(range(range_begin",{"_index":2997,"title":{},"content":{"90":{"position":[[1440,32]]}},"keywords":{}}],["axarr[1].set_xlim",{"_index":3013,"title":{},"content":{"90":{"position":[[2073,19]]}},"keywords":{}}],["axis=1",{"_index":1781,"title":{},"content":{"39":{"position":[[3336,7]]},"40":{"position":[[252,7],[421,7],[1786,7],[1957,7],[2729,7],[2901,7]]},"90":{"position":[[1002,7],[2387,7]]}},"keywords":{}}],["b",{"_index":3592,"title":{},"content":{"105":{"position":[[1048,4]]},"175":{"position":[[171,1]]},"188":{"position":[[1072,1],[1093,1],[1122,1],[1124,1],[1138,1]]},"189":{"position":[[1141,1],[1155,1],[1184,1],[1186,1],[1200,1],[1411,1],[1425,1],[1454,1],[1456,1],[1470,1]]},"192":{"position":[[172,2],[547,2]]},"193":{"position":[[1079,2],[2483,2],[3259,2],[3568,2]]},"197":{"position":[[1346,1]]}},"keywords":{}}],["b.i",{"_index":5287,"title":{},"content":{"193":{"position":[[1381,4],[2561,4],[2624,4],[2638,5],[3332,4],[3646,4]]}},"keywords":{}}],["b.x",{"_index":5283,"title":{},"content":{"193":{"position":[[1353,4],[2533,4],[2585,4],[2599,5],[3304,4],[3618,4]]}},"keywords":{}}],["b_class",{"_index":1902,"title":{},"content":{"44":{"position":[[222,7]]}},"keywords":{}}],["b_class.append(c",{"_index":1905,"title":{},"content":{"44":{"position":[[278,17]]}},"keywords":{}}],["babel",{"_index":4025,"title":{},"content":{"125":{"position":[[764,5],[6728,5]]}},"keywords":{}}],["back",{"_index":1583,"title":{},"content":{"33":{"position":[[1016,4],[1238,4]]},"53":{"position":[[1119,5]]},"61":{"position":[[1932,4],[2220,4]]},"64":{"position":[[219,4],[1187,4]]},"82":{"position":[[101,4]]},"83":{"position":[[205,4]]},"96":{"position":[[915,4]]},"100":{"position":[[361,4]]},"113":{"position":[[2151,4],[2299,5]]},"115":{"position":[[920,5]]},"120":{"position":[[969,4]]},"123":{"position":[[450,4]]},"137":{"position":[[242,4]]},"156":{"position":[[1110,4]]},"163":{"position":[[151,5]]},"173":{"position":[[1229,4]]},"193":{"position":[[225,4],[1653,4]]}},"keywords":{}}],["backdidn't",{"_index":3322,"title":{},"content":{"96":{"position":[[357,10]]}},"keywords":{}}],["background",{"_index":88,"title":{},"content":{"2":{"position":[[201,10]]},"61":{"position":[[2136,11]]}},"keywords":{}}],["backtest",{"_index":1671,"title":{},"content":{"35":{"position":[[327,9]]},"39":{"position":[[38,9]]}},"keywords":{}}],["backward",{"_index":2450,"title":{},"content":{"64":{"position":[[117,8]]}},"keywords":{}}],["bad",{"_index":1120,"title":{},"content":{"24":{"position":[[2972,3]]},"96":{"position":[[164,3],[815,3]]},"97":{"position":[[6120,4]]},"125":{"position":[[5007,3]]}},"keywords":{}}],["bake",{"_index":4733,"title":{},"content":{"161":{"position":[[412,6],[992,4]]}},"keywords":{}}],["balanc",{"_index":3985,"title":{},"content":{"123":{"position":[[859,7]]}},"keywords":{}}],["ball",{"_index":1561,"title":{},"content":{"32":{"position":[[2281,4]]}},"keywords":{}}],["band",{"_index":1411,"title":{},"content":{"30":{"position":[[5631,4]]}},"keywords":{}}],["bank",{"_index":2035,"title":{},"content":{"46":{"position":[[494,4]]},"53":{"position":[[1762,7]]},"54":{"position":[[199,4]]},"121":{"position":[[34,4]]}},"keywords":{}}],["bar",{"_index":3069,"title":{},"content":{"90":{"position":[[5231,4]]},"91":{"position":[[4834,4]]},"92":{"position":[[1497,4]]}},"keywords":{}}],["barrier",{"_index":544,"title":{},"content":{"13":{"position":[[196,7],[278,7],[433,7],[487,7]]},"14":{"position":[[141,7],[351,7],[421,7],[486,7],[540,7],[615,7],[656,7],[739,8],[885,8],[911,8],[996,8],[1076,8],[1250,8],[1270,8]]},"15":{"position":[[266,8],[316,8],[336,8]]}},"keywords":{}}],["bar{\\lambda",{"_index":2119,"title":{},"content":{"51":{"position":[[2067,18]]}},"keywords":{}}],["base",{"_index":360,"title":{"102":{"position":[[6,5]]}},"content":{"6":{"position":[[887,5]]},"58":{"position":[[512,5],[717,5],[791,5]]},"65":{"position":[[2318,4],[2431,4]]},"75":{"position":[[438,5]]},"89":{"position":[[338,5]]},"125":{"position":[[3246,4]]},"157":{"position":[[160,5],[398,5]]}},"keywords":{}}],["base_url",{"_index":901,"title":{},"content":{"22":{"position":[[596,8],[701,10],[714,9]]},"93":{"position":[[2474,8]]}},"keywords":{}}],["baselin",{"_index":4510,"title":{},"content":{"152":{"position":[[347,8]]}},"keywords":{}}],["basi",{"_index":314,"title":{},"content":{"6":{"position":[[221,5]]},"160":{"position":[[161,6]]},"168":{"position":[[37,6]]},"169":{"position":[[37,6]]}},"keywords":{}}],["basic",{"_index":455,"title":{"110":{"position":[[18,5]]}},"content":{"9":{"position":[[24,5]]},"110":{"position":[[167,5]]},"117":{"position":[[2089,5]]},"169":{"position":[[121,5]]},"199":{"position":[[1290,5]]}},"keywords":{}}],["bassdriv",{"_index":3306,"title":{},"content":{"95":{"position":[[191,10]]}},"keywords":{}}],["basslin",{"_index":3548,"title":{},"content":{"103":{"position":[[2330,8]]},"104":{"position":[[449,9],[1284,9]]}},"keywords":{}}],["batch",{"_index":513,"title":{},"content":{"11":{"position":[[317,7]]}},"keywords":{}}],["bay",{"_index":1979,"title":{},"content":{"45":{"position":[[1247,5],[1668,5]]}},"keywords":{}}],["be",{"_index":635,"title":{},"content":{"14":{"position":[[822,5]]},"22":{"position":[[2751,5]]},"28":{"position":[[289,5],[838,5]]},"33":{"position":[[162,5]]},"36":{"position":[[44,5]]},"40":{"position":[[1496,5]]},"45":{"position":[[787,5],[960,5]]},"53":{"position":[[1636,5],[1785,5]]},"93":{"position":[[1914,5]]},"97":{"position":[[2555,5],[3249,5]]},"113":{"position":[[424,5]]},"122":{"position":[[239,5]]},"123":{"position":[[44,5]]},"125":{"position":[[11307,5]]},"132":{"position":[[298,5]]},"160":{"position":[[3980,5]]},"172":{"position":[[1888,5]]},"176":{"position":[[1139,5]]},"181":{"position":[[939,5]]},"182":{"position":[[547,5]]},"190":{"position":[[715,5]]},"197":{"position":[[199,5]]}},"keywords":{}}],["be.randomli",{"_index":2135,"title":{},"content":{"51":{"position":[[2879,11]]}},"keywords":{}}],["bear",{"_index":1168,"title":{},"content":{"26":{"position":[[10,5]]},"46":{"position":[[147,7]]},"93":{"position":[[145,7]]}},"keywords":{}}],["bearer",{"_index":2406,"title":{},"content":{"62":{"position":[[534,8]]}},"keywords":{}}],["beat",{"_index":2020,"title":{},"content":{"45":{"position":[[2587,4]]},"46":{"position":[[454,4]]},"57":{"position":[[687,6]]},"58":{"position":[[551,5],[636,5]]},"65":{"position":[[49,5],[1320,5]]},"76":{"position":[[2812,5],[2950,4]]}},"keywords":{}}],["beaten",{"_index":2331,"title":{},"content":{"58":{"position":[[318,6]]},"64":{"position":[[1980,6]]}},"keywords":{}}],["becauserefcel",{"_index":5129,"title":{},"content":{"184":{"position":[[933,14]]}},"keywords":{}}],["becom",{"_index":1392,"title":{},"content":{"30":{"position":[[4076,8]]},"53":{"position":[[312,8]]},"103":{"position":[[2024,6]]},"115":{"position":[[2938,8]]},"125":{"position":[[11020,6]]}},"keywords":{}}],["befor",{"_index":79,"title":{},"content":{"2":{"position":[[71,6]]},"24":{"position":[[145,7],[397,6]]},"26":{"position":[[189,6]]},"38":{"position":[[1313,6]]},"44":{"position":[[1257,6]]},"53":{"position":[[1074,6]]},"54":{"position":[[283,6]]},"55":{"position":[[192,7]]},"58":{"position":[[99,6]]},"65":{"position":[[2567,6]]},"89":{"position":[[605,6],[862,6]]},"90":{"position":[[1,6]]},"91":{"position":[[2676,6],[4764,6],[5080,6]]},"92":{"position":[[488,6]]},"93":{"position":[[337,6],[1870,6],[1940,7],[2118,7]]},"106":{"position":[[1068,7]]},"115":{"position":[[2989,6]]},"116":{"position":[[2823,6]]},"125":{"position":[[739,6],[10990,6]]},"127":{"position":[[943,6]]},"150":{"position":[[463,6]]},"160":{"position":[[2734,6],[3379,6]]},"163":{"position":[[331,6]]},"164":{"position":[[999,6]]},"165":{"position":[[904,6]]},"175":{"position":[[1398,6]]},"176":{"position":[[775,6]]},"189":{"position":[[303,6]]},"190":{"position":[[1,6]]}},"keywords":{}}],["began",{"_index":76,"title":{},"content":{"2":{"position":[[32,5]]},"122":{"position":[[537,5]]}},"keywords":{}}],["begin",{"_index":1526,"title":{},"content":{"32":{"position":[[633,9]]},"33":{"position":[[1295,9]]},"75":{"position":[[1076,5]]},"115":{"position":[[3169,6]]},"128":{"position":[[118,5]]},"166":{"position":[[582,10]]},"175":{"position":[[1524,5]]}},"keywords":{}}],["beginn",{"_index":4054,"title":{},"content":{"125":{"position":[[1806,8]]}},"keywords":{}}],["begin{array}{cc",{"_index":2579,"title":{},"content":{"70":{"position":[[257,17]]},"71":{"position":[[357,17]]}},"keywords":{}}],["begin{array}{lr",{"_index":2581,"title":{},"content":{"70":{"position":[[289,17],[463,17]]},"71":{"position":[[389,17],[563,17]]},"74":{"position":[[580,17]]}},"keywords":{}}],["behav",{"_index":3902,"title":{},"content":{"121":{"position":[[1505,7]]},"142":{"position":[[249,6]]},"155":{"position":[[808,6]]},"159":{"position":[[735,6]]},"182":{"position":[[302,6]]}},"keywords":{}}],["behavior",{"_index":4416,"title":{},"content":{"139":{"position":[[286,9]]},"153":{"position":[[70,9]]},"156":{"position":[[1806,9]]},"158":{"position":[[387,9]]},"159":{"position":[[333,8],[835,8]]},"172":{"position":[[1159,8]]},"175":{"position":[[1156,9]]},"179":{"position":[[1693,8]]},"189":{"position":[[186,8]]},"198":{"position":[[612,8],[962,9]]}},"keywords":{}}],["behind",{"_index":1536,"title":{},"content":{"32":{"position":[[1055,6]]}},"keywords":{}}],["believ",{"_index":262,"title":{},"content":{"4":{"position":[[817,7]]},"101":{"position":[[930,7]]},"102":{"position":[[364,7]]},"129":{"position":[[230,7]]},"165":{"position":[[980,7]]},"176":{"position":[[1406,7]]}},"keywords":{}}],["bell",{"_index":3210,"title":{},"content":{"93":{"position":[[1881,5]]}},"keywords":{}}],["below",{"_index":629,"title":{},"content":{"14":{"position":[[197,5],[675,5],[979,5]]},"15":{"position":[[1307,5]]},"20":{"position":[[911,5]]},"28":{"position":[[1630,6],[3416,6]]},"43":{"position":[[259,6]]},"90":{"position":[[3645,6],[5072,5]]},"148":{"position":[[591,6]]},"167":{"position":[[179,5]]},"196":{"position":[[668,5]]},"199":{"position":[[1000,5]]}},"keywords":{}}],["benchmark",{"_index":3577,"title":{},"content":{"105":{"position":[[285,9]]},"153":{"position":[[233,10]]},"163":{"position":[[5,9]]},"167":{"position":[[120,11]]},"170":{"position":[[12,9]]},"172":{"position":[[2398,11]]},"176":{"position":[[309,11],[1118,11],[1305,12]]},"198":{"position":[[332,9]]}},"keywords":{}}],["benchmark,y",{"_index":4619,"title":{},"content":{"158":{"position":[[111,13]]}},"keywords":{}}],["benefici",{"_index":4954,"title":{},"content":{"173":{"position":[[928,11]]}},"keywords":{}}],["benefit",{"_index":2810,"title":{},"content":{"83":{"position":[[160,8]]},"172":{"position":[[2302,8]]},"174":{"position":[[968,8],[1345,9]]}},"keywords":{}}],["besid",{"_index":4182,"title":{},"content":{"125":{"position":[[9344,7]]}},"keywords":{}}],["bespok",{"_index":194,"title":{},"content":{"3":{"position":[[1143,7]]}},"keywords":{}}],["best",{"_index":198,"title":{},"content":{"3":{"position":[[1211,4]]},"44":{"position":[[1765,4]]},"46":{"position":[[502,4]]},"58":{"position":[[206,5],[365,5]]},"76":{"position":[[945,4],[2117,4],[3286,4]]},"93":{"position":[[318,4]]},"104":{"position":[[89,4],[139,4],[959,4],[1472,4]]},"112":{"position":[[553,4],[1318,4]]},"120":{"position":[[1011,4]]},"123":{"position":[[986,4]]},"166":{"position":[[798,4]]},"170":{"position":[[164,4]]},"189":{"position":[[433,4]]}},"keywords":{}}],["bestructur",{"_index":4981,"title":{},"content":{"174":{"position":[[354,12]]}},"keywords":{}}],["bet",{"_index":1598,"title":{},"content":{"34":{"position":[[843,3],[867,3],[945,3]]}},"keywords":{}}],["better",{"_index":431,"title":{},"content":{"7":{"position":[[1093,6]]},"30":{"position":[[2862,6]]},"40":{"position":[[1521,6],[3292,6]]},"45":{"position":[[1871,6]]},"51":{"position":[[2702,6]]},"66":{"position":[[177,6]]},"73":{"position":[[824,6]]},"76":{"position":[[2549,8]]},"78":{"position":[[923,8]]},"82":{"position":[[298,8],[368,8],[438,8],[508,8],[578,8],[648,8],[718,8],[788,8],[858,8],[929,8]]},"86":{"position":[[1168,6]]},"93":{"position":[[757,6],[797,7],[833,6]]},"96":{"position":[[132,6]]},"105":{"position":[[2600,6],[3315,6],[3393,6]]},"121":{"position":[[290,6]]},"125":{"position":[[7348,6]]},"129":{"position":[[1333,6]]},"152":{"position":[[331,6]]},"159":{"position":[[848,6]]},"164":{"position":[[770,7]]},"172":{"position":[[907,6]]},"193":{"position":[[2146,6]]},"198":{"position":[[108,6]]}},"keywords":{}}],["between",{"_index":386,"title":{},"content":{"7":{"position":[[246,7]]},"9":{"position":[[179,7]]},"10":{"position":[[348,7]]},"15":{"position":[[1272,7]]},"43":{"position":[[1324,7]]},"64":{"position":[[317,7],[392,7],[1087,7],[1331,7],[2005,7]]},"89":{"position":[[780,7]]},"91":{"position":[[279,7]]},"115":{"position":[[1216,7],[1596,7],[1873,7],[2421,7],[2674,7]]},"116":{"position":[[1168,7],[1501,7],[1778,7],[2279,7],[3261,7]]},"117":{"position":[[983,7]]},"125":{"position":[[7595,7],[8281,7]]},"161":{"position":[[55,7]]},"175":{"position":[[279,7],[512,7],[1295,7]]},"183":{"position":[[31,7]]},"184":{"position":[[1087,7]]},"185":{"position":[[768,7]]},"199":{"position":[[69,7]]}},"keywords":{}}],["betweenth",{"_index":4650,"title":{},"content":{"160":{"position":[[243,10]]}},"keywords":{}}],["beyond",{"_index":1987,"title":{},"content":{"45":{"position":[[1774,6]]},"120":{"position":[[239,6]]}},"keywords":{}}],["bia",{"_index":1433,"title":{},"content":{"30":{"position":[[7633,5]]},"34":{"position":[[725,4],[1635,5],[2235,5]]},"39":{"position":[[1046,6],[1455,5],[2195,6]]},"41":{"position":[[483,4]]},"91":{"position":[[3918,4]]}},"keywords":{}}],["bias",{"_index":1695,"title":{},"content":{"38":{"position":[[687,7]]},"70":{"position":[[30,6],[57,6],[1225,6],[1243,6]]},"71":{"position":[[1390,6]]},"78":{"position":[[44,6]]},"79":{"position":[[40,6]]},"80":{"position":[[33,6]]},"82":{"position":[[152,6]]}},"keywords":{}}],["bias.th",{"_index":1594,"title":{},"content":{"34":{"position":[[376,8]]}},"keywords":{}}],["bib",{"_index":1836,"title":{},"content":{"40":{"position":[[3364,5]]}},"keywords":{}}],["big",{"_index":1784,"title":{},"content":{"40":{"position":[[58,3],[1310,3]]},"93":{"position":[[425,3]]},"125":{"position":[[11400,3]]},"129":{"position":[[798,3]]},"140":{"position":[[78,3]]},"163":{"position":[[502,3]]}},"keywords":{}}],["bigdecim",{"_index":3943,"title":{},"content":{"122":{"position":[[648,10],[683,10]]}},"keywords":{}}],["biggest",{"_index":5116,"title":{},"content":{"183":{"position":[[12,7]]}},"keywords":{}}],["billion",{"_index":2306,"title":{"57":{"position":[[4,8]]}},"content":{"57":{"position":[[673,7]]},"58":{"position":[[159,7],[241,7],[256,7],[385,7]]},"64":{"position":[[52,7],[2075,7]]}},"keywords":{}}],["billionth",{"_index":5170,"title":{},"content":{"188":{"position":[[1517,9]]}},"keywords":{}}],["bin",{"_index":2110,"title":{},"content":{"51":{"position":[[1713,4]]},"109":{"position":[[184,3]]}},"keywords":{}}],["binar",{"_index":1910,"title":{},"content":{"44":{"position":[[476,10],[593,8]]}},"keywords":{}}],["binari",{"_index":1896,"title":{"44":{"position":[[33,6]]},"162":{"position":[[0,6]]},"163":{"position":[[10,6]]},"166":{"position":[[7,6]]}},"content":{"44":{"position":[[71,6],[370,6],[1781,6]]},"45":{"position":[[208,6],[832,6],[3421,6]]},"96":{"position":[[1265,6]]},"108":{"position":[[11,6],[373,6],[730,6]]},"109":{"position":[[17,6]]},"110":{"position":[[590,6]]},"113":{"position":[[1550,7]]},"115":{"position":[[187,6]]},"116":{"position":[[287,6]]},"117":{"position":[[786,6],[850,6],[1079,6]]},"125":{"position":[[7860,7],[7896,7],[8114,7]]},"160":{"position":[[1862,6]]},"163":{"position":[[307,6]]},"165":{"position":[[205,6]]},"166":{"position":[[272,6]]},"180":{"position":[[95,7]]},"190":{"position":[[657,6]]}},"keywords":{}}],["binarize(x[b_class",{"_index":1914,"title":{},"content":{"44":{"position":[[610,20]]}},"keywords":{}}],["bind",{"_index":4333,"title":{},"content":{"129":{"position":[[2722,7]]},"130":{"position":[[324,9]]},"196":{"position":[[282,4]]}},"keywords":{}}],["bindgen",{"_index":4086,"title":{},"content":{"125":{"position":[[3726,7],[5275,7],[5823,7],[6168,7],[6482,7],[6566,7],[6769,7],[7623,7],[7667,7],[7842,7],[7925,7],[8087,7],[9357,8],[11416,7]]}},"keywords":{}}],["binghamton",{"_index":1202,"title":{},"content":{"28":{"position":[[191,11],[368,11],[990,14]]},"30":{"position":[[8681,13],[10162,10]]}},"keywords":{}}],["binghamton_loc",{"_index":1459,"title":{},"content":{"30":{"position":[[8572,14],[8695,14]]}},"keywords":{}}],["bins=11",{"_index":2566,"title":{},"content":{"68":{"position":[[617,9]]},"70":{"position":[[1198,9]]},"71":{"position":[[1349,8]]},"78":{"position":[[607,8]]}},"keywords":{}}],["bins=bin",{"_index":2113,"title":{},"content":{"51":{"position":[[1771,10]]}},"keywords":{}}],["biotech",{"_index":1823,"title":{},"content":{"40":{"position":[[2588,7]]}},"keywords":{}}],["biotech_df",{"_index":1825,"title":{},"content":{"40":{"position":[[2607,10]]}},"keywords":{}}],["biotech_df.xs('day",{"_index":1830,"title":{},"content":{"40":{"position":[[2707,21]]}},"keywords":{}}],["biotech_df.xs('scor",{"_index":1831,"title":{},"content":{"40":{"position":[[2878,22]]}},"keywords":{}}],["birth",{"_index":2497,"title":{},"content":{"64":{"position":[[2026,5]]}},"keywords":{}}],["birthday",{"_index":2479,"title":{},"content":{"64":{"position":[[1204,9],[1342,8]]}},"keywords":{}}],["birthday_heartbeat",{"_index":2487,"title":{},"content":{"64":{"position":[[1565,19]]}},"keywords":{}}],["birthday_minut",{"_index":2486,"title":{},"content":{"64":{"position":[[1542,16],[1587,16]]}},"keywords":{}}],["bit",{"_index":456,"title":{},"content":{"9":{"position":[[73,3]]},"24":{"position":[[518,3]]},"25":{"position":[[243,3]]},"28":{"position":[[2406,3]]},"29":{"position":[[25,3]]},"30":{"position":[[506,3],[9492,3]]},"40":{"position":[[883,3]]},"44":{"position":[[1005,3],[1677,3]]},"51":{"position":[[850,3]]},"61":{"position":[[1288,3]]},"65":{"position":[[22,4]]},"76":{"position":[[586,3]]},"86":{"position":[[227,3]]},"89":{"position":[[1017,5]]},"96":{"position":[[1955,3]]},"97":{"position":[[1206,3]]},"105":{"position":[[576,3],[729,3],[2867,3]]},"108":{"position":[[553,3]]},"113":{"position":[[792,3]]},"115":{"position":[[2709,3]]},"116":{"position":[[2365,3]]},"117":{"position":[[490,3]]},"123":{"position":[[522,3]]},"124":{"position":[[660,3]]},"125":{"position":[[7332,4]]},"127":{"position":[[312,4],[1119,5],[1216,3],[1549,3]]},"128":{"position":[[559,4],[792,4],[958,4],[1321,4],[1557,4],[1756,4]]},"129":{"position":[[308,3],[468,4],[761,3],[2680,3]]},"152":{"position":[[266,3]]},"156":{"position":[[525,3],[1031,3]]},"157":{"position":[[15,3]]},"160":{"position":[[807,3]]},"161":{"position":[[428,3]]},"179":{"position":[[22,3]]},"184":{"position":[[419,3]]},"196":{"position":[[1403,3]]}},"keywords":{}}],["bitrat",{"_index":3652,"title":{},"content":{"106":{"position":[[465,8]]}},"keywords":{}}],["black",{"_index":3055,"title":{},"content":{"90":{"position":[[4447,8],[4564,8],[4670,8]]}},"keywords":{}}],["blasphemi",{"_index":4199,"title":{},"content":{"125":{"position":[[10319,10]]}},"keywords":{}}],["bless",{"_index":1957,"title":{},"content":{"45":{"position":[[52,8]]}},"keywords":{}}],["blob",{"_index":4088,"title":{},"content":{"125":{"position":[[3897,5],[4481,4],[4623,5],[4936,4],[6591,4]]}},"keywords":{}}],["block",{"_index":913,"title":{},"content":{"22":{"position":[[859,6]]},"91":{"position":[[1819,5],[2750,5]]},"92":{"position":[[562,5]]},"98":{"position":[[248,6]]},"105":{"position":[[3091,5],[3289,5],[3375,5]]},"106":{"position":[[779,6]]},"121":{"position":[[1675,7],[1834,5]]},"123":{"position":[[250,8]]},"125":{"position":[[9425,6],[9655,6]]},"129":{"position":[[156,6],[341,6]]},"163":{"position":[[980,5],[1076,5]]},"165":{"position":[[28,6]]},"188":{"position":[[632,5],[932,6],[4136,7]]}},"keywords":{}}],["block_len",{"_index":4784,"title":{},"content":{"163":{"position":[[1859,10]]}},"keywords":{}}],["block_siz",{"_index":3523,"title":{},"content":{"103":{"position":[[988,10],[1031,10],[1060,11],[1232,11],[1244,12],[1613,11]]},"105":{"position":[[1374,12],[1453,11]]}},"keywords":{}}],["block_size=1024",{"_index":3522,"title":{},"content":{"103":{"position":[[910,17]]}},"keywords":{}}],["block_typ",{"_index":4783,"title":{},"content":{"163":{"position":[[1847,11]]}},"keywords":{}}],["blockstak",{"_index":3904,"title":{},"content":{"121":{"position":[[1573,10]]}},"keywords":{}}],["blog",{"_index":249,"title":{},"content":{"4":{"position":[[654,4]]},"30":{"position":[[7967,4],[8184,4],[8268,4]]},"39":{"position":[[209,4]]},"53":{"position":[[857,4]]},"86":{"position":[[669,4]]},"125":{"position":[[2298,4],[11651,4]]},"161":{"position":[[263,4]]},"166":{"position":[[67,4]]}},"keywords":{}}],["blow",{"_index":980,"title":{"143":{"position":[[0,7]]}},"content":{"22":{"position":[[2833,5]]},"76":{"position":[[1457,4]]},"91":{"position":[[3255,4]]},"92":{"position":[[1067,4]]},"96":{"position":[[1832,5]]},"121":{"position":[[631,5]]},"153":{"position":[[776,5]]}},"keywords":{}}],["blown",{"_index":4303,"title":{},"content":{"129":{"position":[[1755,6]]}},"keywords":{}}],["blue",{"_index":3064,"title":{},"content":{"90":{"position":[[4749,4],[4972,4],[5011,4]]}},"keywords":{}}],["bodywrap",{"_index":3914,"title":{},"content":{"121":{"position":[[2048,11]]}},"keywords":{}}],["boilerpl",{"_index":4219,"title":{},"content":{"125":{"position":[[11592,11]]}},"keywords":{}}],["bokeh.palett",{"_index":1325,"title":{},"content":{"30":{"position":[[156,14]]}},"keywords":{}}],["bokeh.plot",{"_index":1323,"title":{},"content":{"30":{"position":[[99,14]]}},"keywords":{}}],["bokehj",{"_index":1331,"title":{},"content":{"30":{"position":[[298,7]]}},"keywords":{}}],["bond",{"_index":302,"title":{"5":{"position":[[13,5]]}},"content":{"6":{"position":[[36,6]]}},"keywords":{}}],["bonfir",{"_index":2212,"title":{},"content":{"53":{"position":[[452,8]]}},"keywords":{}}],["book",{"_index":4660,"title":{},"content":{"160":{"position":[[628,4]]},"163":{"position":[[70,4]]}},"keywords":{}}],["bookment",{"_index":5064,"title":{},"content":{"179":{"position":[[74,12]]}},"keywords":{}}],["bool",{"_index":4224,"title":{},"content":{"127":{"position":[[205,4]]}},"keywords":{}}],["boolean",{"_index":3891,"title":{},"content":{"121":{"position":[[1005,7]]}},"keywords":{}}],["boost",{"_index":5237,"title":{},"content":{"189":{"position":[[1264,6]]}},"keywords":{}}],["bootstrap",{"_index":4010,"title":{},"content":{"125":{"position":[[204,9]]}},"keywords":{}}],["bore",{"_index":4800,"title":{},"content":{"163":{"position":[[2489,6]]}},"keywords":{}}],["born",{"_index":2451,"title":{},"content":{"64":{"position":[[161,4]]}},"keywords":{}}],["borrow",{"_index":2621,"title":{"97":{"position":[[27,6]]}},"content":{"73":{"position":[[165,6]]},"97":{"position":[[428,6],[4583,7],[5011,8],[5133,8]]},"113":{"position":[[1130,8]]},"115":{"position":[[3137,6]]},"164":{"position":[[717,6]]},"193":{"position":[[3459,9]]}},"keywords":{}}],["both",{"_index":223,"title":{},"content":{"4":{"position":[[61,4]]},"15":{"position":[[458,4]]},"24":{"position":[[2933,4],[3345,4]]},"38":{"position":[[523,4]]},"40":{"position":[[3606,4]]},"71":{"position":[[122,4]]},"76":{"position":[[3277,4]]},"78":{"position":[[39,4]]},"79":{"position":[[35,4]]},"92":{"position":[[1592,4]]},"118":{"position":[[73,4]]},"125":{"position":[[2,4],[11382,4]]},"129":{"position":[[1802,4]]},"130":{"position":[[301,4]]},"132":{"position":[[717,4]]},"146":{"position":[[1,4]]},"160":{"position":[[2697,4]]},"166":{"position":[[321,4]]},"170":{"position":[[228,4]]},"172":{"position":[[1659,4]]},"181":{"position":[[457,4]]},"188":{"position":[[1740,4]]},"189":{"position":[[2334,4]]},"190":{"position":[[889,4]]}},"keywords":{}}],["bothlibtest",{"_index":4542,"title":{},"content":{"153":{"position":[[312,11]]}},"keywords":{}}],["bottom",{"_index":1572,"title":{},"content":{"33":{"position":[[393,6]]},"161":{"position":[[1137,6]]}},"keywords":{}}],["bound",{"_index":811,"title":{},"content":{"20":{"position":[[1203,5],[1947,6]]},"97":{"position":[[1859,5]]},"115":{"position":[[951,5],[1265,5],[1645,5],[1922,5]]},"116":{"position":[[950,5],[1217,5],[1550,5],[1827,5]]},"129":{"position":[[1822,5]]}},"keywords":{}}],["boundari",{"_index":3812,"title":{},"content":{"116":{"position":[[2594,11],[2727,11]]}},"keywords":{}}],["bounds=bound",{"_index":843,"title":{},"content":{"20":{"position":[[2230,14]]}},"keywords":{}}],["box",{"_index":3797,"title":{"116":{"position":[[31,4]]},"152":{"position":[[29,4]]}},"content":{"116":{"position":[[5,3]]},"141":{"position":[[93,5],[196,3]]},"152":{"position":[[627,5]]},"155":{"position":[[1129,3]]},"159":{"position":[[978,5]]}},"keywords":{}}],["box<_>",{"_index":4461,"title":{},"content":{"145":{"position":[[364,14]]}},"keywords":{}}],["box<u64>",{"_index":5366,"title":{},"content":{"198":{"position":[[1012,14],[1147,14]]}},"keywords":{}}],["box<vec<u8>>",{"_index":4434,"title":{},"content":{"141":{"position":[[27,24]]}},"keywords":{}}],["box,rc",{"_index":4697,"title":{},"content":{"160":{"position":[[2571,7]]}},"keywords":{}}],["box::new(0",{"_index":4580,"title":{},"content":{"155":{"position":[[1387,12]]}},"keywords":{}}],["box::new(24",{"_index":4517,"title":{},"content":{"152":{"position":[[694,13]]}},"keywords":{}}],["box::new(point_read",{"_index":3800,"title":{},"content":{"116":{"position":[[569,23]]}},"keywords":{}}],["box::new(vec::new",{"_index":4435,"title":{},"content":{"141":{"position":[[54,21]]}},"keywords":{}}],["box`",{"_index":3801,"title":{},"content":{"116":{"position":[[619,8]]}},"keywords":{}}],["boxed_read",{"_index":3799,"title":{},"content":{"116":{"position":[[554,12]]}},"keywords":{}}],["boxrcarccow",{"_index":4563,"title":{},"content":{"155":{"position":[[570,11]]}},"keywords":{}}],["bracket",{"_index":3870,"title":{},"content":{"121":{"position":[[26,7]]}},"keywords":{}}],["bradlee'",{"_index":1528,"title":{},"content":{"32":{"position":[[768,9]]}},"keywords":{}}],["bradlee@speice.io",{"_index":4721,"title":{},"content":{"160":{"position":[[4330,17]]}},"keywords":{}}],["brainer",{"_index":3963,"title":{},"content":{"122":{"position":[[1487,8]]}},"keywords":{}}],["branch",{"_index":4982,"title":{},"content":{"174":{"position":[[379,6]]}},"keywords":{}}],["branchesin",{"_index":4937,"title":{},"content":{"172":{"position":[[2642,10]]}},"keywords":{}}],["bread",{"_index":3840,"title":{"161":{"position":[[7,5]]}},"content":{"118":{"position":[[128,5]]},"161":{"position":[[246,5],[1001,5],[1516,5],[1550,5]]}},"keywords":{}}],["break",{"_index":299,"title":{},"content":{"4":{"position":[[1521,5]]},"30":{"position":[[9578,7]]},"32":{"position":[[2140,5]]},"33":{"position":[[1190,5]]},"34":{"position":[[251,5]]},"104":{"position":[[97,5]]},"125":{"position":[[11471,5]]},"129":{"position":[[369,5]]},"150":{"position":[[57,5]]},"161":{"position":[[479,5],[1631,6]]},"172":{"position":[[2533,5]]}},"keywords":{}}],["breakfast/articles"",{"_index":904,"title":{},"content":{"22":{"position":[[656,24]]}},"keywords":{}}],["breakneck",{"_index":4359,"title":{},"content":{"132":{"position":[[953,9]]}},"keywords":{}}],["breaksthere'",{"_index":278,"title":{},"content":{"4":{"position":[[1077,13]]}},"keywords":{}}],["breath",{"_index":2201,"title":{},"content":{"53":{"position":[[255,7]]},"66":{"position":[[617,7]]}},"keywords":{}}],["breviti",{"_index":3786,"title":{},"content":{"115":{"position":[[2526,8]]}},"keywords":{}}],["brew",{"_index":3671,"title":{},"content":{"108":{"position":[[515,4]]}},"keywords":{}}],["brief",{"_index":3461,"title":{"101":{"position":[[2,5]]}},"content":{},"keywords":{}}],["bring",{"_index":2716,"title":{},"content":{"76":{"position":[[1854,6]]},"124":{"position":[[421,5]]},"172":{"position":[[2291,6]]}},"keywords":{}}],["brittl",{"_index":4197,"title":{},"content":{"125":{"position":[[10301,7]]}},"keywords":{}}],["broad",{"_index":2950,"title":{},"content":{"89":{"position":[[473,5]]},"197":{"position":[[28,5]]}},"keywords":{}}],["broadli",{"_index":3469,"title":{},"content":{"101":{"position":[[299,7]]}},"keywords":{}}],["broke",{"_index":2938,"title":{},"content":{"88":{"position":[[3590,5]]},"103":{"position":[[60,5]]},"125":{"position":[[2352,5]]}},"keywords":{}}],["brought",{"_index":4765,"title":{},"content":{"163":{"position":[[489,7]]}},"keywords":{}}],["browser",{"_index":70,"title":{},"content":{"1":{"position":[[776,8]]},"125":{"position":[[1039,8],[6811,7],[7180,7],[8747,7],[9465,8]]},"160":{"position":[[2883,8]]}},"keywords":{}}],["browser'",{"_index":4190,"title":{},"content":{"125":{"position":[[9679,9]]}},"keywords":{}}],["browser."",{"_index":26,"title":{},"content":{"1":{"position":[[297,14]]}},"keywords":{}}],["bs",{"_index":3610,"title":{},"content":{"105":{"position":[[1734,3],[1745,2]]}},"keywords":{}}],["bsd",{"_index":3995,"title":{},"content":{"124":{"position":[[270,3]]}},"keywords":{}}],["bubbl",{"_index":4742,"title":{},"content":{"161":{"position":[[880,8]]}},"keywords":{}}],["bueno",{"_index":4186,"title":{},"content":{"125":{"position":[[9480,6]]}},"keywords":{}}],["buffer",{"_index":3752,"title":{},"content":{"113":{"position":[[1573,6],[1598,6],[1645,6],[1707,7]]},"115":{"position":[[148,8],[2737,6]]},"116":{"position":[[248,8]]},"117":{"position":[[1040,8]]},"164":{"position":[[482,6],[589,7],[965,6],[1049,6]]},"168":{"position":[[144,7]]}},"keywords":{}}],["buffer.as_slic",{"_index":3758,"title":{},"content":{"113":{"position":[[1838,18]]},"115":{"position":[[293,18]]},"116":{"position":[[393,18]]},"117":{"position":[[1182,18]]}},"keywords":{}}],["build",{"_index":265,"title":{"111":{"position":[[23,5]]},"112":{"position":[[20,6]]},"171":{"position":[[3,8]]}},"content":{"4":{"position":[[868,5]]},"7":{"position":[[391,5]]},"12":{"position":[[29,5]]},"34":{"position":[[763,5]]},"49":{"position":[[32,5]]},"50":{"position":[[141,5]]},"51":{"position":[[370,5],[714,5]]},"97":{"position":[[2365,5],[3065,5],[3955,5]]},"98":{"position":[[239,8]]},"102":{"position":[[1471,5]]},"105":{"position":[[357,5]]},"109":{"position":[[377,6]]},"111":{"position":[[38,5],[848,5]]},"112":{"position":[[76,5],[139,5]]},"113":{"position":[[118,8],[756,8],[2516,5]]},"124":{"position":[[841,8]]},"125":{"position":[[5219,5],[5767,5],[6997,5],[9646,8],[9727,8]]},"128":{"position":[[18,5]]},"132":{"position":[[22,8],[594,5]]},"141":{"position":[[240,6]]},"143":{"position":[[417,8]]},"146":{"position":[[225,7]]},"160":{"position":[[3564,5]]},"163":{"position":[[545,5],[1634,5],[2408,8]]},"165":{"position":[[911,8]]},"167":{"position":[[7,8]]},"170":{"position":[[1,8]]},"188":{"position":[[159,8]]},"190":{"position":[[448,8]]}},"keywords":{}}],["build.r",{"_index":3698,"title":{},"content":{"111":{"position":[[166,8],[292,9]]}},"keywords":{}}],["build_estimates(sign",{"_index":3602,"title":{},"content":{"105":{"position":[[1336,23]]}},"keywords":{}}],["build_estimates(tabulasa_left",{"_index":3609,"title":{},"content":{"105":{"position":[[1700,30]]}},"keywords":{}}],["build_handler(messag",{"_index":3372,"title":{},"content":{"97":{"position":[[1463,22]]}},"keywords":{}}],["builder",{"_index":3722,"title":{},"content":{"112":{"position":[[1280,7],[1385,8],[1482,7]]},"113":{"position":[[839,8],[948,7],[1044,9]]},"164":{"position":[[352,7]]}},"keywords":{}}],["builder.init_root::<point_capnp::point::builder>",{"_index":3748,"title":{},"content":{"113":{"position":[[1364,57]]}},"keywords":{}}],["builderscan't",{"_index":4805,"title":{},"content":{"164":{"position":[[430,13]]}},"keywords":{}}],["builderthat",{"_index":4807,"title":{},"content":{"164":{"position":[[560,11]]}},"keywords":{}}],["built",{"_index":2147,"title":{},"content":{"51":{"position":[[3437,5]]},"52":{"position":[[10,5]]},"111":{"position":[[583,5]]},"113":{"position":[[563,5]]},"122":{"position":[[245,6]]},"124":{"position":[[16,5]]},"125":{"position":[[1544,5]]},"132":{"position":[[304,6]]},"175":{"position":[[675,5]]},"176":{"position":[[149,6]]}},"keywords":{}}],["bulg",{"_index":3869,"title":{},"content":{"121":{"position":[[20,5]]}},"keywords":{}}],["bulk",{"_index":4384,"title":{},"content":{"136":{"position":[[118,4]]}},"keywords":{}}],["bundl",{"_index":251,"title":{},"content":{"4":{"position":[[691,8]]},"125":{"position":[[4150,6],[6656,6]]}},"keywords":{}}],["bundle.j",{"_index":4089,"title":{},"content":{"125":{"position":[[4003,9]]}},"keywords":{}}],["burden",{"_index":4663,"title":{},"content":{"160":{"position":[[699,6]]},"174":{"position":[[811,8]]}},"keywords":{}}],["burdensom",{"_index":4689,"title":{},"content":{"160":{"position":[[2302,10]]}},"keywords":{}}],["button",{"_index":4032,"title":{},"content":{"125":{"position":[[938,6]]},"176":{"position":[[989,8]]}},"keywords":{}}],["bycach",{"_index":4830,"title":{},"content":{"165":{"position":[[864,9]]}},"keywords":{}}],["bypass",{"_index":4810,"title":{},"content":{"164":{"position":[[703,6]]},"174":{"position":[[1231,7]]}},"keywords":{}}],["byte",{"_index":3319,"title":{},"content":{"96":{"position":[[189,5]]},"105":{"position":[[599,5],[746,5]]},"127":{"position":[[215,4]]},"192":{"position":[[243,5],[356,5],[503,5]]},"193":{"position":[[1145,5]]},"195":{"position":[[184,5]]}},"keywords":{}}],["bytecod",{"_index":4929,"title":{},"content":{"172":{"position":[[2055,8]]},"189":{"position":[[141,8]]}},"keywords":{}}],["bytes"",{"_index":4732,"title":{},"content":{"161":{"position":[[383,12]]}},"keywords":{}}],["bytestr",{"_index":3591,"title":{},"content":{"105":{"position":[[1011,10]]}},"keywords":{}}],["bz2",{"_index":3580,"title":{},"content":{"105":{"position":[[453,3]]}},"keywords":{}}],["bz2"",{"_index":3615,"title":{},"content":{"105":{"position":[[1857,10]]}},"keywords":{}}],["bz2(1",{"_index":3617,"title":{},"content":{"105":{"position":[[1963,6]]}},"keywords":{}}],["bz2_estimate(transform",{"_index":3590,"title":{},"content":{"105":{"position":[[979,25],[1534,25]]}},"keywords":{}}],["bz2_pca_estim",{"_index":3605,"title":{},"content":{"105":{"position":[[1515,16],[1642,16]]}},"keywords":{}}],["c",{"_index":1903,"title":{"128":{"position":[[33,4]]}},"content":{"44":{"position":[[239,1]]},"98":{"position":[[668,3],[672,5],[894,3]]},"103":{"position":[[354,1]]},"128":{"position":[[145,1],[1094,1],[1582,1],[1690,1]]},"130":{"position":[[180,1]]},"155":{"position":[[249,4]]},"160":{"position":[[2321,3]]},"172":{"position":[[1030,3],[1449,1],[1471,3],[1490,3],[1494,4],[1805,3],[2185,2],[2610,3]]},"188":{"position":[[187,1],[193,3],[1079,1],[1085,1],[1128,1],[1130,1],[1147,1],[4299,1]]},"189":{"position":[[593,2],[1147,1],[1190,1],[1192,1],[1209,1],[1417,1],[1460,1],[1462,1],[1479,1]]}},"keywords":{}}],["c"",{"_index":4184,"title":{},"content":{"125":{"position":[[9417,7]]}},"keywords":{}}],["c/c",{"_index":5147,"title":{},"content":{"188":{"position":[[95,6]]},"189":{"position":[[112,6]]}},"keywords":{}}],["c6e2990393c32fe6/out/point_capnp.r",{"_index":3716,"title":{},"content":{"112":{"position":[[835,35]]}},"keywords":{}}],["c='k",{"_index":2011,"title":{},"content":{"45":{"position":[[2358,6],[2433,6],[3138,6],[3213,6]]}},"keywords":{}}],["c_n",{"_index":1541,"title":{},"content":{"32":{"position":[[1572,3]]}},"keywords":{}}],["cach",{"_index":4986,"title":{},"content":{"174":{"position":[[604,8]]}},"keywords":{}}],["cachegrind",{"_index":4923,"title":{},"content":{"172":{"position":[[1620,10]]}},"keywords":{}}],["calcul",{"_index":411,"title":{"18":{"position":[[0,11]]},"19":{"position":[[0,11]]},"20":{"position":[[0,11]]}},"content":{"7":{"position":[[680,9],[765,9]]},"9":{"position":[[297,9]]},"10":{"position":[[526,10],[600,10]]},"19":{"position":[[168,9]]},"20":{"position":[[2742,9]]},"24":{"position":[[207,9]]},"74":{"position":[[212,12],[858,9]]},"76":{"position":[[219,11],[679,12]]},"90":{"position":[[3525,10]]},"163":{"position":[[161,9]]},"165":{"position":[[1316,11]]},"175":{"position":[[1412,9]]},"188":{"position":[[1503,9],[1849,11]]}},"keywords":{}}],["calculate_closing_ret(djia",{"_index":1143,"title":{},"content":{"25":{"position":[[529,27]]}},"keywords":{}}],["calculate_closing_ret(fram",{"_index":1136,"title":{},"content":{"25":{"position":[[152,29]]}},"keywords":{}}],["calculate_closing_ret(nasdaq",{"_index":1147,"title":{},"content":{"25":{"position":[[621,29]]}},"keywords":{}}],["calculate_closing_ret(russ",{"_index":1145,"title":{},"content":{"25":{"position":[[574,27]]}},"keywords":{}}],["calculate_closing_ret(spi",{"_index":1141,"title":{},"content":{"25":{"position":[[485,26]]}},"keywords":{}}],["calculate_opening_ret(djia",{"_index":1041,"title":{},"content":{"24":{"position":[[811,27]]}},"keywords":{}}],["calculate_opening_ret(fram",{"_index":1023,"title":{},"content":{"24":{"position":[[427,29]]}},"keywords":{}}],["calculate_opening_ret(nasdaq",{"_index":1045,"title":{},"content":{"24":{"position":[[901,29]]}},"keywords":{}}],["calculate_opening_ret(russ",{"_index":1043,"title":{},"content":{"24":{"position":[[855,27]]}},"keywords":{}}],["calculate_opening_ret(spi",{"_index":1039,"title":{},"content":{"24":{"position":[[768,26]]}},"keywords":{}}],["calculated_term2",{"_index":502,"title":{},"content":{"10":{"position":[[438,16]]}},"keywords":{}}],["calculated_term2)"",{"_index":505,"title":{},"content":{"10":{"position":[[546,26]]}},"keywords":{}}],["calendar",{"_index":2967,"title":{},"content":{"90":{"position":[[419,9]]},"91":{"position":[[3802,8]]}},"keywords":{}}],["calendar=trade_calendar",{"_index":2977,"title":{},"content":{"90":{"position":[[714,24]]}},"keywords":{}}],["call",{"_index":543,"title":{"146":{"position":[[15,6]]}},"content":{"13":{"position":[[153,6],[191,4],[273,4]]},"14":{"position":[[308,6],[346,4],[610,4],[734,4],[760,6],[906,4],[1071,4],[1097,6],[1245,4]]},"15":{"position":[[311,4]]},"32":{"position":[[760,4]]},"33":{"position":[[465,6]]},"53":{"position":[[1727,4]]},"64":{"position":[[367,4]]},"95":{"position":[[489,4]]},"96":{"position":[[557,4]]},"97":{"position":[[404,4],[1343,6],[4255,4],[4339,4]]},"102":{"position":[[139,6]]},"122":{"position":[[191,4]]},"125":{"position":[[3193,4],[5154,5],[5444,4]]},"127":{"position":[[1508,4]]},"128":{"position":[[669,4],[708,4],[1427,4],[1466,4],[1817,4],[1941,5]]},"129":{"position":[[619,4],[689,4],[1039,4],[1702,4],[1807,4],[1856,4]]},"135":{"position":[[85,6]]},"136":{"position":[[53,5]]},"147":{"position":[[423,5]]},"150":{"position":[[107,4]]},"152":{"position":[[738,4]]},"156":{"position":[[542,4],[594,4],[773,5]]},"160":{"position":[[1277,6]]},"161":{"position":[[966,5]]},"163":{"position":[[439,6]]},"173":{"position":[[176,6],[948,6],[1097,5]]},"174":{"position":[[1217,6]]},"178":{"position":[[630,7]]},"180":{"position":[[620,4]]},"186":{"position":[[641,6]]},"188":{"position":[[909,4],[3736,4],[4441,7]]},"189":{"position":[[240,7],[319,7],[1483,4],[2960,7]]},"193":{"position":[[331,7],[643,7],[701,4],[775,4]]},"195":{"position":[[727,4]]},"196":{"position":[[1081,6]]},"197":{"position":[[998,4]]}},"keywords":{}}],["call_barri",{"_index":558,"title":{},"content":{"13":{"position":[[519,12],[653,13],[800,12],[1200,13]]},"14":{"position":[[1336,12],[1494,13],[1657,12],[2245,13]]},"15":{"position":[[705,12],[865,13],[1047,12],[1915,13]]}},"keywords":{}}],["call_onc",{"_index":5142,"title":{},"content":{"186":{"position":[[589,11]]}},"keywords":{}}],["callback_url",{"_index":2349,"title":{},"content":{"60":{"position":[[242,12]]},"61":{"position":[[1728,13]]}},"keywords":{}}],["caller",{"_index":5290,"title":{},"content":{"193":{"position":[[1602,6]]}},"keywords":{}}],["callingto_str",{"_index":4291,"title":{},"content":{"129":{"position":[[820,18]]}},"keywords":{}}],["came",{"_index":31,"title":{},"content":{"1":{"position":[[336,4]]},"2":{"position":[[264,4],[503,4]]},"53":{"position":[[2218,4]]}},"keywords":{}}],["can't",{"_index":1178,"title":{},"content":{"26":{"position":[[716,5]]},"39":{"position":[[1797,5]]},"46":{"position":[[301,5]]},"96":{"position":[[2051,5]]},"101":{"position":[[954,5]]},"106":{"position":[[704,5]]},"116":{"position":[[2862,5]]},"120":{"position":[[633,5]]},"125":{"position":[[4696,5],[8538,5],[9006,5],[9255,5]]},"127":{"position":[[473,5]]},"153":{"position":[[796,5]]},"160":{"position":[[1402,5]]},"165":{"position":[[544,5]]},"172":{"position":[[1608,5]]},"188":{"position":[[3229,5]]}},"keywords":{}}],["can'tcalendar",{"_index":3947,"title":{},"content":{"122":{"position":[[874,13]]}},"keywords":{}}],["canblock",{"_index":4964,"title":{},"content":{"173":{"position":[[1568,8]]}},"keywords":{}}],["cancondition",{"_index":5219,"title":{},"content":{"188":{"position":[[4159,16]]}},"keywords":{}}],["candid",{"_index":192,"title":{},"content":{"3":{"position":[[1114,10]]},"124":{"position":[[394,9]]}},"keywords":{}}],["candlestick_ohlc",{"_index":2846,"title":{},"content":{"88":{"position":[[383,16]]}},"keywords":{}}],["candlestick_ohlc(ax",{"_index":2867,"title":{},"content":{"88":{"position":[[1162,20]]}},"keywords":{}}],["canreleas",{"_index":4590,"title":{},"content":{"156":{"position":[[123,10]]}},"keywords":{}}],["canyarn",{"_index":4048,"title":{},"content":{"125":{"position":[[1448,7]]}},"keywords":{}}],["cap",{"_index":2955,"title":{},"content":{"89":{"position":[[805,3]]}},"keywords":{}}],["cap'n",{"_index":3662,"title":{"109":{"position":[[19,5]]},"164":{"position":[[0,5]]}},"content":{"108":{"position":[[271,5]]},"109":{"position":[[535,5],[645,5]]},"111":{"position":[[70,5],[606,5]]},"112":{"position":[[1238,5]]},"113":{"position":[[18,5],[127,5],[767,5],[2552,5]]},"116":{"position":[[3241,5]]},"117":{"position":[[49,5],[689,5],[2095,5]]},"164":{"position":[[56,5],[300,5],[629,5],[800,5],[1021,5],[1192,5],[1475,5]]},"165":{"position":[[164,5],[392,5],[1124,5]]},"166":{"position":[[326,5]]},"168":{"position":[[240,5]]},"169":{"position":[[354,5]]}},"keywords":{}}],["cap/high",{"_index":3191,"title":{},"content":{"93":{"position":[[679,8]]}},"keywords":{}}],["capabl",{"_index":3992,"title":{},"content":{"124":{"position":[[169,7]]}},"keywords":{}}],["capit",{"_index":575,"title":{},"content":{"13":{"position":[[937,7]]},"14":{"position":[[1955,7]]},"15":{"position":[[1623,7]]}},"keywords":{}}],["capnp",{"_index":3660,"title":{"108":{"position":[[19,6]]}},"content":{"108":{"position":[[5,5],[871,5]]},"109":{"position":[[11,5],[442,5]]},"113":{"position":[[307,7],[347,6]]}},"keywords":{}}],["capnp.ex",{"_index":3675,"title":{},"content":{"108":{"position":[[720,9]]}},"keywords":{}}],["capnp::message::builder::new_default",{"_index":3739,"title":{},"content":{"113":{"position":[[958,39]]}},"keywords":{}}],["capnp::message::readeroptions::new",{"_index":3759,"title":{},"content":{"113":{"position":[[1857,36]]},"115":{"position":[[312,36]]},"116":{"position":[[412,36]]},"117":{"position":[[1201,36]]}},"keywords":{}}],["capnp::message::typedreader<capnp::serialize::ownedseg",{"_index":3827,"title":{},"content":{"117":{"position":[[1268,63]]}},"keywords":{}}],["capnp::message::typedreader::new(deseri",{"_index":3829,"title":{},"content":{"117":{"position":[[1364,47]]}},"keywords":{}}],["capnp::private::arena::readerarena",{"_index":3781,"title":{},"content":{"115":{"position":[[1651,36],[1819,36]]},"116":{"position":[[1556,36],[1724,36]]}},"keywords":{}}],["capnp::private::layout::wirepoint",{"_index":3780,"title":{},"content":{"115":{"position":[[1279,36],[1544,36]]},"116":{"position":[[1231,36],[1449,36]]}},"keywords":{}}],["capnp::serialize::read_messag",{"_index":3757,"title":{},"content":{"113":{"position":[[1797,31]]},"115":{"position":[[252,31]]},"116":{"position":[[352,31]]},"117":{"position":[[1141,31]]}},"keywords":{}}],["capnp::serialize::write_message(&mut",{"_index":3754,"title":{},"content":{"113":{"position":[[1666,40]]}},"keywords":{}}],["capnp_cookbook_1",{"_index":3681,"title":{},"content":{"109":{"position":[[134,16],[154,16]]},"110":{"position":[[303,18]]},"112":{"position":[[649,16]]}},"keywords":{}}],["capnpc",{"_index":3690,"title":{},"content":{"109":{"position":[[398,6]]},"111":{"position":[[316,7],[533,7]]},"113":{"position":[[325,8]]}},"keywords":{}}],["capnpc::compilercommand::new",{"_index":3702,"title":{},"content":{"111":{"position":[[336,32]]}},"keywords":{}}],["capnproto",{"_index":3668,"title":{},"content":{"108":{"position":[[438,9]]},"109":{"position":[[511,10],[563,10]]}},"keywords":{}}],["capnpwindow",{"_index":3672,"title":{},"content":{"108":{"position":[[528,12]]}},"keywords":{}}],["captain'",{"_index":3658,"title":{"107":{"position":[[0,9]]},"114":{"position":[[0,9]]}},"content":{},"keywords":{}}],["captur",{"_index":2961,"title":{},"content":{"90":{"position":[[98,7]]},"159":{"position":[[42,8]]},"163":{"position":[[1432,8]]},"196":{"position":[[35,7],[165,7],[206,7],[905,8]]}},"keywords":{}}],["captured_len",{"_index":4788,"title":{},"content":{"163":{"position":[[1915,13]]}},"keywords":{}}],["car",{"_index":4425,"title":{},"content":{"139":{"position":[[642,5]]}},"keywords":{}}],["card",{"_index":4275,"title":{},"content":{"129":{"position":[[33,4]]}},"keywords":{}}],["care",{"_index":1395,"title":{},"content":{"30":{"position":[[4141,7]]},"43":{"position":[[1356,4],[1404,4]]},"73":{"position":[[419,4]]},"97":{"position":[[3016,4],[3152,4]]},"121":{"position":[[1637,7]]},"124":{"position":[[553,4]]},"125":{"position":[[4800,4]]},"147":{"position":[[75,7]]},"153":{"position":[[205,8]]},"158":{"position":[[131,4]]},"159":{"position":[[165,4]]},"172":{"position":[[2345,7]]},"173":{"position":[[1932,4]]},"176":{"position":[[889,4]]},"181":{"position":[[970,6]]}},"keywords":{}}],["career",{"_index":2203,"title":{},"content":{"53":{"position":[[302,6],[2175,7]]}},"keywords":{}}],["carefulli",{"_index":3826,"title":{},"content":{"117":{"position":[[931,9]]}},"keywords":{}}],["cargo",{"_index":3683,"title":{},"content":{"109":{"position":[[171,5]]},"112":{"position":[[133,5],[175,5]]},"113":{"position":[[508,6]]},"125":{"position":[[5204,5],[5752,5],[6516,5]]},"160":{"position":[[3602,5],[3616,5],[3679,6],[3704,5]]}},"keywords":{}}],["cargo.lock",{"_index":4148,"title":{},"content":{"125":{"position":[[7532,10]]}},"keywords":{}}],["cargo.toml",{"_index":3684,"title":{},"content":{"109":{"position":[[227,11]]},"111":{"position":[[239,10]]}},"keywords":{}}],["cari",{"_index":1231,"title":{},"content":{"28":{"position":[[1005,7]]},"30":{"position":[[7444,5],[8284,4],[8623,7],[10323,4]]}},"keywords":{}}],["carlo",{"_index":2301,"title":{},"content":{"55":{"position":[[124,5]]}},"keywords":{}}],["carolina",{"_index":1197,"title":{},"content":{"28":{"position":[[60,8]]},"30":{"position":[[84,9],[353,9],[529,8],[1017,8],[7807,9],[8041,8]]}},"keywords":{}}],["cary_forecast",{"_index":1353,"title":{},"content":{"30":{"position":[[1310,13]]}},"keywords":{}}],["cary_loc",{"_index":1450,"title":{},"content":{"30":{"position":[[8470,8],[8631,9]]}},"keywords":{}}],["case",{"_index":1432,"title":{"69":{"position":[[9,6]]},"70":{"position":[[5,4]]},"71":{"position":[[5,4]]},"131":{"position":[[2,4]]},"152":{"position":[[4,4]]}},"content":{"30":{"position":[[7612,4]]},"38":{"position":[[281,5]]},"51":{"position":[[2054,4]]},"53":{"position":[[1953,5],[2072,5]]},"64":{"position":[[728,4],[769,4]]},"68":{"position":[[73,5],[156,5],[899,4],[960,4]]},"69":{"position":[[115,5]]},"72":{"position":[[272,5]]},"75":{"position":[[206,4]]},"96":{"position":[[168,6]]},"104":{"position":[[819,5],[1220,5]]},"105":{"position":[[24,5]]},"116":{"position":[[61,4],[2614,5]]},"148":{"position":[[291,4]]},"152":{"position":[[153,6]]},"160":{"position":[[1184,6]]},"170":{"position":[[250,4],[278,4]]},"184":{"position":[[53,4],[467,6]]},"192":{"position":[[14,4]]},"196":{"position":[[752,5]]},"198":{"position":[[529,5]]}},"keywords":{}}],["case.th",{"_index":2055,"title":{},"content":{"49":{"position":[[190,8]]}},"keywords":{}}],["casino",{"_index":2553,"title":{"67":{"position":[[11,6]]},"77":{"position":[[13,7]]}},"content":{"69":{"position":[[175,6]]},"77":{"position":[[68,6]]},"78":{"position":[[5,6]]},"79":{"position":[[5,6]]},"80":{"position":[[5,6]]},"81":{"position":[[32,6]]},"83":{"position":[[630,7]]},"86":{"position":[[730,6]]}},"keywords":{}}],["casserol",{"_index":4748,"title":{},"content":{"161":{"position":[[1115,9]]}},"keywords":{}}],["catch",{"_index":2744,"title":{"77":{"position":[[0,8]]}},"content":{"77":{"position":[[58,5]]},"121":{"position":[[1376,5],[1567,5]]}},"keywords":{}}],["categor",{"_index":2633,"title":{},"content":{"74":{"position":[[473,11]]}},"keywords":{}}],["categori",{"_index":1015,"title":{},"content":{"24":{"position":[[77,8]]}},"keywords":{}}],["cathol",{"_index":2225,"title":{},"content":{"53":{"position":[[703,8]]}},"keywords":{}}],["caught",{"_index":3443,"title":{},"content":{"98":{"position":[[518,6]]}},"keywords":{}}],["caus",{"_index":828,"title":{},"content":{"20":{"position":[[1703,5]]},"125":{"position":[[9219,7]]},"153":{"position":[[492,6]]},"195":{"position":[[141,5]]}},"keywords":{}}],["caveat",{"_index":1306,"title":{"147":{"position":[[0,8]]}},"content":{"28":{"position":[[4017,7]]},"82":{"position":[[1158,6]]},"93":{"position":[[429,7]]},"160":{"position":[[3371,7]]},"184":{"position":[[770,7]]}},"keywords":{}}],["ccc",{"_index":553,"title":{},"content":{"13":{"position":[[370,3]]}},"keywords":{}}],["cd",{"_index":3682,"title":{},"content":{"109":{"position":[[151,2]]},"110":{"position":[[361,2]]},"125":{"position":[[3108,2]]}},"keywords":{}}],["cdef",{"_index":5161,"title":{},"content":{"188":{"position":[[970,4],[1046,4],[3524,4]]}},"keywords":{}}],["cdot",{"_index":550,"title":{},"content":{"13":{"position":[[325,5]]},"20":{"position":[[600,5],[693,5]]},"64":{"position":[[543,5],[558,5]]},"65":{"position":[[437,5],[452,5]]}},"keywords":{}}],["celgene'",{"_index":1845,"title":{},"content":{"40":{"position":[[3692,9]]}},"keywords":{}}],["cell",{"_index":4566,"title":{},"content":{"155":{"position":[[774,4]]},"173":{"position":[[1986,4],[2196,4]]},"179":{"position":[[581,4],[656,6],[736,6],[863,5]]},"180":{"position":[[373,5],[461,4]]}},"keywords":{}}],["cell.get_mut",{"_index":5097,"title":{},"content":{"180":{"position":[[503,17]]}},"keywords":{}}],["cell.replace(14",{"_index":5072,"title":{},"content":{"179":{"position":[[545,17],[953,17]]}},"keywords":{}}],["center",{"_index":5012,"title":{},"content":{"175":{"position":[[525,8]]}},"keywords":{}}],["center/data",{"_index":491,"title":{},"content":{"10":{"position":[[240,11]]}},"keywords":{}}],["center/interest",{"_index":493,"title":{},"content":{"10":{"position":[[258,15]]}},"keywords":{}}],["centered_data",{"_index":2983,"title":{},"content":{"90":{"position":[[1010,13],[2395,13]]}},"keywords":{}}],["centered_data.mean(axis=0",{"_index":2986,"title":{},"content":{"90":{"position":[[1106,26],[2491,26]]}},"keywords":{}}],["centered_data.shape[1",{"_index":2985,"title":{},"content":{"90":{"position":[[1064,22],[2449,22]]}},"keywords":{}}],["centered_data[:,lookforward",{"_index":2988,"title":{},"content":{"90":{"position":[[1152,29],[2537,29]]}},"keywords":{}}],["certainli",{"_index":3572,"title":{},"content":{"104":{"position":[[1988,9]]},"121":{"position":[[247,9]]},"173":{"position":[[26,9]]},"181":{"position":[[1020,9]]},"199":{"position":[[889,9]]}},"keywords":{}}],["chain",{"_index":2299,"title":{},"content":{"55":{"position":[[112,5]]},"95":{"position":[[450,5]]},"125":{"position":[[10173,5]]}},"keywords":{}}],["challeng",{"_index":255,"title":{},"content":{"4":{"position":[[730,10]]},"30":{"position":[[669,11]]},"53":{"position":[[1601,10]]},"61":{"position":[[1292,12]]}},"keywords":{}}],["chanc",{"_index":1220,"title":{},"content":{"28":{"position":[[700,6],[2870,7],[3855,6],[4275,6],[4339,7]]},"29":{"position":[[136,6]]},"30":{"position":[[4540,6],[4662,6],[5350,8],[5566,6],[5884,7],[5953,6]]},"49":{"position":[[333,6],[374,6]]}},"keywords":{}}],["chance".format(month",{"_index":1304,"title":{},"content":{"28":{"position":[[3778,27]]}},"keywords":{}}],["chane",{"_index":2206,"title":{},"content":{"53":{"position":[[362,5]]}},"keywords":{}}],["chang",{"_index":170,"title":{},"content":{"3":{"position":[[708,8],[789,8],[934,6]]},"4":{"position":[[1242,7]]},"20":{"position":[[46,6],[222,7]]},"24":{"position":[[123,6]]},"28":{"position":[[707,7]]},"38":{"position":[[1255,6]]},"76":{"position":[[1100,9],[1132,9],[1247,6],[1681,6],[1709,6],[1737,6],[1765,6]]},"97":{"position":[[4835,7],[6016,6],[6370,6]]},"104":{"position":[[1368,8]]},"125":{"position":[[2344,7]]},"160":{"position":[[88,6],[4401,7]]},"161":{"position":[[306,6]]},"163":{"position":[[506,8]]},"175":{"position":[[315,6]]},"178":{"position":[[210,9]]},"183":{"position":[[242,6],[879,7]]},"188":{"position":[[2711,6]]},"189":{"position":[[411,8]]}},"keywords":{}}],["changeswasm",{"_index":4211,"title":{},"content":{"125":{"position":[[11404,11]]}},"keywords":{}}],["channel",{"_index":3838,"title":{},"content":{"117":{"position":[[2022,8]]}},"keywords":{}}],["char",{"_index":4225,"title":{},"content":{"127":{"position":[[210,4]]}},"keywords":{}}],["charact",{"_index":2140,"title":{},"content":{"51":{"position":[[3008,10]]}},"keywords":{}}],["characterist",{"_index":541,"title":{},"content":{"13":{"position":[[121,16]]},"14":{"position":[[261,15]]},"172":{"position":[[436,16]]}},"keywords":{}}],["chars_remain",{"_index":2185,"title":{},"content":{"52":{"position":[[729,15],[866,15],[948,15]]}},"keywords":{}}],["chart",{"_index":492,"title":{},"content":{"10":{"position":[[252,5]]},"28":{"position":[[630,7]]},"30":{"position":[[2283,5],[5547,6]]},"33":{"position":[[412,5]]},"88":{"position":[[38,6],[1720,5],[2039,6],[2154,6]]},"90":{"position":[[81,5]]},"91":{"position":[[1402,7]]},"135":{"position":[[123,6]]}},"keywords":{}}],["chatter",{"_index":5023,"title":{},"content":{"175":{"position":[[987,7]]}},"keywords":{}}],["cheap",{"_index":3468,"title":{},"content":{"101":{"position":[[115,5]]}},"keywords":{}}],["cheat",{"_index":2554,"title":{"68":{"position":[[22,9]]}},"content":{"68":{"position":[[113,8],[307,8]]},"69":{"position":[[185,9]]},"72":{"position":[[36,8],[231,8],[738,9]]},"77":{"position":[[75,8]]}},"keywords":{}}],["check",{"_index":574,"title":{},"content":{"13":{"position":[[931,5]]},"14":{"position":[[1949,5]]},"15":{"position":[[1617,5]]},"24":{"position":[[1050,5],[2326,8],[2492,8]]},"25":{"position":[[770,5],[2215,8]]},"30":{"position":[[2795,5],[4437,8],[4471,5]]},"39":{"position":[[1910,5]]},"61":{"position":[[472,5],[679,6]]},"73":{"position":[[484,5]]},"103":{"position":[[1992,6]]},"123":{"position":[[367,5]]},"125":{"position":[[6451,6],[7518,5]]},"129":{"position":[[242,5]]},"143":{"position":[[538,5]]},"148":{"position":[[361,5]]},"156":{"position":[[1829,5]]},"157":{"position":[[474,5]]},"195":{"position":[[540,5]]}},"keywords":{}}],["checked:"",{"_index":1148,"title":{},"content":{"25":{"position":[[2050,15]]}},"keywords":{}}],["checker",{"_index":3355,"title":{"97":{"position":[[34,8]]}},"content":{"97":{"position":[[435,9]]},"115":{"position":[[3144,8]]},"164":{"position":[[724,8]]}},"keywords":{}}],["checkselectron",{"_index":4144,"title":{},"content":{"125":{"position":[[6896,14]]}},"keywords":{}}],["checksum",{"_index":5029,"title":{},"content":{"175":{"position":[[1202,10],[1422,9],[1593,9]]}},"keywords":{}}],["cheek",{"_index":4027,"title":{},"content":{"125":{"position":[[790,5]]}},"keywords":{}}],["child",{"_index":3792,"title":{},"content":{"115":{"position":[[2869,5],[3000,5]]},"116":{"position":[[2800,5]]}},"keywords":{}}],["china",{"_index":1808,"title":{},"content":{"40":{"position":[[1335,5]]}},"keywords":{}}],["chocolatey",{"_index":3673,"title":{},"content":{"108":{"position":[[591,11]]}},"keywords":{}}],["choic",{"_index":228,"title":{},"content":{"4":{"position":[[147,6]]},"125":{"position":[[8775,7]]},"176":{"position":[[540,6]]}},"keywords":{}}],["choos",{"_index":1595,"title":{},"content":{"34":{"position":[[551,7]]},"74":{"position":[[1531,6]]},"102":{"position":[[1198,6]]},"172":{"position":[[403,6]]},"173":{"position":[[1738,6]]},"178":{"position":[[742,8]]},"181":{"position":[[42,6],[750,6]]}},"keywords":{}}],["chop",{"_index":3571,"title":{},"content":{"104":{"position":[[1740,4]]}},"keywords":{}}],["choreographi",{"_index":4657,"title":{},"content":{"160":{"position":[[506,12]]}},"keywords":{}}],["chose",{"_index":2623,"title":{},"content":{"73":{"position":[[345,5]]},"86":{"position":[[165,5]]}},"keywords":{}}],["chosen",{"_index":1980,"title":{},"content":{"45":{"position":[[1304,6]]}},"keywords":{}}],["christma",{"_index":2220,"title":{},"content":{"53":{"position":[[650,9],[1488,10]]},"57":{"position":[[205,9]]}},"keywords":{}}],["chuck",{"_index":2058,"title":{},"content":{"49":{"position":[[358,5]]},"104":{"position":[[905,5]]}},"keywords":{}}],["circumst",{"_index":2618,"title":{},"content":{"72":{"position":[[498,12]]},"143":{"position":[[318,13]]},"172":{"position":[[2582,14]]},"196":{"position":[[1868,12]]}},"keywords":{}}],["cite",{"_index":2944,"title":{},"content":{"89":{"position":[[85,4]]}},"keywords":{}}],["citi",{"_index":1194,"title":{"28":{"position":[[16,7]]}},"content":{"28":{"position":[[155,7],[337,6],[410,5],[739,4],[857,5],[981,6],[2020,6],[2059,4],[2067,7],[2206,4],[2214,7],[2672,6],[3675,6],[3714,4],[3722,7],[3879,4],[3887,7],[4301,6]]},"29":{"position":[[162,6],[236,4]]},"30":{"position":[[8242,6],[8612,6],[9659,5]]},"53":{"position":[[1016,5]]}},"keywords":{}}],["cities.item",{"_index":1485,"title":{},"content":{"30":{"position":[[9672,15]]}},"keywords":{}}],["cities[i",{"_index":1234,"title":{},"content":{"28":{"position":[[1045,11]]}},"keywords":{}}],["citiesal",{"_index":1288,"title":{},"content":{"28":{"position":[[2662,9]]}},"keywords":{}}],["city_avg_cc(c",{"_index":1257,"title":{},"content":{"28":{"position":[[1790,17],[2027,17],[3682,17]]}},"keywords":{}}],["city_avg_precip(c",{"_index":1303,"title":{},"content":{"28":{"position":[[3538,21]]}},"keywords":{}}],["city_color",{"_index":1233,"title":{},"content":{"28":{"position":[[1031,11]]}},"keywords":{}}],["city_forecast",{"_index":1226,"title":{},"content":{"28":{"position":[[864,14]]},"30":{"position":[[1196,14],[9635,14]]}},"keywords":{}}],["city_forecasts[(c",{"_index":1491,"title":{},"content":{"30":{"position":[[9833,21],[9917,21]]}},"keywords":{}}],["claim",{"_index":1678,"title":{},"content":{"36":{"position":[[5,6]]},"165":{"position":[[258,6]]}},"keywords":{}}],["clarifi",{"_index":3072,"title":{},"content":{"91":{"position":[[164,7]]}},"keywords":{}}],["class",{"_index":880,"title":{},"content":{"22":{"position":[[40,7],[143,5],[464,9],[1088,5]]},"43":{"position":[[702,7],[875,8]]},"45":{"position":[[807,8],[1205,8]]},"54":{"position":[[8,5]]},"86":{"position":[[40,7]]},"93":{"position":[[1457,5]]},"127":{"position":[[581,5],[1231,5]]},"129":{"position":[[1915,5]]}},"keywords":{}}],["classif",{"_index":1962,"title":{},"content":{"45":{"position":[[215,14],[839,15]]}},"keywords":{}}],["classifi",{"_index":1897,"title":{"44":{"position":[[40,12]]}},"content":{"44":{"position":[[78,11],[1788,11]]},"45":{"position":[[3428,12]]}},"keywords":{}}],["clb",{"_index":712,"title":{},"content":{"17":{"position":[[169,6]]},"18":{"position":[[207,7]]},"19":{"position":[[436,7]]},"20":{"position":[[356,7],[2886,7]]}},"keywords":{}}],["clean",{"_index":2293,"title":{},"content":{"54":{"position":[[271,5]]},"193":{"position":[[1001,6]]}},"keywords":{}}],["clear",{"_index":114,"title":{},"content":{"2":{"position":[[605,5]]},"3":{"position":[[519,5]]},"28":{"position":[[2794,6]]},"116":{"position":[[2518,6]]},"181":{"position":[[886,5]]},"183":{"position":[[288,6]]},"189":{"position":[[1861,5]]}},"keywords":{}}],["cli",{"_index":4140,"title":{},"content":{"125":{"position":[[6490,4],[7631,3]]}},"keywords":{}}],["cli/bin/cli.js"",{"_index":4121,"title":{},"content":{"125":{"position":[[5505,20],[5967,20]]}},"keywords":{}}],["click",{"_index":4034,"title":{},"content":{"125":{"position":[[983,6]]}},"keywords":{}}],["client",{"_index":2345,"title":{},"content":{"60":{"position":[[108,6]]},"88":{"position":[[731,6]]},"93":{"position":[[4146,6]]}},"keywords":{}}],["client_id",{"_index":2348,"title":{},"content":{"60":{"position":[[231,10]]},"61":{"position":[[1742,12],[1755,9],[2012,9]]}},"keywords":{}}],["client_secret",{"_index":2347,"title":{},"content":{"60":{"position":[[216,14]]}},"keywords":{}}],["clippi",{"_index":5089,"title":{},"content":{"179":{"position":[[1725,6]]}},"keywords":{}}],["clone",{"_index":3449,"title":{},"content":{"98":{"position":[[858,9]]},"125":{"position":[[3053,5]]},"198":{"position":[[1115,7]]}},"keywords":{}}],["cloneabl",{"_index":5365,"title":{},"content":{"198":{"position":[[997,9]]}},"keywords":{}}],["close",{"_index":720,"title":{"25":{"position":[[31,6]]}},"content":{"17":{"position":[[244,7]]},"24":{"position":[[139,5]]},"25":{"position":[[59,5],[2681,6]]},"26":{"position":[[25,5],[279,9],[799,6]]},"32":{"position":[[561,5],[1087,7],[1251,7],[2307,7]]},"33":{"position":[[134,7],[488,7],[623,7],[785,5],[1090,6]]},"34":{"position":[[418,7],[531,5],[643,7],[3139,5],[3658,6]]},"35":{"position":[[96,7]]},"39":{"position":[[1848,5]]},"40":{"position":[[796,5],[3129,5]]},"41":{"position":[[501,5]]},"43":{"position":[[945,7]]},"51":{"position":[[2143,6]]},"53":{"position":[[1294,5],[2009,5]]},"74":{"position":[[1587,5]]},"75":{"position":[[1251,5]]},"90":{"position":[[3931,7]]},"91":{"position":[[310,7],[2594,7]]},"92":{"position":[[406,7]]},"93":{"position":[[2019,7],[2056,6]]},"102":{"position":[[636,5],[807,5]]},"105":{"position":[[95,5],[3118,5]]},"116":{"position":[[2830,7]]},"121":{"position":[[423,5],[1826,5]]},"122":{"position":[[489,5]]},"123":{"position":[[397,5]]},"128":{"position":[[1677,5]]},"132":{"position":[[80,7]]},"155":{"position":[[269,7]]}},"keywords":{}}],["close"",{"_index":1752,"title":{},"content":{"39":{"position":[[2357,11],[2423,11]]}},"keywords":{}}],["close_column",{"_index":1754,"title":{},"content":{"39":{"position":[[2393,12],[2441,12]]}},"keywords":{}}],["close_v",{"_index":1138,"title":{},"content":{"25":{"position":[[375,9],[423,10]]},"34":{"position":[[1749,10]]},"39":{"position":[[1018,11]]}},"keywords":{}}],["close_vals[day",{"_index":1742,"title":{},"content":{"39":{"position":[[2017,14]]}},"keywords":{}}],["closed='left",{"_index":1243,"title":{},"content":{"28":{"position":[[1352,14],[3152,14]]},"30":{"position":[[1718,14],[3067,14],[4991,14],[6135,14]]}},"keywords":{}}],["closer",{"_index":3190,"title":{},"content":{"93":{"position":[[601,6]]},"97":{"position":[[4799,6]]}},"keywords":{}}],["closur",{"_index":3415,"title":{"196":{"position":[[0,9]]}},"content":{"97":{"position":[[4534,7],[4686,7]]},"147":{"position":[[381,7]]},"159":{"position":[[681,8]]},"179":{"position":[[1509,7]]},"196":{"position":[[413,8],[468,8],[779,7],[859,8],[1002,7],[1277,8]]}},"keywords":{}}],["closure@src/main.rs:31:37",{"_index":3775,"title":{},"content":{"115":{"position":[[1008,28],[1355,28],[2096,28]]}},"keywords":{}}],["cloud",{"_index":1217,"title":{},"content":{"28":{"position":[[670,5],[2109,5],[2706,5],[2822,5],[4161,5],[4365,5]]},"29":{"position":[[98,5]]},"30":{"position":[[832,5],[996,5],[1170,5],[2086,5],[2329,5],[2397,5],[2572,5],[3771,5],[4048,5],[4446,5],[5785,5]]}},"keywords":{}}],["cloud_cover_sampl",{"_index":1247,"title":{},"content":{"28":{"position":[[1461,19],[1738,19]]},"30":{"position":[[1822,19],[1944,19],[3171,19],[3354,19]]}},"keywords":{}}],["cloud_cover_v",{"_index":1244,"title":{},"content":{"28":{"position":[[1367,16],[1526,19]]},"30":{"position":[[1733,16],[1887,19],[3082,16],[3236,19],[3298,17]]}},"keywords":{}}],["cloudcov",{"_index":1237,"title":{},"content":{"28":{"position":[[1126,12]]},"30":{"position":[[1498,12]]}},"keywords":{}}],["cloudi",{"_index":1191,"title":{"27":{"position":[[0,6]]}},"content":{"28":{"position":[[236,6],[315,7],[2629,6]]},"30":{"position":[[581,6],[1075,7],[2819,6],[3572,6],[3996,6],[4345,7],[4702,6],[5739,6],[7675,6]]}},"keywords":{}}],["cloudy_day",{"_index":1383,"title":{},"content":{"30":{"position":[[3256,11]]}},"keywords":{}}],["cmp(12",{"_index":4524,"title":{},"content":{"152":{"position":[[1118,7]]}},"keywords":{}}],["cmp(x",{"_index":4513,"title":{},"content":{"152":{"position":[[473,6]]}},"keywords":{}}],["cmr",{"_index":3944,"title":{},"content":{"122":{"position":[[704,3]]}},"keywords":{}}],["cn∑i=1ndioi>∑i=1ndic_n",{"_index":1529,"title":{},"content":{"32":{"position":[[799,25]]}},"keywords":{}}],["cn∑i=1n−1dioi+cndnon>∑i=1n−1di+dncndnon−dn>∑i=1n−1(di−cndioi)dn(cn−onon)>∑i=1n−1di(1−cnoi)dn>oncn−on∑i=1n−1di(1−1oi)\\begin{align",{"_index":1540,"title":{},"content":{"32":{"position":[[1429,142]]}},"keywords":{}}],["co",{"_index":3896,"title":{},"content":{"121":{"position":[[1332,2]]}},"keywords":{}}],["code",{"_index":116,"title":{"76":{"position":[[11,5]]}},"content":{"2":{"position":[[640,4],[824,5]]},"3":{"position":[[231,4]]},"25":{"position":[[11,4],[114,5]]},"30":{"position":[[930,4],[8127,4]]},"34":{"position":[[1004,5],[1368,4]]},"39":{"position":[[130,4],[242,5]]},"43":{"position":[[238,4]]},"47":{"position":[[1,4]]},"50":{"position":[[272,5]]},"52":{"position":[[28,4]]},"53":{"position":[[267,4]]},"54":{"position":[[247,4]]},"61":{"position":[[2103,4]]},"64":{"position":[[1404,4]]},"73":{"position":[[478,5],[505,5]]},"76":{"position":[[1829,4]]},"86":{"position":[[498,4]]},"88":{"position":[[246,4],[971,4],[2433,4]]},"90":{"position":[[171,4]]},"91":{"position":[[403,4],[1733,4],[1814,4],[2745,4],[5138,4],[5515,4]]},"92":{"position":[[223,4],[557,4],[1680,4],[1839,4]]},"93":{"position":[[1240,4],[3795,4]]},"97":{"position":[[2985,4],[3779,4],[5469,5],[5577,4]]},"98":{"position":[[376,4]]},"103":{"position":[[728,4]]},"108":{"position":[[128,4]]},"109":{"position":[[496,4]]},"111":{"position":[[101,4]]},"112":{"position":[[121,5],[255,4],[349,4],[474,4],[1220,5],[1379,5]]},"113":{"position":[[80,4],[170,4],[255,4],[416,4],[549,4],[1094,4]]},"115":{"position":[[77,4],[2829,5]]},"116":{"position":[[2763,4]]},"117":{"position":[[66,5]]},"120":{"position":[[303,4]]},"121":{"position":[[137,4],[188,4],[409,5],[626,4],[715,4],[1127,4],[1279,4],[1765,4],[2245,4]]},"124":{"position":[[690,5]]},"125":{"position":[[659,4],[2749,4],[3776,4],[6542,4],[6777,4]]},"128":{"position":[[80,4],[380,4]]},"129":{"position":[[1353,4]]},"130":{"position":[[501,5]]},"133":{"position":[[140,5]]},"136":{"position":[[178,4]]},"139":{"position":[[226,4],[558,4],[967,4]]},"142":{"position":[[182,4]]},"143":{"position":[[92,4],[279,4],[407,4],[554,4]]},"147":{"position":[[41,4]]},"148":{"position":[[54,4],[186,4]]},"152":{"position":[[866,5]]},"153":{"position":[[103,4],[438,5]]},"155":{"position":[[1273,5]]},"158":{"position":[[36,5],[83,5]]},"160":{"position":[[454,4],[2640,4],[3083,4],[3578,4]]},"163":{"position":[[785,4],[2277,4],[2496,4]]},"164":{"position":[[1327,4]]},"169":{"position":[[156,4]]},"172":{"position":[[2074,5],[2430,4]]},"173":{"position":[[1,4],[49,4],[1479,4]]},"174":{"position":[[213,5],[345,4]]},"178":{"position":[[468,5]]},"181":{"position":[[1032,4]]},"183":{"position":[[151,5]]},"185":{"position":[[493,5]]},"186":{"position":[[507,4]]},"188":{"position":[[226,4],[602,4]]},"189":{"position":[[298,4],[375,4],[770,4],[1921,4]]},"190":{"position":[[141,4],[710,4]]},"193":{"position":[[711,5]]},"196":{"position":[[1465,4]]},"199":{"position":[[87,4]]}},"keywords":{}}],["codeandth",{"_index":3924,"title":{},"content":{"121":{"position":[[2500,10]]}},"keywords":{}}],["codeat",{"_index":5227,"title":{},"content":{"189":{"position":[[170,6]]}},"keywords":{}}],["codec",{"_index":3651,"title":{},"content":{"106":{"position":[[425,6]]}},"keywords":{}}],["codecontain",{"_index":5223,"title":{},"content":{"188":{"position":[[4301,12]]}},"keywords":{}}],["codegen",{"_index":3735,"title":{},"content":{"113":{"position":[[587,7]]}},"keywords":{}}],["coef",{"_index":2684,"title":{},"content":{"76":{"position":[[424,5],[458,5],[713,5],[758,5],[783,7]]}},"keywords":{}}],["coef_rang",{"_index":2760,"title":{},"content":{"78":{"position":[[418,10]]}},"keywords":{}}],["cognit",{"_index":4662,"title":{},"content":{"160":{"position":[[689,9]]}},"keywords":{}}],["coin",{"_index":1130,"title":{},"content":{"24":{"position":[[3238,4]]},"26":{"position":[[102,4],[254,4]]}},"keywords":{}}],["coin_toss",{"_index":2742,"title":{},"content":{"76":{"position":[[3062,9],[3094,9]]}},"keywords":{}}],["col",{"_index":1900,"title":{},"content":{"44":{"position":[[205,4],[244,5]]}},"keywords":{}}],["cold",{"_index":298,"title":{},"content":{"4":{"position":[[1508,4]]},"53":{"position":[[1046,4]]}},"keywords":{}}],["collect",{"_index":4341,"title":{"156":{"position":[[0,12]]}},"content":{"132":{"position":[[167,10]]},"156":{"position":[[1,10],[258,11],[404,11],[472,11]]},"160":{"position":[[1071,8]]},"172":{"position":[[9,11],[44,10],[142,9],[209,9],[535,11],[666,10]]},"176":{"position":[[475,10]]},"199":{"position":[[587,10],[1024,11]]}},"keywords":{}}],["collection.java",{"_index":4902,"title":{},"content":{"172":{"position":[[348,15]]}},"keywords":{}}],["collector",{"_index":3446,"title":{},"content":{"98":{"position":[[583,9]]}},"keywords":{}}],["collus",{"_index":2947,"title":{},"content":{"89":{"position":[[237,10]]}},"keywords":{}}],["color",{"_index":429,"title":{},"content":{"7":{"position":[[1044,5],[1148,6],[1172,6]]},"134":{"position":[[409,7]]}},"keywords":{}}],["color='b",{"_index":2882,"title":{},"content":{"88":{"position":[[1594,10],[1921,10],[2567,10],[2668,10]]}},"keywords":{}}],["color='g",{"_index":2927,"title":{},"content":{"88":{"position":[[3051,10],[3436,10]]},"91":{"position":[[812,10],[1282,10]]}},"keywords":{}}],["color=city_colors[c",{"_index":1278,"title":{},"content":{"28":{"position":[[2287,24],[3960,24]]}},"keywords":{}}],["color=color",{"_index":438,"title":{},"content":{"7":{"position":[[1230,13]]}},"keywords":{}}],["color=palette[x",{"_index":1368,"title":{},"content":{"30":{"position":[[2234,17],[3719,17],[3942,17],[5498,17],[6799,17],[7022,17]]}},"keywords":{}}],["columbu",{"_index":2972,"title":{},"content":{"90":{"position":[[602,8]]}},"keywords":{}}],["column",{"_index":1953,"title":{},"content":{"44":{"position":[[1844,7]]},"102":{"position":[[1014,7]]}},"keywords":{}}],["combin",{"_index":4768,"title":{},"content":{"163":{"position":[[669,9]]}},"keywords":{}}],["combust",{"_index":4506,"title":{},"content":{"150":{"position":[[869,7]]}},"keywords":{}}],["come",{"_index":74,"title":{},"content":{"2":{"position":[[5,5]]},"3":{"position":[[5,5]]},"4":{"position":[[316,5]]},"30":{"position":[[783,5],[7984,6]]},"40":{"position":[[2124,4]]},"46":{"position":[[576,4]]},"51":{"position":[[3108,4]]},"57":{"position":[[507,5]]},"61":{"position":[[58,6]]},"64":{"position":[[200,5]]},"65":{"position":[[5,5],[119,4]]},"66":{"position":[[683,6]]},"69":{"position":[[126,4]]},"83":{"position":[[57,4],[200,4]]},"95":{"position":[[179,6],[390,6]]},"96":{"position":[[1521,4]]},"97":{"position":[[1447,4]]},"102":{"position":[[79,5]]},"103":{"position":[[27,5],[2339,5]]},"120":{"position":[[356,4]]},"125":{"position":[[9549,6],[11604,5]]},"127":{"position":[[41,5]]},"133":{"position":[[374,5]]},"152":{"position":[[24,5]]},"155":{"position":[[238,5]]},"157":{"position":[[327,5]]},"158":{"position":[[364,5]]},"188":{"position":[[284,5]]},"192":{"position":[[19,5]]},"197":{"position":[[16,4]]}},"keywords":{}}],["comfort",{"_index":4818,"title":{},"content":{"164":{"position":[[1554,11]]}},"keywords":{}}],["coming.i'm",{"_index":3441,"title":{},"content":{"98":{"position":[[415,10]]}},"keywords":{}}],["command",{"_index":3677,"title":{},"content":{"108":{"position":[[841,7]]},"112":{"position":[[145,8],[577,7],[736,7]]},"124":{"position":[[214,7]]},"173":{"position":[[634,7]]}},"keywords":{}}],["comment",{"_index":3729,"title":{},"content":{"113":{"position":[[233,8]]},"122":{"position":[[628,8]]},"148":{"position":[[582,8]]}},"keywords":{}}],["common",{"_index":4591,"title":{},"content":{"156":{"position":[[317,6]]}},"keywords":{}}],["commun",{"_index":5271,"title":{},"content":{"193":{"position":[[38,11]]}},"keywords":{}}],["compani",{"_index":2948,"title":{"149":{"position":[[11,9]]}},"content":{"89":{"position":[[254,7]]},"90":{"position":[[3479,7]]},"93":{"position":[[717,9],[1228,10],[1854,7]]},"150":{"position":[[742,8]]}},"keywords":{}}],["compar",{"_index":989,"title":{},"content":{"23":{"position":[[51,7]]},"28":{"position":[[485,9]]},"30":{"position":[[7200,8],[8002,7]]},"102":{"position":[[684,10]]},"152":{"position":[[649,7]]},"161":{"position":[[725,8]]},"172":{"position":[[2362,9]]},"189":{"position":[[579,10]]}},"keywords":{}}],["comparison",{"_index":1012,"title":{"24":{"position":[[12,11]]}},"content":{"105":{"position":[[3147,11]]},"112":{"position":[[1564,11]]},"121":{"position":[[2471,11]]},"152":{"position":[[794,10]]}},"keywords":{}}],["compat",{"_index":157,"title":{},"content":{"3":{"position":[[466,13],[1416,16]]},"124":{"position":[[33,10]]},"125":{"position":[[6819,10]]}},"keywords":{}}],["compens",{"_index":852,"title":{},"content":{"20":{"position":[[2447,10]]}},"keywords":{}}],["competit",{"_index":699,"title":{"17":{"position":[[8,11]]}},"content":{},"keywords":{}}],["compil",{"_index":93,"title":{"151":{"position":[[21,8]]}},"content":{"2":{"position":[[289,8]]},"96":{"position":[[1889,7],[2033,7]]},"97":{"position":[[42,8],[460,8],[480,7],[1748,7],[4168,8]]},"111":{"position":[[201,9],[524,8],[558,7],[701,8]]},"115":{"position":[[857,8]]},"116":{"position":[[2456,8],[2853,8]]},"121":{"position":[[2109,8],[2256,9]]},"125":{"position":[[6108,7],[6525,7],[6752,7],[7133,8],[7682,9]]},"127":{"position":[[694,8]]},"128":{"position":[[307,8],[1364,8]]},"129":{"position":[[383,8],[1365,8]]},"152":{"position":[[582,8],[1662,8]]},"153":{"position":[[352,8],[868,8],[1033,8]]},"155":{"position":[[1610,8]]},"156":{"position":[[701,8]]},"159":{"position":[[438,8],[518,8]]},"160":{"position":[[540,9],[651,8],[962,8],[2987,8],[3109,8],[3242,8]]},"172":{"position":[[1744,12],[1776,8],[1918,8],[2130,11],[2472,8]]},"174":{"position":[[281,8]]},"178":{"position":[[158,8],[408,8],[669,7],[686,8]]},"180":{"position":[[194,7],[528,8],[551,8]]},"181":{"position":[[29,8],[356,8],[737,8]]},"183":{"position":[[623,8],[834,8]]},"184":{"position":[[983,7]]},"185":{"position":[[545,7]]},"188":{"position":[[439,11]]},"189":{"position":[[76,9],[125,8],[275,8],[510,8],[781,8],[1516,12],[1599,8],[1969,12]]},"190":{"position":[[573,9]]},"192":{"position":[[566,8]]},"193":{"position":[[257,8],[825,8],[1244,8],[1968,8],[2923,8],[3775,8]]},"194":{"position":[[436,8],[535,8]]},"195":{"position":[[979,8]]},"196":{"position":[[1195,8],[1295,8],[1606,8],[1808,8],[1893,8]]},"197":{"position":[[1421,8]]},"198":{"position":[[1169,8]]},"199":{"position":[[1709,8]]}},"keywords":{}}],["compiler'",{"_index":5277,"title":{},"content":{"193":{"position":[[739,10]]},"196":{"position":[[609,10]]}},"keywords":{}}],["compiler)th",{"_index":3692,"title":{},"content":{"109":{"position":[[522,12]]}},"keywords":{}}],["compilercommanddynam",{"_index":3711,"title":{},"content":{"111":{"position":[[858,27]]}},"keywords":{}}],["complain",{"_index":1321,"title":{"30":{"position":[[0,11]]}},"content":{"30":{"position":[[38,11],[2479,12],[7647,9]]},"112":{"position":[[181,12]]},"116":{"position":[[2897,9]]},"139":{"position":[[15,11]]}},"keywords":{}}],["complaint",{"_index":3434,"title":{},"content":{"97":{"position":[[6138,9]]}},"keywords":{}}],["complet",{"_index":2194,"title":{},"content":{"53":{"position":[[23,10]]},"75":{"position":[[1119,8]]},"88":{"position":[[114,9]]},"153":{"position":[[974,9]]},"173":{"position":[[1199,9]]},"188":{"position":[[3261,10]]}},"keywords":{}}],["complex",{"_index":2,"title":{"0":{"position":[[23,7]]}},"content":{"3":{"position":[[1159,10]]},"4":{"position":[[1028,11]]},"97":{"position":[[1215,8],[2963,7]]},"109":{"position":[[99,7]]},"117":{"position":[[494,8]]},"125":{"position":[[7109,10]]},"160":{"position":[[33,7],[229,10],[498,7]]},"163":{"position":[[252,8],[742,7],[2181,7]]},"196":{"position":[[1741,9]]},"199":{"position":[[1438,7]]}},"keywords":{}}],["complex"",{"_index":272,"title":{},"content":{"4":{"position":[[966,15]]}},"keywords":{}}],["complexitywebpack",{"_index":264,"title":{},"content":{"4":{"position":[[845,17]]}},"keywords":{}}],["complic",{"_index":2344,"title":{},"content":{"59":{"position":[[166,11]]},"73":{"position":[[141,12]]},"85":{"position":[[160,11]]},"108":{"position":[[562,12]]},"121":{"position":[[777,11]]},"125":{"position":[[3671,11],[6939,12]]},"129":{"position":[[770,12],[2684,12]]},"190":{"position":[[524,12]]}},"keywords":{}}],["compon",{"_index":1977,"title":{},"content":{"45":{"position":[[1092,10]]},"102":{"position":[[1185,10],[1243,11],[1333,11]]},"103":{"position":[[1947,10]]},"104":{"position":[[375,9],[480,10],[664,10],[888,11],[925,10],[1097,10],[1201,10],[1456,11]]},"105":{"position":[[62,10],[146,10],[670,10],[3077,10]]},"106":{"position":[[227,9],[581,11]]},"198":{"position":[[755,10]]}},"keywords":{}}],["component_byt",{"_index":3586,"title":{},"content":{"105":{"position":[[764,15]]}},"keywords":{}}],["compos",{"_index":3817,"title":{},"content":{"117":{"position":[[302,7]]}},"keywords":{}}],["comprehens",{"_index":1028,"title":{},"content":{"24":{"position":[[536,13]]},"25":{"position":[[261,13]]},"30":{"position":[[9549,13]]},"121":{"position":[[2414,14],[2444,15],[2614,14]]}},"keywords":{}}],["compress",{"_index":3455,"title":{"99":{"position":[[10,11]]},"100":{"position":[[32,11]]},"101":{"position":[[30,12]]},"102":{"position":[[12,11]]}},"content":{"100":{"position":[[433,11]]},"101":{"position":[[228,8],[346,11],[461,8],[550,11],[698,12],[811,11]]},"102":{"position":[[214,12],[377,11]]},"105":{"position":[[464,8],[925,11],[1081,10]]},"106":{"position":[[33,11]]}},"keywords":{}}],["compress(bytestr",{"_index":3594,"title":{},"content":{"105":{"position":[[1094,20]]}},"keywords":{}}],["compression_attempt",{"_index":3596,"title":{},"content":{"105":{"position":[[1148,20],[1751,20],[1900,20]]}},"keywords":{}}],["comput",{"_index":453,"title":{"9":{"position":[[0,9]]}},"content":{"11":{"position":[[258,7]]},"12":{"position":[[74,9]]},"44":{"position":[[1980,11]]},"45":{"position":[[1365,8],[2524,13]]},"53":{"position":[[83,8]]},"74":{"position":[[1293,13],[1414,8],[1613,8]]},"86":{"position":[[908,7]]},"128":{"position":[[166,9]]},"132":{"position":[[926,8]]},"173":{"position":[[1667,8]]},"174":{"position":[[1028,8]]},"175":{"position":[[266,9]]},"189":{"position":[[2074,8]]}},"keywords":{}}],["concat",{"_index":3345,"title":{},"content":{"96":{"position":[[1543,7],[1853,7],[2057,8]]}},"keywords":{}}],["concat!("y",{"_index":3347,"title":{},"content":{"96":{"position":[[1706,17]]}},"keywords":{}}],["concaten",{"_index":3343,"title":{},"content":{"96":{"position":[[1460,11]]}},"keywords":{}}],["concept",{"_index":2323,"title":{},"content":{"58":{"position":[[144,7]]},"125":{"position":[[10204,8],[10454,8]]}},"keywords":{}}],["concern",{"_index":761,"title":{},"content":{"20":{"position":[[138,9]]},"30":{"position":[[9200,9]]},"33":{"position":[[373,9]]},"44":{"position":[[1009,10]]},"86":{"position":[[231,9]]},"102":{"position":[[339,8]]},"164":{"position":[[238,8]]},"166":{"position":[[234,9]]},"176":{"position":[[1353,8]]}},"keywords":{}}],["conclud",{"_index":2614,"title":{},"content":{"72":{"position":[[208,8],[712,8]]},"188":{"position":[[4363,9]]}},"keywords":{}}],["conclus",{"_index":1311,"title":{"29":{"position":[[0,11]]},"72":{"position":[[10,11]]},"83":{"position":[[0,11]]},"93":{"position":[[0,10]]},"98":{"position":[[0,11]]},"106":{"position":[[0,12]]},"124":{"position":[[12,11]]},"130":{"position":[[0,11]]},"137":{"position":[[0,11]]},"148":{"position":[[0,11]]},"170":{"position":[[0,11]]},"190":{"position":[[0,11]]}},"content":{"30":{"position":[[7391,11]]}},"keywords":{}}],["concurr",{"_index":3201,"title":{},"content":{"93":{"position":[[1419,10]]}},"keywords":{}}],["condit",{"_index":1442,"title":{},"content":{"30":{"position":[[8021,10]]},"51":{"position":[[728,11]]},"160":{"position":[[3356,10]]},"188":{"position":[[4209,10]]}},"keywords":{}}],["confer",{"_index":2276,"title":{},"content":{"53":{"position":[[1508,10]]}},"keywords":{}}],["confid",{"_index":2294,"title":{},"content":{"55":{"position":[[12,9]]},"170":{"position":[[145,9]]}},"keywords":{}}],["configur",{"_index":168,"title":{},"content":{"3":{"position":[[658,14],[729,14],[953,14]]},"97":{"position":[[6257,9]]}},"keywords":{}}],["confirm",{"_index":1285,"title":{},"content":{"28":{"position":[[2520,9],[4130,7]]},"30":{"position":[[7620,12]]}},"keywords":{}}],["confus",{"_index":196,"title":{},"content":{"3":{"position":[[1186,10]]}},"keywords":{}}],["congest",{"_index":5016,"title":{},"content":{"175":{"position":[[652,10]]}},"keywords":{}}],["congratul",{"_index":3982,"title":{},"content":{"123":{"position":[[726,15]]}},"keywords":{}}],["connect",{"_index":50,"title":{},"content":{"1":{"position":[[567,10]]},"173":{"position":[[1649,9]]},"175":{"position":[[138,10],[1011,10]]}},"keywords":{}}],["conrod",{"_index":4044,"title":{},"content":{"125":{"position":[[1326,7]]}},"keywords":{}}],["consequ",{"_index":5299,"title":{},"content":{"193":{"position":[[1992,11]]}},"keywords":{}}],["conserv",{"_index":1855,"title":{},"content":{"41":{"position":[[558,12]]}},"keywords":{}}],["consid",{"_index":1584,"title":{},"content":{"33":{"position":[[1036,8]]},"40":{"position":[[3643,8]]},"72":{"position":[[386,11]]},"132":{"position":[[206,10]]}},"keywords":{}}],["consider",{"_index":2320,"title":{"58":{"position":[[12,15]]}},"content":{"58":{"position":[[62,14]]}},"keywords":{}}],["consist",{"_index":1166,"title":{},"content":{"25":{"position":[[2802,13]]},"28":{"position":[[4255,12]]},"40":{"position":[[1035,12]]},"181":{"position":[[945,11]]}},"keywords":{}}],["const",{"_index":3772,"title":{"178":{"position":[[0,5]]}},"content":{"115":{"position":[[957,7],[1189,7],[1271,7],[1536,7],[1928,7],[2277,7]]},"116":{"position":[[956,7],[1141,7],[1223,7],[1441,7],[1833,7],[2135,7],[2680,7]]},"159":{"position":[[410,5]]},"163":{"position":[[1678,5]]},"178":{"position":[[136,6],[524,5],[536,5],[640,5],[717,5]]},"179":{"position":[[771,5],[857,5],[1245,5],[1423,7]]},"180":{"position":[[35,5],[124,5],[367,5]]},"181":{"position":[[57,5],[72,5],[667,5],[926,5],[997,5]]},"182":{"position":[[33,5],[479,6]]},"183":{"position":[[39,5],[107,5],[224,5]]},"184":{"position":[[442,5],[550,5],[814,5]]}},"keywords":{}}],["constant",{"_index":3528,"title":{},"content":{"103":{"position":[[1114,11]]},"152":{"position":[[618,8]]},"179":{"position":[[126,9]]}},"keywords":{}}],["constant_values=0",{"_index":3529,"title":{},"content":{"103":{"position":[[1126,18]]}},"keywords":{}}],["constantli",{"_index":5259,"title":{},"content":{"190":{"position":[[271,10]]}},"keywords":{}}],["constitut",{"_index":1681,"title":{},"content":{"36":{"position":[[115,10]]}},"keywords":{}}],["constraint",{"_index":837,"title":{},"content":{"20":{"position":[[2014,11]]},"160":{"position":[[1795,11],[2485,11]]}},"keywords":{}}],["constraints=constraint",{"_index":844,"title":{},"content":{"20":{"position":[[2245,24]]}},"keywords":{}}],["construct",{"_index":509,"title":{},"content":{"11":{"position":[[101,9]]},"51":{"position":[[2776,12],[3418,13]]},"117":{"position":[[941,9]]}},"keywords":{}}],["contact",{"_index":1889,"title":{},"content":{"43":{"position":[[1332,7],[1382,10]]}},"keywords":{}}],["contain",{"_index":1969,"title":{},"content":{"45":{"position":[[467,9]]},"61":{"position":[[1998,10],[2179,8],[2256,8]]},"96":{"position":[[1018,7]]},"97":{"position":[[2975,9]]},"104":{"position":[[235,10],[390,8]]},"113":{"position":[[874,9]]},"115":{"position":[[172,10]]},"116":{"position":[[272,10]]},"117":{"position":[[1064,10]]},"156":{"position":[[239,8]]},"165":{"position":[[742,8],[796,8]]},"185":{"position":[[278,7]]}},"keywords":{}}],["containwith",{"_index":5218,"title":{},"content":{"188":{"position":[[4118,11]]}},"keywords":{}}],["contemporari",{"_index":3857,"title":{},"content":{"120":{"position":[[689,12]]}},"keywords":{}}],["contend",{"_index":1822,"title":{},"content":{"40":{"position":[[2436,9]]}},"keywords":{}}],["content",{"_index":130,"title":{},"content":{"2":{"position":[[861,7]]},"22":{"position":[[1507,10],[1747,9],[1818,8]]},"49":{"position":[[648,8],[698,7]]},"95":{"position":[[158,7]]},"97":{"position":[[5020,7],[5142,7]]},"98":{"position":[[163,7]]},"109":{"position":[[214,7]]},"110":{"position":[[411,7]]},"111":{"position":[[281,7]]},"112":{"position":[[959,7]]},"113":{"position":[[917,7],[1453,7],[1977,7],[2473,7]]},"115":{"position":[[202,7],[2763,7]]},"116":{"position":[[302,7]]},"117":{"position":[[1094,7]]},"125":{"position":[[2013,7]]},"156":{"position":[[48,8]]},"159":{"position":[[920,8],[1016,8],[1096,8]]},"160":{"position":[[3730,7],[3971,8]]},"164":{"position":[[409,8]]},"192":{"position":[[104,9],[447,7]]}},"keywords":{}}],["context",{"_index":1399,"title":{},"content":{"30":{"position":[[4285,7]]},"51":{"position":[[3394,7]]},"53":{"position":[[744,7]]},"58":{"position":[[863,8]]},"66":{"position":[[120,8]]},"117":{"position":[[228,7]]},"173":{"position":[[1214,7],[1456,7],[1775,7]]},"175":{"position":[[961,8]]},"176":{"position":[[263,7]]},"190":{"position":[[168,7]]}},"keywords":{}}],["contigu",{"_index":5331,"title":{},"content":{"196":{"position":[[924,11]]}},"keywords":{}}],["continu",{"_index":72,"title":{"2":{"position":[[0,10]]}},"content":{"66":{"position":[[161,8]]},"75":{"position":[[764,8]]},"89":{"position":[[652,8],[734,8]]},"93":{"position":[[1107,8]]},"139":{"position":[[818,8]]},"143":{"position":[[186,8]]},"188":{"position":[[711,8]]}},"keywords":{}}],["contrari",{"_index":1173,"title":{},"content":{"26":{"position":[[531,8]]}},"keywords":{}}],["contrast",{"_index":4239,"title":{},"content":{"127":{"position":[[1001,9]]},"164":{"position":[[1138,9]]},"166":{"position":[[444,9]]},"175":{"position":[[234,9]]}},"keywords":{}}],["contribut",{"_index":3986,"title":{},"content":{"123":{"position":[[1012,12]]},"150":{"position":[[990,11]]},"161":{"position":[[149,12]]},"165":{"position":[[988,11]]}},"keywords":{}}],["contributor",{"_index":3974,"title":{},"content":{"123":{"position":[[293,11],[352,11],[592,11],[1029,12]]}},"keywords":{}}],["control",{"_index":2654,"title":{},"content":{"74":{"position":[[1464,7]]},"117":{"position":[[286,8]]},"125":{"position":[[4702,7],[7560,8]]},"128":{"position":[[700,7],[1458,7]]},"173":{"position":[[2130,10]]},"175":{"position":[[639,8],[663,7]]},"189":{"position":[[198,10]]},"198":{"position":[[576,8]]}},"keywords":{}}],["controversi",{"_index":3977,"title":{},"content":{"123":{"position":[[526,14]]}},"keywords":{}}],["conundrum",{"_index":4021,"title":{},"content":{"125":{"position":[[623,9]]}},"keywords":{}}],["conv_count",{"_index":2732,"title":{},"content":{"76":{"position":[[2267,12],[2407,10]]}},"keywords":{}}],["conv_count=10",{"_index":2719,"title":{},"content":{"76":{"position":[[1906,14]]}},"keywords":{}}],["convent",{"_index":5274,"title":{},"content":{"193":{"position":[[339,11],[356,10],[651,11]]}},"keywords":{}}],["converg",{"_index":2812,"title":{},"content":{"83":{"position":[[266,8]]},"86":{"position":[[503,9]]}},"keywords":{}}],["convert",{"_index":3115,"title":{},"content":{"91":{"position":[[2118,7]]},"103":{"position":[[198,7]]},"116":{"position":[[27,7]]}},"keywords":{}}],["convinc",{"_index":4180,"title":{},"content":{"125":{"position":[[9194,9]]}},"keywords":{}}],["cookbook",{"_index":3659,"title":{"107":{"position":[[10,9]]},"114":{"position":[[10,9]]}},"content":{},"keywords":{}}],["cool",{"_index":3363,"title":{"126":{"position":[[34,5]]}},"content":{"97":{"position":[[221,5]]},"98":{"position":[[1188,5]]},"106":{"position":[[995,4]]},"125":{"position":[[74,4],[11709,5]]},"129":{"position":[[597,4]]},"130":{"position":[[136,4],[397,4]]},"139":{"position":[[806,5]]}},"keywords":{}}],["coolest",{"_index":3357,"title":{},"content":{"97":{"position":[[15,7]]}},"keywords":{}}],["coordin",{"_index":1448,"title":{},"content":{"30":{"position":[[8415,10]]},"112":{"position":[[1716,12]]}},"keywords":{}}],["copi",{"_index":975,"title":{"181":{"position":[[0,8]]},"198":{"position":[[0,4]]}},"content":{"22":{"position":[[2675,4]]},"76":{"position":[[1380,5]]},"90":{"position":[[505,4]]},"97":{"position":[[5744,4],[5984,5]]},"128":{"position":[[550,4],[783,4],[950,7],[1313,7],[1543,7]]},"159":{"position":[[461,4],[886,4]]},"164":{"position":[[1297,4]]},"165":{"position":[[440,4]]},"178":{"position":[[426,4],[712,4]]},"181":{"position":[[52,4],[760,4]]},"183":{"position":[[141,6]]},"196":{"position":[[193,8]]},"198":{"position":[[34,4],[270,5],[358,4],[401,7],[428,7],[590,4],[624,4],[776,5],[824,5],[1056,6]]}},"keywords":{}}],["copy(retrieve_data(url",{"_index":984,"title":{},"content":{"22":{"position":[[2923,25]]}},"keywords":{}}],["copyif",{"_index":5362,"title":{},"content":{"198":{"position":[[730,6]]}},"keywords":{}}],["copyto",{"_index":5359,"title":{},"content":{"198":{"position":[[472,6]]}},"keywords":{}}],["core",{"_index":4942,"title":{},"content":{"173":{"position":[[390,5],[429,5],[527,5],[596,5],[773,5],[1757,4],[1899,4]]}},"keywords":{}}],["core::ptr::drop_in_plac",{"_index":4290,"title":{},"content":{"129":{"position":[[694,24]]}},"keywords":{}}],["core::ptr::real_drop_in_plac",{"_index":5351,"title":{},"content":{"197":{"position":[[1261,32]]}},"keywords":{}}],["corert",{"_index":4931,"title":{},"content":{"172":{"position":[[2174,7]]}},"keywords":{}}],["coreutil",{"_index":3996,"title":{},"content":{"124":{"position":[[274,9],[318,9]]}},"keywords":{}}],["corpor",{"_index":2289,"title":{},"content":{"54":{"position":[[74,9],[98,9]]}},"keywords":{}}],["correct",{"_index":482,"title":{},"content":{"10":{"position":[[78,7]]},"20":{"position":[[1162,7]]},"62":{"position":[[1308,7]]},"88":{"position":[[3796,9]]},"132":{"position":[[722,7],[742,7]]},"160":{"position":[[4283,9]]}},"keywords":{}}],["correctli",{"_index":485,"title":{},"content":{"10":{"position":[[114,10]]},"71":{"position":[[1174,10]]},"89":{"position":[[170,9]]},"112":{"position":[[27,9]]},"121":{"position":[[1770,10]]},"148":{"position":[[146,10]]},"167":{"position":[[309,10]]},"175":{"position":[[826,10]]},"197":{"position":[[1082,9]]}},"keywords":{}}],["correctth",{"_index":3164,"title":{},"content":{"91":{"position":[[4791,10]]}},"keywords":{}}],["correspond",{"_index":4596,"title":{},"content":{"156":{"position":[[580,13]]}},"keywords":{}}],["corrupt",{"_index":4677,"title":{},"content":{"160":{"position":[[1421,7]]},"195":{"position":[[923,10]]}},"keywords":{}}],["cost",{"_index":5037,"title":{},"content":{"175":{"position":[[1641,4]]},"178":{"position":[[300,4]]}},"keywords":{}}],["costs;electron",{"_index":4218,"title":{},"content":{"125":{"position":[[11571,14]]}},"keywords":{}}],["cough",{"_index":4155,"title":{},"content":{"125":{"position":[[8170,7]]}},"keywords":{}}],["couldn't",{"_index":183,"title":{},"content":{"3":{"position":[[974,8],[1351,8],[1505,8]]},"4":{"position":[[1369,8]]},"125":{"position":[[2580,8]]}},"keywords":{}}],["count",{"_index":1401,"title":{},"content":{"30":{"position":[[4365,5],[5828,5]]},"40":{"position":[[3554,5]]},"51":{"position":[[1538,5]]},"91":{"position":[[1556,5]]},"172":{"position":[[169,5]]},"193":{"position":[[2335,5]]},"196":{"position":[[1434,5],[1726,6]]}},"keywords":{}}],["count_dict",{"_index":1070,"title":{},"content":{"24":{"position":[[1635,10]]},"25":{"position":[[1334,10]]}},"keywords":{}}],["count_dict[index",{"_index":1083,"title":{},"content":{"24":{"position":[[2126,17]]},"25":{"position":[[1850,17]]}},"keywords":{}}],["counter",{"_index":930,"title":{},"content":{"22":{"position":[[1238,7]]},"172":{"position":[[1646,8]]}},"keywords":{}}],["counterpart",{"_index":4606,"title":{},"content":{"157":{"position":[[166,12]]},"159":{"position":[[1169,12]]}},"keywords":{}}],["countgo",{"_index":4573,"title":{},"content":{"155":{"position":[[1169,9]]}},"keywords":{}}],["coupl",{"_index":1565,"title":{},"content":{"33":{"position":[[61,6]]},"34":{"position":[[69,6]]},"46":{"position":[[18,6]]},"54":{"position":[[189,6]]},"55":{"position":[[38,6]]},"66":{"position":[[483,6]]},"72":{"position":[[424,6]]},"77":{"position":[[20,6]]},"89":{"position":[[515,6]]},"90":{"position":[[4003,6]]},"91":{"position":[[109,6]]},"97":{"position":[[888,6],[5178,6]]},"100":{"position":[[320,6]]},"102":{"position":[[1144,6]]},"105":{"position":[[2552,6]]},"112":{"position":[[1067,6]]},"121":{"position":[[584,6],[957,6]]},"125":{"position":[[123,6],[4737,6],[10828,6]]},"179":{"position":[[92,6]]}},"keywords":{}}],["coupledifferentthread",{"_index":3950,"title":{},"content":{"122":{"position":[[944,22]]}},"keywords":{}}],["coupon",{"_index":546,"title":{},"content":{"13":{"position":[[230,6],[305,6],[378,6],[578,6],[687,7],[1234,7]]},"14":{"position":[[134,6],[152,7],[414,6],[649,6],[815,6],[878,6],[936,7],[989,6],[1150,6],[1408,6],[1544,7],[1688,6],[1850,6],[2295,7]]},"15":{"position":[[152,7],[259,6],[329,6],[388,7],[446,7],[508,7],[777,6],[915,7],[1078,6],[1356,6],[1965,7]]}},"keywords":{}}],["coupon*i",{"_index":570,"title":{},"content":{"13":{"position":[[831,9]]}},"keywords":{}}],["coupon_barri",{"_index":643,"title":{},"content":{"14":{"position":[[1354,14],[1508,15],[1773,14],[2259,15]]},"15":{"position":[[723,14],[879,15],[1166,14],[1929,15]]}},"keywords":{}}],["cours",{"_index":1673,"title":{},"content":{"35":{"position":[[384,6]]},"71":{"position":[[1456,6]]},"86":{"position":[[456,6]]},"97":{"position":[[5316,8]]},"124":{"position":[[74,6]]},"125":{"position":[[639,6],[2263,6]]}},"keywords":{}}],["cover",{"_index":1218,"title":{},"content":{"28":{"position":[[676,5],[2183,5],[2712,5],[2828,5],[4167,6],[4371,6]]},"29":{"position":[[104,5]]},"30":{"position":[[838,5],[1002,5],[1176,5],[2092,7],[2335,5],[2403,5],[2578,5],[2913,6],[3270,6],[3289,5],[3777,5],[4054,5],[4452,6],[5791,5]]},"97":{"position":[[833,5],[1240,5]]},"118":{"position":[[205,8]]},"155":{"position":[[685,7]]}},"keywords":{}}],["cover".format(month",{"_index":1271,"title":{},"content":{"28":{"position":[[2115,26]]}},"keywords":{}}],["cow::from("drop"",{"_index":4589,"title":{},"content":{"155":{"position":[[1574,28]]}},"keywords":{}}],["cpu",{"_index":4943,"title":{},"content":{"173":{"position":[[425,3],[523,3],[687,3],[1136,3],[1687,3],[1724,3],[1895,3],[2191,4]]},"174":{"position":[[1,3],[189,3],[317,3]]},"176":{"position":[[998,3]]},"180":{"position":[[287,3]]},"188":{"position":[[1574,3],[1672,3],[2241,3],[2558,3],[3096,3]]},"189":{"position":[[1762,3],[2217,3],[2500,3],[2789,3]]},"193":{"position":[[3157,3]]}},"keywords":{}}],["cpu/mmu",{"_index":4984,"title":{},"content":{"174":{"position":[[501,7]]}},"keywords":{}}],["cpython",{"_index":5148,"title":{},"content":{"188":{"position":[[131,7],[560,7]]},"189":{"position":[[546,7]]}},"keywords":{}}],["cra",{"_index":30,"title":{},"content":{"1":{"position":[[330,5]]},"3":{"position":[[353,3],[492,3],[901,3]]}},"keywords":{}}],["crack",{"_index":3317,"title":{},"content":{"96":{"position":[[142,8]]}},"keywords":{}}],["craco",{"_index":151,"title":{},"content":{"3":{"position":[[384,6]]}},"keywords":{}}],["cramer",{"_index":872,"title":{"21":{"position":[[8,6]]}},"content":{"24":{"position":[[3384,6]]},"26":{"position":[[422,6],[543,6]]}},"keywords":{}}],["crash",{"_index":5200,"title":{},"content":{"188":{"position":[[3449,5]]},"195":{"position":[[169,6],[794,7]]}},"keywords":{}}],["crate",{"_index":3701,"title":{},"content":{"111":{"position":[[310,5]]},"113":{"position":[[341,5]]},"132":{"position":[[43,6]]},"155":{"position":[[534,5]]},"157":{"position":[[197,7],[433,6]]},"159":{"position":[[1191,6]]},"160":{"position":[[1675,5],[2543,6]]},"181":{"position":[[850,8]]}},"keywords":{}}],["crazi",{"_index":2141,"title":{},"content":{"51":{"position":[[3102,5]]},"128":{"position":[[1005,6]]}},"keywords":{}}],["creat",{"_index":27,"title":{},"content":{"1":{"position":[[313,6]]},"45":{"position":[[1856,6]]},"62":{"position":[[278,6]]},"90":{"position":[[838,6],[2223,6]]},"91":{"position":[[1790,7],[2714,7]]},"92":{"position":[[526,7]]},"97":{"position":[[927,6],[1272,8],[5377,7]]},"109":{"position":[[57,6]]},"110":{"position":[[205,6],[332,7]]},"113":{"position":[[360,6],[820,8],[1337,6]]},"125":{"position":[[1456,6],[7773,6]]},"127":{"position":[[1373,7]]},"136":{"position":[[579,6]]},"155":{"position":[[928,8]]},"156":{"position":[[459,8]]},"165":{"position":[[714,6]]},"178":{"position":[[308,8]]},"180":{"position":[[560,7]]},"188":{"position":[[2027,6]]},"192":{"position":[[37,8],[414,8]]},"196":{"position":[[140,7]]}},"keywords":{}}],["creation",{"_index":2260,"title":{},"content":{"53":{"position":[[1254,9]]}},"keywords":{}}],["creepi",{"_index":2540,"title":{},"content":{"66":{"position":[[24,6]]}},"keywords":{}}],["cring",{"_index":4015,"title":{},"content":{"125":{"position":[[442,6]]}},"keywords":{}}],["critic",{"_index":2650,"title":{},"content":{"74":{"position":[[1265,10]]},"112":{"position":[[280,10]]},"148":{"position":[[107,8]]},"161":{"position":[[543,10]]},"172":{"position":[[2653,8]]},"173":{"position":[[542,8],[731,8]]}},"keywords":{}}],["crook",{"_index":2831,"title":{},"content":{"86":{"position":[[722,7]]}},"keywords":{}}],["cross",{"_index":671,"title":{},"content":{"15":{"position":[[247,7]]}},"keywords":{}}],["crucial",{"_index":3481,"title":{},"content":{"101":{"position":[[635,7]]},"172":{"position":[[984,8]]},"176":{"position":[[504,7]]}},"keywords":{}}],["crude",{"_index":1094,"title":{},"content":{"24":{"position":[[2522,5],[2674,5]]},"25":{"position":[[2245,5],[2397,5]]}},"keywords":{}}],["crunch",{"_index":2078,"title":{},"content":{"51":{"position":[[339,10]]}},"keywords":{}}],["crusad",{"_index":3796,"title":{},"content":{"115":{"position":[[3161,7]]}},"keywords":{}}],["crust",{"_index":4757,"title":{},"content":{"161":{"position":[[1522,5]]}},"keywords":{}}],["crystal",{"_index":1560,"title":{},"content":{"32":{"position":[[2273,7]]}},"keywords":{}}],["csv",{"_index":2376,"title":{},"content":{"61":{"position":[[1624,3]]}},"keywords":{}}],["culinari",{"_index":3843,"title":{},"content":{"118":{"position":[[168,8]]}},"keywords":{}}],["cur_d1",{"_index":2723,"title":{},"content":{"76":{"position":[[2003,6],[2081,7],[2193,6],[2880,6],[3189,6],[3342,7]]}},"keywords":{}}],["cur_d2",{"_index":2725,"title":{},"content":{"76":{"position":[[2030,6],[2089,7],[2209,6],[2627,7],[2896,6],[3205,6],[3350,6]]}},"keywords":{}}],["cur_scor",{"_index":2726,"title":{},"content":{"76":{"position":[[2057,9],[2174,9],[2582,11],[2776,10],[2858,9],[3051,10],[3167,9]]}},"keywords":{}}],["curios",{"_index":3648,"title":{"132":{"position":[[0,10]]}},"content":{"105":{"position":[[3018,10]]}},"keywords":{}}],["curiou",{"_index":1337,"title":{},"content":{"30":{"position":[[510,8]]},"43":{"position":[[410,8]]},"176":{"position":[[449,7]]}},"keywords":{}}],["current",{"_index":336,"title":{},"content":{"6":{"position":[[505,7]]},"13":{"position":[[352,7]]},"14":{"position":[[630,7]]},"25":{"position":[[19,9]]},"38":{"position":[[889,9]]},"51":{"position":[[815,7],[1000,9]]},"52":{"position":[[926,7],[1041,7],[1100,7]]},"57":{"position":[[549,9]]},"75":{"position":[[451,7],[497,7],[705,8]]},"76":{"position":[[2524,7],[2959,7]]},"78":{"position":[[898,7]]},"82":{"position":[[273,7],[343,7],[413,7],[483,7],[553,7],[623,7],[693,7],[763,7],[833,7],[904,7]]},"88":{"position":[[613,9]]},"93":{"position":[[4028,9]]},"97":{"position":[[4558,7],[4621,7]]},"113":{"position":[[1927,9]]},"117":{"position":[[220,7]]},"124":{"position":[[499,9]]},"125":{"position":[[7911,9]]},"160":{"position":[[3789,9],[4472,9]]},"161":{"position":[[1339,9]]},"175":{"position":[[254,9]]},"184":{"position":[[785,9]]},"189":{"position":[[2928,9]]},"194":{"position":[[618,9]]},"195":{"position":[[710,7]]}},"keywords":{}}],["current[0",{"_index":2191,"title":{},"content":{"52":{"position":[[1000,10],[1022,10]]}},"keywords":{}}],["current_clos",{"_index":1605,"title":{},"content":{"34":{"position":[[1089,14],[1227,13]]},"39":{"position":[[809,14],[862,13],[939,13]]}},"keywords":{}}],["current_open",{"_index":1614,"title":{},"content":{"34":{"position":[[1243,12]]},"39":{"position":[[878,12]]}},"keywords":{}}],["current_pric",{"_index":1727,"title":{},"content":{"39":{"position":[[724,13]]}},"keywords":{}}],["current_price*shar",{"_index":1621,"title":{},"content":{"34":{"position":[[1534,20]]}},"keywords":{}}],["curri",{"_index":3371,"title":{},"content":{"97":{"position":[[1350,9],[2657,7]]}},"keywords":{}}],["curs",{"_index":1958,"title":{},"content":{"45":{"position":[[67,6],[75,6]]}},"keywords":{}}],["custom",{"_index":152,"title":{"42":{"position":[[21,8]]}},"content":{"3":{"position":[[391,9]]},"43":{"position":[[746,10],[773,10],[894,8],[1347,8],[1395,8]]},"44":{"position":[[1171,10],[1318,10],[1378,10],[1405,10],[1578,10],[1608,10]]},"46":{"position":[[190,8],[533,9]]},"125":{"position":[[4878,6],[4898,6]]},"132":{"position":[[602,6]]},"137":{"position":[[39,6]]}},"keywords":{}}],["custombusinessday",{"_index":2966,"title":{},"content":{"90":{"position":[[310,17],[3405,17]]}},"keywords":{}}],["custombusinessday(day",{"_index":2976,"title":{},"content":{"90":{"position":[[690,23]]}},"keywords":{}}],["cut",{"_index":3543,"title":{},"content":{"103":{"position":[[1924,3]]},"188":{"position":[[2759,3]]}},"keywords":{}}],["cvx",{"_index":711,"title":{},"content":{"17":{"position":[[162,6]]},"18":{"position":[[239,6]]},"19":{"position":[[466,6]]},"20":{"position":[[386,6],[2857,7]]}},"keywords":{}}],["cycl",{"_index":247,"title":{},"content":{"4":{"position":[[621,7]]},"161":{"position":[[804,5]]}},"keywords":{}}],["cyclic",{"_index":1813,"title":{},"content":{"40":{"position":[[1628,10]]}},"keywords":{}}],["cyclic_df",{"_index":1814,"title":{},"content":{"40":{"position":[[1640,9]]}},"keywords":{}}],["cyclic_df.xs('day",{"_index":1817,"title":{},"content":{"40":{"position":[[1765,20]]}},"keywords":{}}],["cyclic_df.xs('scor",{"_index":1818,"title":{},"content":{"40":{"position":[[1935,21]]}},"keywords":{}}],["cython",{"_index":5145,"title":{"188":{"position":[[0,7]]}},"content":{"188":{"position":[[13,6],[387,6],[595,6],[827,8],[1493,6],[3515,8],[4152,6]]},"189":{"position":[[6,7],[60,6],[962,7],[1910,6],[2581,7],[2873,7]]},"190":{"position":[[345,6],[537,6],[894,6]]}},"keywords":{}}],["cython'",{"_index":5221,"title":{},"content":{"188":{"position":[[4264,8],[4377,8]]}},"keywords":{}}],["cython/numba",{"_index":5262,"title":{},"content":{"190":{"position":[[504,12]]}},"keywords":{}}],["cython_gil(n",{"_index":5171,"title":{},"content":{"188":{"position":[[1557,14]]}},"keywords":{}}],["cython_gil(unsign",{"_index":5168,"title":{},"content":{"188":{"position":[[1289,19]]}},"keywords":{}}],["cython_nogil(n",{"_index":5177,"title":{},"content":{"188":{"position":[[1653,16]]}},"keywords":{}}],["cython_nogil(unsign",{"_index":5165,"title":{},"content":{"188":{"position":[[1153,21]]}},"keywords":{}}],["cython_recurse(2",{"_index":5204,"title":{},"content":{"188":{"position":[[3626,17]]}},"keywords":{}}],["cython_recurse(int",{"_index":5202,"title":{},"content":{"188":{"position":[[3533,18]]}},"keywords":{}}],["cython_recurse(n",{"_index":5203,"title":{},"content":{"188":{"position":[[3604,16]]}},"keywords":{}}],["c⋅ic",{"_index":549,"title":{},"content":{"13":{"position":[[320,4]]}},"keywords":{}}],["d",{"_index":787,"title":{},"content":{"20":{"position":[[714,3]]},"39":{"position":[[580,2],[2480,3],[2582,1]]},"62":{"position":[[566,3],[825,1],[1112,2]]},"88":{"position":[[762,3],[1279,4]]},"90":{"position":[[774,1],[2159,1]]},"93":{"position":[[2902,2],[4177,3]]},"121":{"position":[[354,2]]}},"keywords":{}}],["d(0,t",{"_index":465,"title":{},"content":{"9":{"position":[[433,5]]}},"keywords":{}}],["d(0,t)=d(0,t−1)⋅fi−1,id(0",{"_index":464,"title":{},"content":{"9":{"position":[[401,26]]}},"keywords":{}}],["d.isoformat",{"_index":3243,"title":{},"content":{"93":{"position":[[2905,14]]}},"keywords":{}}],["d1",{"_index":2597,"title":{},"content":{"70":{"position":[[1027,2]]},"71":{"position":[[1210,2],[1255,2]]}},"keywords":{}}],["d1={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3d2={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3e[d1]=3.5e[d2]=3.5e[d1+d2]=7=e[dfair+dfair]\\begin{align",{"_index":2607,"title":{},"content":{"71":{"position":[[187,169]]}},"keywords":{}}],["d1={1w.p.1/32w.p.1/33w.p.1/124w.p.1/125w.p.1/126w.p.1/12d2={1w.p.1/122w.p.1/123w.p.1/124w.p.1/125w.p.1/36w.p.1/3e[d1]=2.5e[d2]=4.5e[d1+d2]=7=e[dfair+dfair]\\begin{align",{"_index":2578,"title":{},"content":{"70":{"position":[[87,169]]}},"keywords":{}}],["d1_densiti",{"_index":2687,"title":{},"content":{"76":{"position":[[477,11]]}},"keywords":{}}],["d1_index1",{"_index":2701,"title":{},"content":{"76":{"position":[[1260,10]]}},"keywords":{}}],["d1_index2",{"_index":2702,"title":{},"content":{"76":{"position":[[1271,9]]}},"keywords":{}}],["d1_p",{"_index":2680,"title":{},"content":{"76":{"position":[[342,4],[432,5]]}},"keywords":{}}],["d1_val",{"_index":2750,"title":{},"content":{"78":{"position":[[159,7]]}},"keywords":{}}],["d2",{"_index":2598,"title":{},"content":{"70":{"position":[[1067,2]]},"71":{"position":[[1250,2]]}},"keywords":{}}],["d2_densiti",{"_index":2677,"title":{},"content":{"76":{"position":[[204,12],[489,12],[746,11],[989,12]]}},"keywords":{}}],["d2_dist",{"_index":2748,"title":{},"content":{"78":{"position":[[140,8],[512,9]]}},"keywords":{}}],["d2_index1",{"_index":2704,"title":{},"content":{"76":{"position":[[1310,10]]}},"keywords":{}}],["d2_index2",{"_index":2705,"title":{},"content":{"76":{"position":[[1321,9]]}},"keywords":{}}],["d2_p",{"_index":2682,"title":{},"content":{"76":{"position":[[383,4]]}},"keywords":{}}],["d2_p).coef",{"_index":2685,"title":{},"content":{"76":{"position":[[440,10]]}},"keywords":{}}],["d2_val",{"_index":2752,"title":{},"content":{"78":{"position":[[192,7],[309,8],[598,8]]}},"keywords":{}}],["d_1",{"_index":2580,"title":{},"content":{"70":{"position":[[275,3]]},"71":{"position":[[375,3]]}},"keywords":{}}],["d_2",{"_index":2586,"title":{},"content":{"70":{"position":[[449,3],[701,4],[1237,5]]},"71":{"position":[[549,3],[801,4],[1384,5]]}},"keywords":{}}],["d_col",{"_index":719,"title":{},"content":{"17":{"position":[[236,5]]}},"keywords":{}}],["d_i(1",{"_index":1550,"title":{},"content":{"32":{"position":[[1803,5],[1883,5]]}},"keywords":{}}],["d_icn​∑i=1n​oi​di​​>∑i=1n​di",{"_index":1533,"title":{},"content":{"32":{"position":[[874,32]]}},"keywords":{}}],["d_n",{"_index":1545,"title":{},"content":{"32":{"position":[[1662,5],[1689,3],[1748,3],[1830,3]]}},"keywords":{}}],["d_{fair",{"_index":2591,"title":{},"content":{"70":{"position":[[734,9]]},"71":{"position":[[834,9]]}},"keywords":{}}],["daili",{"_index":760,"title":{},"content":{"20":{"position":[[40,5]]},"24":{"position":[[180,5]]}},"keywords":{}}],["daily_invest",{"_index":1603,"title":{},"content":{"34":{"position":[[1047,16]]}},"keywords":{}}],["daily_investment(current_open",{"_index":1728,"title":{},"content":{"39":{"position":[[778,30]]}},"keywords":{}}],["daily_investment(open_vals[day",{"_index":1734,"title":{},"content":{"39":{"position":[[1329,32]]}},"keywords":{}}],["daily_investment(open_vals[day+1",{"_index":1637,"title":{},"content":{"34":{"position":[[2116,34]]}},"keywords":{}}],["damn",{"_index":5036,"title":{},"content":{"175":{"position":[[1606,7]]}},"keywords":{}}],["dashboard_article_link",{"_index":895,"title":{},"content":{"22":{"position":[[474,25]]}},"keywords":{}}],["data",{"_index":721,"title":{"22":{"position":[[20,4]]},"23":{"position":[[21,5]]},"43":{"position":[[0,4]]},"50":{"position":[[4,5]]},"59":{"position":[[12,5]]},"62":{"position":[[15,5]]},"63":{"position":[[31,5]]}},"content":{"17":{"position":[[252,4]]},"22":{"position":[[118,4],[1252,4],[2746,4]]},"23":{"position":[[30,5],[177,4]]},"24":{"position":[[550,4],[748,4],[2891,4],[3290,4],[3414,4]]},"25":{"position":[[275,4],[464,4],[2643,4],[2737,4]]},"26":{"position":[[5,4],[73,4],[222,4],[402,5],[452,4]]},"28":{"position":[[599,5],[1618,4],[2376,4],[2396,4],[2761,4],[2834,4],[3404,4],[4006,4],[4067,5]]},"29":{"position":[[282,4],[401,4]]},"30":{"position":[[768,4],[890,4],[2507,4],[2636,4],[2729,4],[4491,4],[7435,4],[8227,4],[8289,4],[8426,4],[9612,4],[9711,4],[10153,4],[10210,4],[10264,4],[10314,4]]},"34":{"position":[[3031,4]]},"39":{"position":[[315,4],[2334,4]]},"40":{"position":[[30,5]]},"41":{"position":[[261,4]]},"43":{"position":[[31,4],[103,4],[1001,4],[1209,4],[1259,4]]},"44":{"position":[[32,4],[198,5],[491,4],[1839,4],[1945,4]]},"45":{"position":[[323,4],[2783,4],[3543,4]]},"46":{"position":[[127,5],[377,4]]},"47":{"position":[[41,5],[102,4],[201,5]]},"51":{"position":[[94,5],[321,5],[2742,4]]},"53":{"position":[[107,5]]},"57":{"position":[[262,4],[294,4],[604,4]]},"58":{"position":[[40,5],[133,5],[744,5],[924,4]]},"59":{"position":[[63,4],[230,5]]},"61":{"position":[[147,4],[314,5],[337,4],[601,5],[728,5],[781,5],[839,4],[897,5],[972,4],[1098,4],[1144,4]]},"62":{"position":[[104,5],[124,4],[246,4],[357,5],[1288,5],[1730,4]]},"63":{"position":[[29,4],[83,4]]},"65":{"position":[[333,4],[1653,4]]},"66":{"position":[[259,4]]},"69":{"position":[[230,6]]},"74":{"position":[[1017,4]]},"75":{"position":[[341,5]]},"82":{"position":[[50,4],[64,4],[1221,5],[1243,4]]},"83":{"position":[[406,5]]},"88":{"position":[[2468,6]]},"89":{"position":[[964,5]]},"90":{"position":[[4124,4]]},"91":{"position":[[2139,4],[2813,4],[3287,4],[3941,4]]},"92":{"position":[[625,4],[1099,4]]},"93":{"position":[[623,5],[1000,5],[1036,4],[1206,4],[1736,6],[1797,5],[2066,5],[2135,5],[3759,4]]},"95":{"position":[[78,4]]},"97":{"position":[[1409,4],[3459,5]]},"100":{"position":[[41,4],[462,5]]},"101":{"position":[[174,4],[242,4]]},"102":{"position":[[268,4],[894,5],[915,5],[1372,4]]},"104":{"position":[[806,5]]},"106":{"position":[[694,5],[893,4]]},"110":{"position":[[52,4]]},"113":{"position":[[1661,4],[1773,4],[2146,4]]},"117":{"position":[[188,5],[246,5],[1641,5]]},"155":{"position":[[80,4],[146,4],[464,4],[941,4],[1008,4]]},"163":{"position":[[39,4],[82,4],[403,5],[1606,4],[2214,5],[2428,4]]},"166":{"position":[[399,5],[515,4]]},"167":{"position":[[165,4],[234,5],[304,4]]},"172":{"position":[[1311,4],[1333,4]]},"175":{"position":[[194,4],[487,4],[520,4],[1290,4],[1349,5],[1393,4],[1541,4]]},"190":{"position":[[210,4]]}},"keywords":{}}],["data.id",{"_index":2044,"title":{},"content":{"47":{"position":[[147,7]]}},"keywords":{}}],["data.index",{"_index":2043,"title":{},"content":{"47":{"position":[[134,10]]},"88":{"position":[[1150,11]]}},"keywords":{}}],["data.loc[d",{"_index":2866,"title":{},"content":{"88":{"position":[[1119,18]]}},"keywords":{}}],["data.loc[end]['high",{"_index":2910,"title":{},"content":{"88":{"position":[[2543,23]]}},"keywords":{}}],["data.loc[end]['low",{"_index":2912,"title":{},"content":{"88":{"position":[[2645,22]]}},"keywords":{}}],["data.loc[start]['high",{"_index":2909,"title":{},"content":{"88":{"position":[[2517,25]]}},"keywords":{}}],["data.loc[start]['low",{"_index":2911,"title":{},"content":{"88":{"position":[[2620,24]]}},"keywords":{}}],["data['close']/2",{"_index":3133,"title":{},"content":{"91":{"position":[[2892,15]]},"92":{"position":[[704,15]]}},"keywords":{}}],["data['open']/2",{"_index":3132,"title":{},"content":{"91":{"position":[[2875,14]]},"92":{"position":[[687,14]]}},"keywords":{}}],["data[d",{"_index":1037,"title":{},"content":{"24":{"position":[[689,10]]},"25":{"position":[[410,10]]}},"keywords":{}}],["data[tick][d_col].pct_chang",{"_index":727,"title":{},"content":{"18":{"position":[[94,30]]}},"keywords":{}}],["data_str",{"_index":3106,"title":{},"content":{"91":{"position":[[1923,8]]},"93":{"position":[[4336,8]]}},"keywords":{}}],["data_str.split('\\n",{"_index":3112,"title":{},"content":{"91":{"position":[[2047,21]]},"93":{"position":[[4460,21]]}},"keywords":{}}],["data_train",{"_index":2045,"title":{},"content":{"47":{"position":[[155,11]]}},"keywords":{}}],["data_train.to_csv('split_train.csv",{"_index":2048,"title":{},"content":{"47":{"position":[[222,36]]}},"keywords":{}}],["data_valid",{"_index":2046,"title":{},"content":{"47":{"position":[[167,13]]}},"keywords":{}}],["data_validate.to_csv('split_validate.csv",{"_index":2049,"title":{},"content":{"47":{"position":[[259,42]]}},"keywords":{}}],["databas",{"_index":4420,"title":{},"content":{"139":{"position":[[487,8]]}},"keywords":{}}],["datafram",{"_index":432,"title":{},"content":{"7":{"position":[[1137,10]]}},"keywords":{}}],["dataset",{"_index":1866,"title":{},"content":{"43":{"position":[[472,7]]},"44":{"position":[[97,7],[351,7]]},"45":{"position":[[402,8]]},"46":{"position":[[41,8]]},"50":{"position":[[109,8]]},"83":{"position":[[471,8],[542,8]]},"88":{"position":[[668,7]]},"93":{"position":[[4083,7]]},"102":{"position":[[487,7]]},"104":{"position":[[158,7],[1115,8]]}},"keywords":{}}],["dataset.drop(['target",{"_index":1870,"title":{},"content":{"43":{"position":[[544,23]]}},"keywords":{}}],["dataset.id",{"_index":1869,"title":{},"content":{"43":{"position":[[529,10]]}},"keywords":{}}],["dataset.index",{"_index":1868,"title":{},"content":{"43":{"position":[[513,13]]}},"keywords":{}}],["dataset.target",{"_index":1872,"title":{},"content":{"43":{"position":[[590,14]]}},"keywords":{}}],["datastream",{"_index":3655,"title":{},"content":{"106":{"position":[[597,11]]}},"keywords":{}}],["date",{"_index":941,"title":{},"content":{"22":{"position":[[1532,4],[1587,4]]},"23":{"position":[[246,5]]},"24":{"position":[[591,4],[1032,5],[2074,9]]},"25":{"position":[[316,4],[752,5],[1798,9]]},"28":{"position":[[1243,5],[1453,7],[3043,5],[3249,7]]},"30":{"position":[[1609,5],[1814,7],[2958,5],[3163,7],[4882,5],[5083,7],[6026,5],[6232,7],[8855,4]]},"62":{"position":[[287,4]]},"66":{"position":[[31,4],[671,4]]},"88":{"position":[[1142,4]]},"90":{"position":[[3518,4]]},"91":{"position":[[2168,5],[2916,5]]},"92":{"position":[[728,5]]},"93":{"position":[[1534,5],[1907,4],[2757,5],[2872,6]]},"120":{"position":[[109,6]]},"122":{"position":[[1467,4]]},"124":{"position":[[209,4],[238,4]]}},"keywords":{}}],["date(2015",{"_index":1658,"title":{},"content":{"34":{"position":[[3344,10],[3735,10]]}},"keywords":{}}],["date/tim",{"_index":3851,"title":{},"content":{"120":{"position":[[416,9]]},"122":{"position":[[1166,9]]}},"keywords":{}}],["date2num",{"_index":2844,"title":{},"content":{"88":{"position":[[343,8]]}},"keywords":{}}],["date2num(d",{"_index":2865,"title":{},"content":{"88":{"position":[[1101,17]]}},"keywords":{}}],["date2num(end",{"_index":2908,"title":{},"content":{"88":{"position":[[2501,15],[2604,15]]}},"keywords":{}}],["date=non",{"_index":1467,"title":{},"content":{"30":{"position":[[8778,11]]}},"keywords":{}}],["date_list",{"_index":3120,"title":{},"content":{"91":{"position":[[2305,9],[2356,10]]}},"keywords":{}}],["date_str",{"_index":940,"title":{},"content":{"22":{"position":[[1463,11]]},"62":{"position":[[909,8]]}},"keywords":{}}],["dateformatt",{"_index":2847,"title":{},"content":{"88":{"position":[[429,14]]}},"keywords":{}}],["dateformatter('%b",{"_index":2871,"title":{},"content":{"88":{"position":[[1261,17]]}},"keywords":{}}],["datepublish",{"_index":939,"title":{},"content":{"22":{"position":[[1436,16]]}},"keywords":{}}],["dates_fil",{"_index":3257,"title":{},"content":{"93":{"position":[[3295,10]]}},"keywords":{}}],["dates_file.write(yaml.dump({r3000_equities.ix[i]['tick",{"_index":3271,"title":{},"content":{"93":{"position":[[3654,59]]}},"keywords":{}}],["datetim",{"_index":707,"title":{},"content":{"17":{"position":[[108,8],[124,9]]},"30":{"position":[[241,8],[257,8],[8388,8],[8404,8],[9094,10]]},"39":{"position":[[3072,8],[3088,8]]},"43":{"position":[[424,8],[440,8]]},"62":{"position":[[433,8],[449,8]]},"65":{"position":[[2292,8]]},"88":{"position":[[499,8],[515,8]]},"90":{"position":[[333,8],[349,9]]},"93":{"position":[[1305,8],[1321,9],[3902,8]]},"122":{"position":[[275,8]]}},"keywords":{}}],["datetime(2015",{"_index":1774,"title":{},"content":{"39":{"position":[[3141,14]]}},"keywords":{}}],["datetime(2016",{"_index":1777,"title":{},"content":{"39":{"position":[[3202,14]]},"62":{"position":[[583,14],[615,14]]},"88":{"position":[[1440,14],[1462,14],[1769,14],[1791,14],[2831,14],[2853,14],[2901,14],[2924,14],[3228,14],[3251,14],[3295,14],[3318,14]]},"90":{"position":[[4041,15]]}},"keywords":{}}],["datetime(2070",{"_index":2529,"title":{},"content":{"65":{"position":[[2325,14]]}},"keywords":{}}],["datetime(row_dt.year",{"_index":1062,"title":{},"content":{"24":{"position":[[1259,21]]},"25":{"position":[[979,21]]}},"keywords":{}}],["datetime.datetime(2070",{"_index":2533,"title":{},"content":{"65":{"position":[[2447,23]]}},"keywords":{}}],["datetime.now",{"_index":1865,"title":{},"content":{"43":{"position":[[457,14]]},"46":{"position":[[594,14]]},"93":{"position":[[2856,15]]}},"keywords":{}}],["datetime.now().strftime("%i:%m:%",{"_index":1488,"title":{},"content":{"30":{"position":[[9757,38]]}},"keywords":{}}],["datetime.strptime(date_str",{"_index":2423,"title":{},"content":{"62":{"position":[[1067,26]]}},"keywords":{}}],["datetimemodul",{"_index":3850,"title":{},"content":{"120":{"position":[[255,15]]}},"keywords":{}}],["dateutil",{"_index":3200,"title":{"119":{"position":[[23,8]]}},"content":{"93":{"position":[[1372,8]]},"120":{"position":[[67,8]]},"121":{"position":[[978,8],[2491,8]]},"122":{"position":[[301,9],[414,8]]},"124":{"position":[[24,8]]}},"keywords":{}}],["dateutil.pars",{"_index":3104,"title":{},"content":{"91":{"position":[[1858,15]]},"93":{"position":[[3868,15]]},"120":{"position":[[271,15],[785,15]]}},"keywords":{}}],["day",{"_index":766,"title":{"46":{"position":[[12,3]]},"91":{"position":[[44,5]]},"92":{"position":[[32,5]]}},"content":{"20":{"position":[[218,3]]},"24":{"position":[[292,4]]},"26":{"position":[[380,3]]},"30":{"position":[[477,3],[598,4],[1065,4],[1131,3],[1153,3],[2617,5],[2826,4],[3579,6],[4003,4],[4257,4],[4314,4],[4574,4],[4631,4],[4682,4],[5851,5],[5936,3],[6652,6],[6857,4],[7083,4],[7157,4],[7691,5]]},"32":{"position":[[270,3],[520,3],[570,3],[646,3],[1221,3],[1324,3],[2128,4]]},"33":{"position":[[534,3],[609,3],[880,3],[1106,3]]},"34":{"position":[[453,4],[1866,3],[2341,3],[3157,4],[3203,3],[3447,4],[3568,4],[3838,4],[3965,4]]},"38":{"position":[[133,4],[387,3],[541,4],[845,4],[936,3],[985,4],[1062,4],[1112,4]]},"39":{"position":[[1081,3],[1561,3]]},"40":{"position":[[351,4],[681,4],[1885,4],[2208,4],[2828,4],[3527,4],[3565,3]]},"53":{"position":[[993,4],[1037,3]]},"61":{"position":[[1708,3]]},"62":{"position":[[255,3]]},"64":{"position":[[143,3],[465,5],[755,5]]},"65":{"position":[[374,4],[620,4],[1425,3],[1642,3]]},"89":{"position":[[600,4]]},"90":{"position":[[611,3],[662,3],[684,5],[3269,3],[4273,4],[4509,5],[4616,5],[4794,4],[4850,5],[4940,5],[5102,3],[5279,3]]},"91":{"position":[[119,4],[353,5],[1460,4],[1541,4],[1571,5],[2522,4],[2611,3],[2671,4],[3004,5],[4232,5],[4342,3],[4550,5],[5000,4],[5011,5],[5065,4],[5147,3],[5374,4],[5524,3],[5730,3],[5908,3],[5971,3]]},"92":{"position":[[164,5],[334,4],[423,3],[483,4],[816,5],[1605,4]]},"93":{"position":[[1936,3]]},"95":{"position":[[499,4]]},"96":{"position":[[567,4]]},"98":{"position":[[19,5]]},"101":{"position":[[127,5]]},"122":{"position":[[1234,4]]},"150":{"position":[[95,4]]},"167":{"position":[[223,3]]}},"keywords":{}}],["day"",{"_index":1415,"title":{},"content":{"30":{"position":[[5919,9]]}},"keywords":{}}],["day'",{"_index":3075,"title":{},"content":{"91":{"position":[[292,5]]}},"keywords":{}}],["day.th",{"_index":3065,"title":{},"content":{"90":{"position":[[5003,7]]}},"keywords":{}}],["dayloc",{"_index":2849,"title":{},"content":{"88":{"position":[[461,11],[1232,12]]}},"keywords":{}}],["daynnn",{"_index":2464,"title":{},"content":{"64":{"position":[[692,7]]},"65":{"position":[[569,7]]}},"keywords":{}}],["dd_a",{"_index":815,"title":{},"content":{"20":{"position":[[1284,4],[1764,5],[2621,5]]}},"keywords":{}}],["de",{"_index":3954,"title":{},"content":{"122":{"position":[[1157,2]]}},"keywords":{}}],["de/seri",{"_index":4850,"title":{},"content":{"166":{"position":[[884,17]]},"170":{"position":[[369,16]]}},"keywords":{}}],["dead",{"_index":3951,"title":{},"content":{"122":{"position":[[1011,4],[1278,4]]}},"keywords":{}}],["deal",{"_index":4194,"title":{},"content":{"125":{"position":[[10155,4]]},"128":{"position":[[1743,7]]},"142":{"position":[[169,7]]},"160":{"position":[[677,4]]}},"keywords":{}}],["dealloc",{"_index":4522,"title":{},"content":{"152":{"position":[[1027,13]]},"155":{"position":[[1098,10]]},"156":{"position":[[1125,13]]}},"keywords":{}}],["dealloc(&self",{"_index":4535,"title":{},"content":{"152":{"position":[[1488,18]]},"156":{"position":[[1571,18]]}},"keywords":{}}],["deallocation."",{"_index":4536,"title":{},"content":{"152":{"position":[[1600,21]]},"156":{"position":[[1683,21]]}},"keywords":{}}],["debug",{"_index":3885,"title":{},"content":{"121":{"position":[[767,9]]}},"keywords":{}}],["debug_assert",{"_index":4412,"title":{"138":{"position":[[9,13]]}},"content":{"143":{"position":[[362,14]]}},"keywords":{}}],["decent",{"_index":1841,"title":{},"content":{"40":{"position":[[3623,6]]}},"keywords":{}}],["decid",{"_index":2517,"title":{},"content":{"65":{"position":[[1453,7]]},"97":{"position":[[2246,7]]},"194":{"position":[[114,7]]}},"keywords":{}}],["decidedli",{"_index":4490,"title":{},"content":{"150":{"position":[[142,9]]}},"keywords":{}}],["decim",{"_index":3938,"title":{},"content":{"122":{"position":[[323,7],[428,9],[562,7]]}},"keywords":{}}],["decis",{"_index":2028,"title":{},"content":{"45":{"position":[[3577,10]]},"53":{"position":[[768,8]]},"122":{"position":[[814,9]]},"125":{"position":[[4036,8]]},"170":{"position":[[70,9]]}},"keywords":{}}],["declar",{"_index":2815,"title":{},"content":{"83":{"position":[[559,7]]},"155":{"position":[[128,9]]},"178":{"position":[[125,7]]},"179":{"position":[[294,8]]},"180":{"position":[[137,8]]},"182":{"position":[[98,7]]},"184":{"position":[[258,8]]},"186":{"position":[[375,8]]},"195":{"position":[[89,9]]},"196":{"position":[[516,8]]},"197":{"position":[[645,8]]}},"keywords":{}}],["declin",{"_index":1291,"title":{},"content":{"28":{"position":[[2718,7]]}},"keywords":{}}],["decod",{"_index":4815,"title":{},"content":{"164":{"position":[[1254,8]]}},"keywords":{}}],["decompress",{"_index":3484,"title":{},"content":{"101":{"position":[[719,12]]}},"keywords":{}}],["decor",{"_index":5228,"title":{},"content":{"189":{"position":[[229,10],[250,9],[489,10],[634,9]]},"190":{"position":[[407,9]]}},"keywords":{}}],["decreas",{"_index":2699,"title":{},"content":{"76":{"position":[[1116,8]]},"90":{"position":[[4961,10]]}},"keywords":{}}],["deep",{"_index":1186,"title":{},"content":{"26":{"position":[[860,4]]},"125":{"position":[[4787,4]]}},"keywords":{}}],["deepli",{"_index":268,"title":{},"content":{"4":{"position":[[907,6]]}},"keywords":{}}],["deepthought",{"_index":2271,"title":{},"content":{"53":{"position":[[1435,13]]}},"keywords":{}}],["def",{"_index":820,"title":{},"content":{"20":{"position":[[1510,3],[1820,3]]},"22":{"position":[[296,3],[1277,3],[1363,3],[1625,3],[1725,3],[2269,3],[2324,3]]},"24":{"position":[[423,3],[931,3]]},"25":{"position":[[148,3],[651,3]]},"28":{"position":[[1090,3],[1196,3],[1786,3],[2879,3],[3000,3],[3534,3]]},"30":{"position":[[1462,3],[1568,3],[2920,3],[4724,3],[4845,3],[5989,3],[8750,3]]},"39":{"position":[[602,3],[774,3],[990,3],[2142,3],[3036,3]]},"45":{"position":[[2012,3],[2794,3]]},"51":{"position":[[3606,3],[3755,3],[3828,3],[3928,3],[4078,3]]},"52":{"position":[[707,3]]},"62":{"position":[[834,3]]},"70":{"position":[[934,3]]},"76":{"position":[[175,3],[464,3],[965,3],[1887,3]]},"78":{"position":[[111,3]]},"88":{"position":[[563,3],[921,3],[2438,3]]},"90":{"position":[[739,3],[2118,3],[3175,3]]},"91":{"position":[[2413,3],[3315,3]]},"92":{"position":[[228,3]]},"93":{"position":[[1545,3],[1632,3],[1714,3],[2183,3],[2257,3],[3978,3]]},"96":{"position":[[460,3]]},"103":{"position":[[873,3]]},"105":{"position":[[493,3],[975,3],[1332,3]]},"129":{"position":[[1939,3]]},"188":{"position":[[1149,3],[1285,3]]},"189":{"position":[[1077,3],[1349,3],[3069,3]]}},"keywords":{}}],["default",{"_index":4383,"title":{},"content":{"135":{"position":[[652,7]]},"172":{"position":[[457,7],[1301,8]]},"189":{"position":[[884,9],[1320,8]]}},"keywords":{}}],["default,heaptrack",{"_index":4363,"title":{},"content":{"133":{"position":[[77,17]]}},"keywords":{}}],["defeat",{"_index":4105,"title":{},"content":{"125":{"position":[[5025,6]]}},"keywords":{}}],["defin",{"_index":344,"title":{"7":{"position":[[0,8]]},"127":{"position":[[0,8]]}},"content":{"6":{"position":[[612,6]]},"13":{"position":[[16,7]]},"22":{"position":[[16,6]]},"30":{"position":[[1138,7],[5898,6]]},"34":{"position":[[19,7],[713,7]]},"35":{"position":[[7,7]]},"76":{"position":[[13,8]]},"90":{"position":[[4875,7]]},"91":{"position":[[1587,6]]},"97":{"position":[[3427,6]]},"103":{"position":[[717,6]]},"112":{"position":[[1505,7],[1597,7]]},"113":{"position":[[384,6]]},"117":{"position":[[134,6],[2082,6]]},"127":{"position":[[978,6]]},"139":{"position":[[374,6]]},"155":{"position":[[609,7]]},"160":{"position":[[846,8],[4513,7]]},"188":{"position":[[742,6]]}},"keywords":{}}],["definit",{"_index":1520,"title":{},"content":{"32":{"position":[[461,12],[666,11]]},"97":{"position":[[4314,10]]},"105":{"position":[[3300,10]]},"185":{"position":[[214,11],[616,11]]}},"keywords":{}}],["defrost",{"_index":4740,"title":{},"content":{"161":{"position":[[796,7]]}},"keywords":{}}],["degre",{"_index":4668,"title":{},"content":{"160":{"position":[[935,6]]},"161":{"position":[[1356,8]]}},"keywords":{}}],["deliv",{"_index":3438,"title":{},"content":{"98":{"position":[[182,7]]},"125":{"position":[[4608,10]]},"175":{"position":[[816,9]]}},"keywords":{}}],["deliveri",{"_index":5014,"title":{},"content":{"175":{"position":[[624,9]]}},"keywords":{}}],["demonstr",{"_index":2897,"title":{},"content":{"88":{"position":[[2046,11]]},"130":{"position":[[36,13]]},"179":{"position":[[175,11]]},"185":{"position":[[502,11]]},"188":{"position":[[787,12]]}},"keywords":{}}],["deno",{"_index":205,"title":{},"content":{"3":{"position":[[1317,4]]}},"keywords":{}}],["denot",{"_index":3811,"title":{},"content":{"116":{"position":[[2541,7]]}},"keywords":{}}],["densiti",{"_index":2675,"title":{},"content":{"76":{"position":[[86,9],[885,10],[1033,10]]}},"keywords":{}}],["density_coef(d1_dens",{"_index":2676,"title":{},"content":{"76":{"position":[[179,24],[721,24]]}},"keywords":{}}],["density_coef(d1_dist",{"_index":2764,"title":{},"content":{"78":{"position":[[490,21]]}},"keywords":{}}],["density_coef(max_d1",{"_index":2771,"title":{},"content":{"78":{"position":[[689,20]]}},"keywords":{}}],["departmentofredundancydepart",{"_index":2278,"title":{},"content":{"53":{"position":[[1536,33]]}},"keywords":{}}],["depend",{"_index":269,"title":{},"content":{"4":{"position":[[914,9]]},"109":{"position":[[384,13],[427,14]]},"124":{"position":[[445,13]]},"125":{"position":[[4757,9],[8095,10],[9324,6]]},"142":{"position":[[58,9]]},"173":{"position":[[1530,9]]},"190":{"position":[[624,13]]}},"keywords":{}}],["depress",{"_index":1208,"title":{},"content":{"28":{"position":[[300,10],[846,10]]},"29":{"position":[[225,10]]},"30":{"position":[[4712,11]]},"66":{"position":[[870,10]]}},"keywords":{}}],["depth",{"_index":1849,"title":{},"content":{"41":{"position":[[74,5]]},"163":{"position":[[61,5]]}},"keywords":{}}],["derail",{"_index":235,"title":{},"content":{"4":{"position":[[281,6]]}},"keywords":{}}],["derefer",{"_index":4238,"title":{},"content":{"127":{"position":[[926,11],[1189,11],[1456,11]]},"128":{"position":[[1792,11],[1868,12]]}},"keywords":{}}],["dereferenc",{"_index":4234,"title":{},"content":{"127":{"position":[[764,12],[1067,13]]}},"keywords":{}}],["deriv",{"_index":2631,"title":{"74":{"position":[[0,8]]}},"content":{"74":{"position":[[4,6]]},"115":{"position":[[2775,8]]}},"keywords":{}}],["derive(clon",{"_index":5364,"title":{},"content":{"198":{"position":[[973,16]]}},"keywords":{}}],["derive(copi",{"_index":5368,"title":{},"content":{"198":{"position":[[1100,14]]}},"keywords":{}}],["derive(debug",{"_index":5120,"title":{},"content":{"184":{"position":[[131,16],[490,16]]}},"keywords":{}}],["derive(default",{"_index":4546,"title":{},"content":{"153":{"position":[[508,18],[564,18],[623,18],[683,18]]},"195":{"position":[[190,18],[261,18],[337,18],[575,18]]}},"keywords":{}}],["describ",{"_index":4562,"title":{},"content":{"155":{"position":[[400,8]]}},"keywords":{}}],["deseri",{"_index":3756,"title":{"169":{"position":[[0,16]]}},"content":{"113":{"position":[[1757,11],[1782,12],[1909,14]]},"115":{"position":[[237,12]]},"116":{"position":[[337,12]]},"117":{"position":[[1126,12]]},"164":{"position":[[1302,15]]}},"keywords":{}}],["deserialized.get_root::<point_capnp::point::reader>().unwrap",{"_index":3762,"title":{},"content":{"113":{"position":[[2192,69]]},"115":{"position":[[380,69]]},"116":{"position":[[480,69]]}},"keywords":{}}],["deserv",{"_index":2840,"title":{},"content":{"88":{"position":[[207,8]]}},"keywords":{}}],["design",{"_index":1600,"title":{},"content":{"34":{"position":[[901,8]]},"38":{"position":[[23,8]]},"100":{"position":[[146,6],[417,9]]},"102":{"position":[[869,8]]},"155":{"position":[[297,6]]},"172":{"position":[[600,8],[1382,6]]},"176":{"position":[[139,9],[1145,8]]},"199":{"position":[[617,7]]}},"keywords":{}}],["desir",{"_index":2547,"title":{},"content":{"66":{"position":[[548,6]]},"168":{"position":[[100,7]]}},"keywords":{}}],["desktop",{"_index":4002,"title":{"125":{"position":[[11,7]]}},"content":{"125":{"position":[[223,7]]}},"keywords":{}}],["despis",{"_index":4003,"title":{},"content":{"125":{"position":[[7,7]]}},"keywords":{}}],["despit",{"_index":4727,"title":{},"content":{"161":{"position":[[224,7]]}},"keywords":{}}],["destin",{"_index":5035,"title":{},"content":{"175":{"position":[[1577,11]]}},"keywords":{}}],["detail",{"_index":2643,"title":{},"content":{"74":{"position":[[912,8]]},"125":{"position":[[4185,6]]},"127":{"position":[[1604,7]]},"129":{"position":[[1186,7]]},"130":{"position":[[96,7]]},"159":{"position":[[35,6]]},"174":{"position":[[525,8]]},"176":{"position":[[119,7],[569,7]]},"188":{"position":[[4319,6]]},"196":{"position":[[1384,7]]},"198":{"position":[[97,6]]}},"keywords":{}}],["detect",{"_index":174,"title":{"68":{"position":[[15,6]]},"72":{"position":[[0,9]]}},"content":{"3":{"position":[[810,7]]},"68":{"position":[[300,6]]},"69":{"position":[[201,10]]},"71":{"position":[[75,6]]},"72":{"position":[[62,7]]},"190":{"position":[[787,8]]}},"keywords":{}}],["determin",{"_index":1013,"title":{},"content":{"24":{"position":[[40,10],[3312,11]]},"73":{"position":[[71,9]]},"75":{"position":[[836,9]]},"83":{"position":[[95,9]]},"102":{"position":[[1205,10]]},"128":{"position":[[812,10]]},"155":{"position":[[1074,10]]},"193":{"position":[[320,10]]}},"keywords":{}}],["dev",{"_index":3058,"title":{},"content":{"90":{"position":[[4499,4]]}},"keywords":{}}],["develop",{"_index":260,"title":{},"content":{"4":{"position":[[779,10]]},"40":{"position":[[1502,9]]},"46":{"position":[[417,7]]},"51":{"position":[[3575,10]]},"66":{"position":[[318,10]]},"72":{"position":[[453,10]]},"105":{"position":[[197,7]]},"160":{"position":[[2325,10],[2429,10]]}},"keywords":{}}],["deviat",{"_index":742,"title":{},"content":{"19":{"position":[[155,9]]},"72":{"position":[[126,8]]},"90":{"position":[[5052,9]]},"91":{"position":[[4852,9],[5850,9]]},"92":{"position":[[1520,9]]}},"keywords":{}}],["devic",{"_index":4681,"title":{},"content":{"160":{"position":[[1780,8],[2658,7],[2821,8]]},"173":{"position":[[1641,7]]},"175":{"position":[[1239,7]]}},"keywords":{}}],["df",{"_index":2418,"title":{},"content":{"62":{"position":[[962,2],[1134,2]]}},"keywords":{}}],["df.index",{"_index":2421,"title":{},"content":{"62":{"position":[[1028,8]]}},"keywords":{}}],["df['time'].appli",{"_index":2422,"title":{},"content":{"62":{"position":[[1039,17]]}},"keywords":{}}],["dialog",{"_index":2353,"title":{},"content":{"61":{"position":[[206,6]]}},"keywords":{}}],["dice",{"_index":2571,"title":{},"content":{"68":{"position":[[880,4]]},"69":{"position":[[54,4],[344,4],[402,5]]},"72":{"position":[[121,4],[183,5],[329,4],[380,5],[529,4]]},"73":{"position":[[97,4],[819,4]]},"74":{"position":[[372,4]]},"75":{"position":[[258,5]]},"76":{"position":[[1998,4]]},"77":{"position":[[101,5],[161,5]]},"78":{"position":[[25,4]]},"79":{"position":[[21,4]]},"82":{"position":[[147,4]]},"83":{"position":[[129,4]]}},"keywords":{}}],["dict(urllib.parse.parse_qsl(response_url))['access_token",{"_index":2392,"title":{},"content":{"61":{"position":[[2317,58]]}},"keywords":{}}],["dictionari",{"_index":3922,"title":{},"content":{"121":{"position":[[2433,10]]}},"keywords":{}}],["didn't",{"_index":136,"title":{},"content":{"3":{"position":[[45,6],[252,6]]},"40":{"position":[[716,6]]},"76":{"position":[[2943,6]]},"97":{"position":[[3083,6],[5808,6]]},"125":{"position":[[7251,6],[9813,6],[10472,6]]},"143":{"position":[[336,6]]},"158":{"position":[[96,6]]},"163":{"position":[[2460,6]]},"165":{"position":[[56,6]]}},"keywords":{}}],["die",{"_index":2559,"title":{},"content":{"68":{"position":[[348,3],[396,4]]},"70":{"position":[[23,3],[50,3]]},"71":{"position":[[10,3],[107,3],[1093,3],[1121,4]]},"74":{"position":[[318,3],[1547,4]]},"75":{"position":[[1290,4]]},"76":{"position":[[82,3],[1076,3]]},"80":{"position":[[29,3],[65,3]]}},"keywords":{}}],["differ",{"_index":142,"title":{},"content":{"3":{"position":[[182,9],[343,9]]},"9":{"position":[[168,10]]},"15":{"position":[[1261,10]]},"22":{"position":[[2794,9]]},"23":{"position":[[68,9]]},"30":{"position":[[7297,10]]},"38":{"position":[[271,9]]},"39":{"position":[[257,10]]},"43":{"position":[[1132,9]]},"45":{"position":[[1034,9]]},"51":{"position":[[2583,9],[3211,9]]},"53":{"position":[[34,10]]},"68":{"position":[[352,7]]},"72":{"position":[[569,9]]},"74":{"position":[[392,9]]},"85":{"position":[[348,9]]},"86":{"position":[[310,9],[339,9],[1187,9]]},"89":{"position":[[525,9],[757,10]]},"101":{"position":[[969,11],[1095,10]]},"102":{"position":[[843,10],[1151,9]]},"125":{"position":[[7816,9]]},"127":{"position":[[1553,12]]},"135":{"position":[[510,9]]},"153":{"position":[[53,9]]},"161":{"position":[[648,11]]},"163":{"position":[[679,9]]},"165":{"position":[[227,10]]},"169":{"position":[[209,11]]},"172":{"position":[[426,9],[729,9]]},"181":{"position":[[840,9]]},"182":{"position":[[70,9]]},"183":{"position":[[20,10],[267,10]]},"188":{"position":[[2894,11]]},"193":{"position":[[3084,9]]},"196":{"position":[[701,9],[1700,10]]},"199":{"position":[[58,10]]}},"keywords":{}}],["difficult",{"_index":1049,"title":{},"content":{"24":{"position":[[989,9]]},"25":{"position":[[709,9]]},"74":{"position":[[168,9]]},"97":{"position":[[812,9]]},"104":{"position":[[1308,9]]},"106":{"position":[[334,9]]},"120":{"position":[[541,9]]},"139":{"position":[[145,9],[847,9]]},"142":{"position":[[217,9]]}},"keywords":{}}],["difficulti",{"_index":383,"title":{},"content":{"7":{"position":[[129,11]]},"68":{"position":[[186,11]]}},"keywords":{}}],["dig",{"_index":2322,"title":{},"content":{"58":{"position":[[114,7]]},"122":{"position":[[930,3]]},"127":{"position":[[1581,3]]}},"keywords":{}}],["digit",{"_index":3459,"title":{},"content":{"100":{"position":[[235,7]]}},"keywords":{}}],["digress",{"_index":4223,"title":{},"content":{"127":{"position":[[128,8]]}},"keywords":{}}],["dim",{"_index":2005,"title":{},"content":{"45":{"position":[[2243,3],[3023,3]]}},"keywords":{}}],["dim_rang",{"_index":2001,"title":{},"content":{"45":{"position":[[2171,9],[2250,11],[2951,9],[3030,11]]}},"keywords":{}}],["dimens",{"_index":1893,"title":{},"content":{"43":{"position":[[1465,10]]},"45":{"position":[[751,10],[1616,11],[1688,10]]},"103":{"position":[[1179,10]]}},"keywords":{}}],["dimension",{"_index":56,"title":{"44":{"position":[[0,14]]},"45":{"position":[[0,14]]}},"content":{"1":{"position":[[630,11]]},"44":{"position":[[37,14]]},"45":{"position":[[328,14],[697,14],[892,14],[1056,14],[1143,14],[1579,14],[3511,12]]},"46":{"position":[[115,11]]},"73":{"position":[[675,11]]},"85":{"position":[[425,11]]},"102":{"position":[[146,14],[1112,14]]}},"keywords":{}}],["dir",{"_index":4116,"title":{},"content":{"125":{"position":[[5333,3],[5881,3]]}},"keywords":{}}],["dir(8",{"_index":4310,"title":{},"content":{"129":{"position":[[2125,6]]}},"keywords":{}}],["direct",{"_index":1132,"title":{},"content":{"24":{"position":[[3331,9]]},"26":{"position":[[362,9]]}},"keywords":{}}],["directli",{"_index":4172,"title":{},"content":{"125":{"position":[[8760,9]]},"152":{"position":[[640,8]]},"189":{"position":[[150,8]]},"190":{"position":[[928,8]]}},"keywords":{}}],["directori",{"_index":3694,"title":{},"content":{"110":{"position":[[224,9],[322,9]]},"112":{"position":[[510,10],[915,9]]},"134":{"position":[[250,9]]}},"keywords":{}}],["dirti",{"_index":3836,"title":{},"content":{"117":{"position":[[1919,5]]}},"keywords":{}}],["dirtier",{"_index":3313,"title":{},"content":{"95":{"position":[[545,7]]}},"keywords":{}}],["disabl",{"_index":4544,"title":{},"content":{"153":{"position":[[364,7]]},"173":{"position":[[854,7]]}},"keywords":{}}],["disagr",{"_index":4149,"title":{},"content":{"125":{"position":[[7582,12]]}},"keywords":{}}],["disappear",{"_index":4401,"title":{"152":{"position":[[16,12]]}},"content":{"136":{"position":[[912,10]]}},"keywords":{}}],["discard",{"_index":3151,"title":{},"content":{"91":{"position":[[4041,9]]},"199":{"position":[[703,7]]}},"keywords":{}}],["disclaim",{"_index":1677,"title":{"36":{"position":[[14,11]]}},"content":{},"keywords":{}}],["discourag",{"_index":1949,"title":{},"content":{"44":{"position":[[1681,13]]}},"keywords":{}}],["discov",{"_index":1963,"title":{},"content":{"45":{"position":[[247,10]]},"125":{"position":[[1972,9]]}},"keywords":{}}],["discret",{"_index":2572,"title":{},"content":{"68":{"position":[[890,8]]}},"keywords":{}}],["discuss",{"_index":1251,"title":{},"content":{"28":{"position":[[1606,7],[3392,7]]},"73":{"position":[[312,7]]},"125":{"position":[[1876,8],[2689,10],[3645,8]]},"198":{"position":[[347,10]]}},"keywords":{}}],["discussedissu",{"_index":3968,"title":{},"content":{"123":{"position":[[56,15]]}},"keywords":{}}],["disect",{"_index":2951,"title":{},"content":{"89":{"position":[[503,6]]}},"keywords":{}}],["dish",{"_index":4749,"title":{},"content":{"161":{"position":[[1125,4],[1327,4]]}},"keywords":{}}],["dispatch",{"_index":4601,"title":{},"content":{"156":{"position":[[809,11]]},"197":{"position":[[48,8],[100,8],[151,8],[233,8],[682,8],[1496,8]]}},"keywords":{}}],["display",{"_index":406,"title":{},"content":{"7":{"position":[[592,7]]},"17":{"position":[[81,7]]},"121":{"position":[[1930,8]]}},"keywords":{}}],["display("expect",{"_index":855,"title":{},"content":{"20":{"position":[[2510,22],[2655,22]]}},"keywords":{}}],["display("hold",{"_index":848,"title":{},"content":{"20":{"position":[[2342,23]]}},"keywords":{}}],["display(drawdown",{"_index":769,"title":{},"content":{"20":{"position":[[334,18]]}},"keywords":{}}],["display(optimal.messag",{"_index":847,"title":{},"content":{"20":{"position":[[2317,24]]}},"keywords":{}}],["display(sharp",{"_index":754,"title":{},"content":{"19":{"position":[[416,16]]}},"keywords":{}}],["display({tick",{"_index":728,"title":{},"content":{"18":{"position":[[146,14]]}},"keywords":{}}],["display_motion(full_mot",{"_index":523,"title":{},"content":{"11":{"position":[[549,27]]}},"keywords":{}}],["display_motion(mot",{"_index":403,"title":{},"content":{"7":{"position":[[539,22]]},"8":{"position":[[211,22]]}},"keywords":{}}],["dist",{"_index":2164,"title":{},"content":{"51":{"position":[[4117,4],[4216,5]]}},"keywords":{}}],["dist/app.j",{"_index":4170,"title":{},"content":{"125":{"position":[[8681,13]]}},"keywords":{}}],["dist/app_loader.j",{"_index":4171,"title":{},"content":{"125":{"position":[[8697,20],[9148,20]]}},"keywords":{}}],["dist/electron_yew_wasm.j",{"_index":4169,"title":{},"content":{"125":{"position":[[8651,27]]}},"keywords":{}}],["dist/electron_yew_wasm_bg.wasm",{"_index":4166,"title":{},"content":{"125":{"position":[[8480,32],[8616,32]]}},"keywords":{}}],["dist/stdweb_electron.j",{"_index":4179,"title":{},"content":{"125":{"position":[[9120,25]]}},"keywords":{}}],["dist/stdweb_electron_bg.wasm",{"_index":4177,"title":{},"content":{"125":{"position":[[8950,30],[9087,30]]}},"keywords":{}}],["distanc",{"_index":5301,"title":{},"content":{"193":{"position":[[2269,10]]}},"keywords":{}}],["distance(&middl",{"_index":5297,"title":{},"content":{"193":{"position":[[1928,21],[2883,21]]}},"keywords":{}}],["distance(&start",{"_index":5294,"title":{},"content":{"193":{"position":[[1879,20],[2834,20]]}},"keywords":{}}],["distance(a",{"_index":5279,"title":{},"content":{"193":{"position":[[1055,11],[2459,11]]}},"keywords":{}}],["distance_borrowed(a",{"_index":5307,"title":{},"content":{"193":{"position":[[3535,20]]}},"keywords":{}}],["distance_moved(a",{"_index":5306,"title":{},"content":{"193":{"position":[[3234,17]]}},"keywords":{}}],["distil",{"_index":4646,"title":{},"content":{"160":{"position":[[22,10]]}},"keywords":{}}],["distinct",{"_index":3771,"title":{},"content":{"115":{"position":[[904,8]]},"160":{"position":[[1596,12]]},"182":{"position":[[255,11]]}},"keywords":{}}],["distribut",{"_index":1821,"title":{},"content":{"40":{"position":[[2192,12],[3702,12]]},"44":{"position":[[1289,12]]},"49":{"position":[[68,12],[199,12],[418,12],[449,12]]},"51":{"position":[[384,12],[740,14],[1610,13],[1878,13],[3182,13],[3526,13]]},"68":{"position":[[249,12],[323,12],[369,12],[643,15],[668,12],[920,13],[983,13]]},"69":{"position":[[63,12]]},"70":{"position":[[1339,12]]},"71":{"position":[[172,13],[1139,12]]},"72":{"position":[[545,12],[653,12]]},"73":{"position":[[798,12],[865,13]]},"74":{"position":[[322,14],[485,13],[1514,13]]},"75":{"position":[[238,12],[311,12],[1269,12]]},"76":{"position":[[3154,12]]},"77":{"position":[[219,12]]},"78":{"position":[[84,13],[547,14],[637,14],[749,14]]},"82":{"position":[[1187,12],[1275,12]]},"83":{"position":[[109,12],[365,12]]},"125":{"position":[[1403,13]]},"176":{"position":[[369,14]]},"190":{"position":[[461,12],[642,12],[721,11]]}},"keywords":{}}],["distribution?distribut",{"_index":2062,"title":{},"content":{"49":{"position":[[562,25]]}},"keywords":{}}],["ditch",{"_index":2022,"title":{},"content":{"45":{"position":[[2752,5]]}},"keywords":{}}],["div",{"_index":890,"title":{},"content":{"22":{"position":[[346,5]]}},"keywords":{}}],["dive",{"_index":1187,"title":{},"content":{"26":{"position":[[865,4]]}},"keywords":{}}],["divest",{"_index":3189,"title":{},"content":{"93":{"position":[[327,9]]}},"keywords":{}}],["divid",{"_index":1610,"title":{},"content":{"34":{"position":[[1175,6]]},"106":{"position":[[746,7]]}},"keywords":{}}],["dividend",{"_index":379,"title":{},"content":{"7":{"position":[[96,8]]},"9":{"position":[[230,8]]}},"keywords":{}}],["divis",{"_index":825,"title":{},"content":{"20":{"position":[[1645,8],[1665,8]]},"103":{"position":[[971,9]]},"193":{"position":[[957,8]]}},"keywords":{}}],["djia",{"_index":1007,"title":{},"content":{"23":{"position":[[431,4]]},"24":{"position":[[2501,4],[2653,4]]},"25":{"position":[[2224,4],[2376,4]]}},"keywords":{}}],["djia_close_ret",{"_index":1142,"title":{},"content":{"25":{"position":[[512,14],[1435,15]]}},"keywords":{}}],["djia_open_ret",{"_index":1040,"title":{},"content":{"24":{"position":[[795,13],[1714,14]]}},"keywords":{}}],["dnd_ndn",{"_index":1557,"title":{},"content":{"32":{"position":[[2114,8]]},"34":{"position":[[262,11],[3175,8]]}},"keywords":{}}],["do",{"_index":508,"title":{},"content":{"11":{"position":[[67,5]]},"28":{"position":[[121,5]]},"29":{"position":[[45,5]]},"30":{"position":[[9156,5]]},"51":{"position":[[36,5],[1010,5]]},"52":{"position":[[97,5]]},"55":{"position":[[77,5]]},"71":{"position":[[1163,5]]},"103":{"position":[[1964,5]]},"104":{"position":[[948,5],[1948,5]]},"112":{"position":[[201,5]]},"115":{"position":[[3053,5]]},"118":{"position":[[88,5]]},"125":{"position":[[56,5],[11743,5]]},"135":{"position":[[666,6]]},"137":{"position":[[155,6]]},"139":{"position":[[730,5]]},"148":{"position":[[194,5]]},"158":{"position":[[328,5]]},"161":{"position":[[1470,5]]},"172":{"position":[[660,5]]}},"keywords":{}}],["do_cal",{"_index":5350,"title":{},"content":{"197":{"position":[[1154,9]]}},"keywords":{}}],["do_pan",{"_index":4526,"title":{},"content":{"152":{"position":[[1198,9]]},"156":{"position":[[1281,9]]}},"keywords":{}}],["do_panic.load(ordering::seqcst",{"_index":4531,"title":{},"content":{"152":{"position":[[1375,31],[1542,31]]},"156":{"position":[[1458,31],[1625,31]]}},"keywords":{}}],["do_panic.store(fals",{"_index":4523,"title":{},"content":{"152":{"position":[[1063,21]]},"156":{"position":[[1168,21]]}},"keywords":{}}],["do_panic.store(tru",{"_index":4514,"title":{},"content":{"152":{"position":[[535,20]]},"156":{"position":[[976,20]]}},"keywords":{}}],["doc",{"_index":4571,"title":{},"content":{"155":{"position":[[875,4]]},"160":{"position":[[4207,5],[4422,4],[4542,4]]}},"keywords":{}}],["docsgo",{"_index":5355,"title":{},"content":{"198":{"position":[[85,6]]}},"keywords":{}}],["document",{"_index":40,"title":{},"content":{"1":{"position":[[454,13]]},"54":{"position":[[84,9]]},"96":{"position":[[962,13]]},"97":{"position":[[311,13],[561,14],[3041,13],[3205,13]]},"116":{"position":[[2494,13]]},"159":{"position":[[96,8]]},"166":{"position":[[734,10]]},"188":{"position":[[4273,13]]}},"keywords":{}}],["does_trend_down",{"_index":3158,"title":{},"content":{"91":{"position":[[4367,16],[5177,16],[5560,16]]}},"keywords":{}}],["does_trend_down(tick",{"_index":3125,"title":{},"content":{"91":{"position":[[2417,23]]}},"keywords":{}}],["does_trend_up",{"_index":3179,"title":{},"content":{"92":{"position":[[1142,14],[1700,14],[1859,14]]}},"keywords":{}}],["does_trend_up(tick",{"_index":3178,"title":{},"content":{"92":{"position":[[232,21]]}},"keywords":{}}],["doesn't",{"_index":1376,"title":{},"content":{"30":{"position":[[2595,7],[2734,7],[7760,7]]},"34":{"position":[[572,7]]},"39":{"position":[[344,7]]},"40":{"position":[[2238,7]]},"45":{"position":[[1329,7]]},"76":{"position":[[1561,7]]},"82":{"position":[[1248,7]]},"91":{"position":[[3139,7],[3157,7],[3245,7],[3976,7],[4598,7],[5447,7]]},"92":{"position":[[951,7],[969,7],[1057,7]]},"96":{"position":[[798,7]]},"108":{"position":[[640,7]]},"113":{"position":[[2057,7]]},"115":{"position":[[629,7],[866,7]]},"116":{"position":[[884,7],[3040,7]]},"120":{"position":[[1083,7]]},"124":{"position":[[413,7]]},"125":{"position":[[2162,7],[9316,7],[10024,8]]},"145":{"position":[[302,7]]},"146":{"position":[[445,7]]},"147":{"position":[[334,7]]},"152":{"position":[[840,7]]},"153":{"position":[[113,7]]},"166":{"position":[[850,7]]},"173":{"position":[[2217,7]]},"188":{"position":[[2703,7],[3429,7]]},"199":{"position":[[946,7],[1319,7]]}},"keywords":{}}],["doing"",{"_index":4358,"title":{},"content":{"132":{"position":[[938,11]]}},"keywords":{}}],["dollar",{"_index":498,"title":{},"content":{"10":{"position":[[379,6]]},"34":{"position":[[3092,7],[3189,7]]},"127":{"position":[[406,6]]}},"keywords":{}}],["dom",{"_index":46,"title":{},"content":{"1":{"position":[[533,3]]}},"keywords":{}}],["domain",{"_index":1317,"title":{},"content":{"29":{"position":[[419,6]]}},"keywords":{}}],["don't",{"_index":798,"title":{},"content":{"20":{"position":[[963,5]]},"22":{"position":[[2851,5]]},"30":{"position":[[9245,5]]},"34":{"position":[[464,5]]},"38":{"position":[[667,5],[1150,5]]},"40":{"position":[[3058,5]]},"50":{"position":[[40,5]]},"51":{"position":[[177,5]]},"53":{"position":[[869,5]]},"61":{"position":[[85,6]]},"64":{"position":[[1515,5]]},"73":{"position":[[413,5]]},"74":{"position":[[1458,5]]},"85":{"position":[[512,5]]},"90":{"position":[[444,5],[463,5]]},"91":{"position":[[1550,5],[3750,5],[3899,5]]},"96":{"position":[[2019,5]]},"97":{"position":[[104,5],[3002,5],[3139,5],[4325,5]]},"98":{"position":[[682,5]]},"101":{"position":[[187,5]]},"106":{"position":[[194,5],[865,5],[1082,5]]},"108":{"position":[[155,5]]},"112":{"position":[[165,5]]},"115":{"position":[[2791,5]]},"121":{"position":[[745,5],[834,5]]},"123":{"position":[[782,5]]},"125":{"position":[[361,5],[1088,5],[1164,5],[1226,5],[7512,5],[10618,5]]},"127":{"position":[[369,5]]},"129":{"position":[[224,5]]},"137":{"position":[[17,5]]},"143":{"position":[[156,5],[268,5]]},"155":{"position":[[830,5]]},"158":{"position":[[125,5]]},"159":{"position":[[1203,5]]},"161":{"position":[[1073,5]]},"163":{"position":[[599,5]]},"166":{"position":[[674,5]]},"172":{"position":[[1043,5],[2414,5]]},"181":{"position":[[900,5]]},"189":{"position":[[1532,5]]},"194":{"position":[[191,5]]},"196":{"position":[[503,5],[828,5]]}},"keywords":{}}],["done",{"_index":484,"title":{},"content":{"10":{"position":[[104,4]]},"35":{"position":[[214,4]]},"43":{"position":[[207,4]]},"51":{"position":[[959,4],[1488,5]]},"53":{"position":[[835,5]]},"64":{"position":[[385,5]]},"89":{"position":[[333,4]]},"93":{"position":[[1071,5]]},"95":{"position":[[225,4],[321,4]]},"97":{"position":[[2427,5]]},"108":{"position":[[801,4]]},"111":{"position":[[151,4]]},"112":{"position":[[11,4]]},"124":{"position":[[58,5],[628,4]]},"125":{"position":[[6089,4],[6982,4]]},"183":{"position":[[820,5]]},"197":{"position":[[1585,5]]}},"keywords":{}}],["door",{"_index":4495,"title":{},"content":{"150":{"position":[[458,4]]}},"keywords":{}}],["dope",{"_index":3849,"title":{},"content":{"120":{"position":[[173,5]]}},"keywords":{}}],["doubl",{"_index":674,"title":{},"content":{"15":{"position":[[501,6]]},"127":{"position":[[241,6]]},"188":{"position":[[1932,6]]}},"keywords":{}}],["dough",{"_index":4737,"title":{},"content":{"161":{"position":[[603,5],[706,5],[767,5],[907,6],[1028,5]]}},"keywords":{}}],["dow",{"_index":993,"title":{},"content":{"23":{"position":[[111,3]]},"24":{"position":[[2544,3],[2716,3],[2938,3],[3029,3],[3446,3]]},"25":{"position":[[2267,3],[2439,3]]},"26":{"position":[[507,3]]}},"keywords":{}}],["down",{"_index":300,"title":{"91":{"position":[[23,4]]},"120":{"position":[[5,5]]}},"content":{"4":{"position":[[1527,5]]},"28":{"position":[[4396,4]]},"30":{"position":[[2369,4]]},"33":{"position":[[1097,4]]},"40":{"position":[[1596,5]]},"57":{"position":[[113,5],[123,5],[133,4]]},"62":{"position":[[344,4]]},"65":{"position":[[1343,4]]},"88":{"position":[[2774,4],[3170,4],[3639,5],[3747,5]]},"89":{"position":[[579,4]]},"91":{"position":[[90,4],[329,4],[1442,4],[1519,4],[2990,4],[3185,4],[4539,4],[5054,4],[5363,4]]},"92":{"position":[[135,4],[802,4],[997,4]]},"96":{"position":[[151,4]]},"101":{"position":[[418,4]]},"103":{"position":[[1928,4]]},"104":{"position":[[106,5]]},"116":{"position":[[2838,5]]},"121":{"position":[[2172,4]]},"125":{"position":[[6782,4]]},"129":{"position":[[506,4]]},"136":{"position":[[1006,4]]}},"keywords":{}}],["down."",{"_index":3074,"title":{},"content":{"91":{"position":[[212,11]]}},"keywords":{}}],["download",{"_index":873,"title":{"22":{"position":[[0,11]]}},"content":{"22":{"position":[[2996,11]]},"93":{"position":[[3735,11]]},"108":{"position":[[674,8]]},"160":{"position":[[2970,8]]}},"keywords":{}}],["downtrend",{"_index":3126,"title":{},"content":{"91":{"position":[[2492,9]]}},"keywords":{}}],["downturn",{"_index":763,"title":{},"content":{"20":{"position":[[170,9]]}},"keywords":{}}],["downward",{"_index":2952,"title":{},"content":{"89":{"position":[[661,8]]}},"keywords":{}}],["dr",{"_index":2409,"title":{"153":{"position":[[0,3]]}},"content":{"62":{"position":[[637,2],[830,3]]}},"keywords":{}}],["draft",{"_index":2254,"title":{},"content":{"53":{"position":[[1187,5]]}},"keywords":{}}],["dragon",{"_index":4067,"title":{},"content":{"125":{"position":[[2665,8]]}},"keywords":{}}],["dramat",{"_index":4216,"title":{},"content":{"125":{"position":[[11536,12]]},"174":{"position":[[1069,13]]}},"keywords":{}}],["drastic",{"_index":3542,"title":{},"content":{"103":{"position":[[1912,11]]}},"keywords":{}}],["drawdown",{"_index":704,"title":{"20":{"position":[[16,9]]}},"content":{"17":{"position":[[43,8]]},"20":{"position":[[231,8],[270,9],[902,8],[2682,9],[3008,9]]}},"keywords":{}}],["drawdown(returns[tick",{"_index":768,"title":{},"content":{"20":{"position":[[289,23]]}},"keywords":{}}],["drawdown_limit",{"_index":806,"title":{},"content":{"20":{"position":[[1076,14],[1734,14]]}},"keywords":{}}],["drawdowns[tick",{"_index":816,"title":{},"content":{"20":{"position":[[1322,16]]}},"keywords":{}}],["dream",{"_index":2196,"title":{},"content":{"53":{"position":[[66,7]]},"106":{"position":[[506,5]]}},"keywords":{}}],["dri",{"_index":4747,"title":{},"content":{"161":{"position":[[1039,6]]}},"keywords":{}}],["drift",{"_index":335,"title":{},"content":{"6":{"position":[[488,5]]},"9":{"position":[[142,5]]},"11":{"position":[[270,6]]}},"keywords":{}}],["drive",{"_index":2255,"title":{},"content":{"53":{"position":[[1204,6]]},"120":{"position":[[867,6]]},"139":{"position":[[634,7]]}},"keywords":{}}],["driven",{"_index":4667,"title":{},"content":{"160":{"position":[[917,6]]}},"keywords":{}}],["driver",{"_index":4997,"title":{},"content":{"174":{"position":[[1288,8]]}},"keywords":{}}],["drop",{"_index":985,"title":{"104":{"position":[[0,4]]}},"content":{"22":{"position":[[3021,4]]},"40":{"position":[[2289,4]]},"65":{"position":[[1338,4]]},"90":{"position":[[4922,7]]},"121":{"position":[[2164,7]]},"139":{"position":[[198,5]]},"143":{"position":[[77,4]]},"145":{"position":[[320,4],[390,4]]},"152":{"position":[[746,4]]},"155":{"position":[[1360,4],[1422,4],[1484,4],[1547,4]]},"156":{"position":[[644,4]]}},"keywords":{}}],["drop(i",{"_index":4520,"title":{},"content":{"152":{"position":[[765,8]]}},"keywords":{}}],["drop(x",{"_index":4602,"title":{},"content":{"156":{"position":[[1083,8]]}},"keywords":{}}],["drum",{"_index":3551,"title":{},"content":{"103":{"position":[[2407,5]]}},"keywords":{}}],["dt",{"_index":1490,"title":{},"content":{"30":{"position":[[9812,2],[9855,4],[9881,3],[9939,4]]}},"keywords":{}}],["dt_indic",{"_index":1478,"title":{},"content":{"30":{"position":[[9292,10],[9446,11]]}},"keywords":{}}],["dt_merg",{"_index":1480,"title":{},"content":{"30":{"position":[[9403,8],[9818,9]]}},"keywords":{}}],["dtpars",{"_index":3969,"title":{"136":{"position":[[11,8]]}},"content":{"123":{"position":[[139,8]]},"124":{"position":[[350,7],[518,8]]},"132":{"position":[[35,7]]},"136":{"position":[[252,10],[496,7]]}},"keywords":{}}],["dtparse::pars",{"_index":4379,"title":{},"content":{"135":{"position":[[443,15]]},"136":{"position":[[62,15]]}},"keywords":{}}],["dtparsehyp",{"_index":4346,"title":{},"content":{"132":{"position":[[400,12]]}},"keywords":{}}],["dtparser.parse(date_str",{"_index":942,"title":{},"content":{"22":{"position":[[1539,27]]}},"keywords":{}}],["dtype=int64",{"_index":1875,"title":{},"content":{"43":{"position":[[635,12]]}},"keywords":{}}],["dualiti",{"_index":4007,"title":{},"content":{"125":{"position":[[96,7]]}},"keywords":{}}],["due",{"_index":1807,"title":{},"content":{"40":{"position":[[1318,3]]},"91":{"position":[[3795,3]]},"115":{"position":[[2462,3]]},"116":{"position":[[2320,3]]},"169":{"position":[[225,3]]},"189":{"position":[[1296,3]]}},"keywords":{}}],["durat",{"_index":3517,"title":{},"content":{"103":{"position":[[638,8]]},"172":{"position":[[323,8]]}},"keywords":{}}],["dure",{"_index":1350,"title":{},"content":{"30":{"position":[[1026,6],[4579,6]]},"40":{"position":[[1528,6],[3230,6],[3453,6]]},"51":{"position":[[2602,6]]},"54":{"position":[[1,6]]},"101":{"position":[[691,6]]},"125":{"position":[[8446,6]]},"135":{"position":[[276,6],[362,6],[436,6]]},"136":{"position":[[46,6]]},"147":{"position":[[403,6],[551,6]]},"161":{"position":[[1476,6],[1619,6]]},"166":{"position":[[877,6]]},"172":{"position":[[2391,6]]},"176":{"position":[[495,6]]},"183":{"position":[[887,6]]},"199":{"position":[[677,6]]}},"keywords":{}}],["dutch",{"_index":4746,"title":{},"content":{"161":{"position":[[978,5],[1085,5]]}},"keywords":{}}],["dword",{"_index":4261,"title":{},"content":{"128":{"position":[[523,5],[636,5],[870,5],[1588,5]]},"183":{"position":[[387,5],[533,5]]}},"keywords":{}}],["dwrensha",{"_index":4802,"title":{},"content":{"164":{"position":[[150,8]]}},"keywords":{}}],["dyn",{"_index":5338,"title":{},"content":{"197":{"position":[[125,3]]}},"keywords":{}}],["dynam",{"_index":3310,"title":{"154":{"position":[[21,7]]}},"content":{"95":{"position":[[404,7]]},"97":{"position":[[915,11],[6267,12]]},"141":{"position":[[338,11]]},"155":{"position":[[168,7]]},"156":{"position":[[62,7],[177,7]]},"160":{"position":[[1722,7]]},"197":{"position":[[92,7],[143,7],[225,7],[674,7],[1488,7]]}},"keywords":{}}],["e",{"_index":1493,"title":{},"content":{"30":{"position":[[9905,2]]},"93":{"position":[[2554,1]]}},"keywords":{}}],["e.dat",{"_index":3242,"title":{},"content":{"93":{"position":[[2816,8]]}},"keywords":{}}],["e.earnings_offset",{"_index":3239,"title":{},"content":{"93":{"position":[[2726,17],[2797,18]]}},"keywords":{}}],["e.feed(str(s.get(base_url",{"_index":3237,"title":{},"content":{"93":{"position":[[2669,26]]}},"keywords":{}}],["e.g",{"_index":4922,"title":{},"content":{"172":{"position":[[1585,5]]}},"keywords":{}}],["each",{"_index":154,"title":{},"content":{"3":{"position":[[439,4],[1433,4]]},"4":{"position":[[1205,4]]},"7":{"position":[[1054,4]]},"18":{"position":[[32,4]]},"22":{"position":[[128,4]]},"24":{"position":[[64,4],[226,4]]},"28":{"position":[[734,4]]},"38":{"position":[[871,4]]},"51":{"position":[[1569,4]]},"71":{"position":[[1077,4]]},"74":{"position":[[443,4],[773,4],[873,4],[1542,4]]},"75":{"position":[[351,4],[605,4],[1285,4]]},"76":{"position":[[252,4],[539,4]]},"85":{"position":[[230,4]]},"86":{"position":[[1006,4]]},"90":{"position":[[76,4],[4292,4],[4504,4],[4611,4],[4789,4],[5097,4],[5274,4]]},"91":{"position":[[287,4],[1763,4]]},"104":{"position":[[205,4]]},"124":{"position":[[563,4]]},"135":{"position":[[201,4]]},"159":{"position":[[373,4]]},"163":{"position":[[106,4]]},"164":{"position":[[1060,4]]},"165":{"position":[[776,4],[1249,4]]},"167":{"position":[[281,4]]},"169":{"position":[[177,4]]},"172":{"position":[[190,4],[416,4]]},"188":{"position":[[2787,4]]},"189":{"position":[[1488,4]]},"193":{"position":[[55,4]]},"196":{"position":[[655,4]]},"197":{"position":[[892,4]]},"199":{"position":[[979,4]]}},"keywords":{}}],["each.mak",{"_index":1176,"title":{},"content":{"26":{"position":[[672,11]]}},"keywords":{}}],["earli",{"_index":3910,"title":{},"content":{"121":{"position":[[1844,5]]}},"keywords":{}}],["earlier",{"_index":2027,"title":{},"content":{"45":{"position":[[3404,7]]},"110":{"position":[[340,7]]},"111":{"position":[[546,8]]},"118":{"position":[[250,7]]},"127":{"position":[[534,8]]},"185":{"position":[[371,7],[557,7]]}},"keywords":{}}],["earlierstruct",{"_index":3424,"title":{},"content":{"97":{"position":[[5392,14]]}},"keywords":{}}],["earlybirthday",{"_index":2237,"title":{},"content":{"53":{"position":[[922,14]]}},"keywords":{}}],["earn",{"_index":1225,"title":{"87":{"position":[[18,8]]}},"content":{"28":{"position":[[812,6]]},"88":{"position":[[2115,8],[3672,8],[3757,8]]},"89":{"position":[[189,8],[435,8],[615,8],[872,8]]},"91":{"position":[[1479,8],[2130,8],[4565,8],[4742,8],[4918,8],[5091,9]]},"92":{"position":[[1389,8]]},"93":{"position":[[121,8],[238,8],[347,8],[1898,8]]}},"keywords":{}}],["earnings_data",{"_index":3113,"title":{},"content":{"91":{"position":[[2069,13]]},"93":{"position":[[4482,13]]}},"keywords":{}}],["earnings_data.item",{"_index":3121,"title":{},"content":{"91":{"position":[[2318,22]]}},"keywords":{}}],["earnings_data[tick",{"_index":3282,"title":{},"content":{"93":{"position":[[4837,21],[5252,21]]}},"keywords":{}}],["earnings_offset",{"_index":3204,"title":{},"content":{"93":{"position":[[1511,15]]}},"keywords":{}}],["earnings_releases(tick",{"_index":3218,"title":{},"content":{"93":{"position":[[2261,26]]}},"keywords":{}}],["earningspars",{"_index":3233,"title":{},"content":{"93":{"position":[[2558,16]]}},"keywords":{}}],["earningsparser(htmlpars",{"_index":3202,"title":{},"content":{"93":{"position":[[1463,27]]}},"keywords":{}}],["easi",{"_index":54,"title":{},"content":{"1":{"position":[[612,5]]},"20":{"position":[[13,4]]},"64":{"position":[[190,4]]},"66":{"position":[[407,4]]},"72":{"position":[[54,4]]},"90":{"position":[[142,4]]},"91":{"position":[[2193,4]]},"95":{"position":[[437,4]]},"96":{"position":[[102,4]]},"97":{"position":[[1092,4]]},"104":{"position":[[1236,4],[1893,4]]},"106":{"position":[[675,4]]},"108":{"position":[[491,4]]},"110":{"position":[[509,5]]},"121":{"position":[[569,4],[1818,4]]},"122":{"position":[[662,5]]},"128":{"position":[[337,4]]},"134":{"position":[[184,5]]},"158":{"position":[[402,4]]}},"keywords":{}}],["easier",{"_index":998,"title":{},"content":{"23":{"position":[[211,7]]},"39":{"position":[[330,7]]},"74":{"position":[[1184,6]]},"116":{"position":[[133,6]]}},"keywords":{}}],["easiest",{"_index":4446,"title":{},"content":{"144":{"position":[[5,7]]}},"keywords":{}}],["easili",{"_index":378,"title":{},"content":{"7":{"position":[[80,6]]}},"keywords":{}}],["eaten",{"_index":2270,"title":{},"content":{"53":{"position":[[1420,5]]}},"keywords":{}}],["eax",{"_index":4265,"title":{},"content":{"128":{"position":[[631,4],[663,3],[729,4]]}},"keywords":{}}],["echo",{"_index":3321,"title":{},"content":{"96":{"position":[[352,4]]},"97":{"position":[[3817,4],[4591,7],[4715,6],[6422,5]]},"104":{"position":[[1624,5]]}},"keywords":{}}],["echo.handl",{"_index":3408,"title":{},"content":{"97":{"position":[[3906,12]]}},"keywords":{}}],["echo.handle(req",{"_index":3413,"title":{},"content":{"97":{"position":[[4463,17],[4899,17]]}},"keywords":{}}],["echo_handler(request",{"_index":3324,"title":{},"content":{"96":{"position":[[464,22]]}},"keywords":{}}],["echohandl",{"_index":3401,"title":{},"content":{"97":{"position":[[3572,11],[3621,11],[3824,11],[4138,13]]}},"keywords":{}}],["ecosystem",{"_index":3935,"title":{},"content":{"122":{"position":[[169,10]]},"125":{"position":[[7452,10]]}},"keywords":{}}],["edg",{"_index":2285,"title":{"69":{"position":[[4,4]]},"70":{"position":[[0,4]]},"71":{"position":[[0,4]]}},"content":{"53":{"position":[[1948,4],[2067,4]]},"68":{"position":[[151,4]]},"69":{"position":[[110,4]]},"72":{"position":[[267,4]]},"105":{"position":[[19,4]]}},"keywords":{}}],["edi",{"_index":4264,"title":{},"content":{"128":{"position":[[619,7],[658,4],[832,7],[889,3],[1418,4],[1605,3]]},"181":{"position":[[174,4],[301,4],[432,4]]}},"keywords":{}}],["edit",{"_index":4254,"title":{},"content":{"128":{"position":[[433,6],[1258,6]]}},"keywords":{}}],["editor",{"_index":3911,"title":{},"content":{"121":{"position":[[1918,6]]}},"keywords":{}}],["effect",{"_index":2360,"title":{},"content":{"61":{"position":[[905,12]]},"90":{"position":[[3597,11]]},"91":{"position":[[2965,12]]},"92":{"position":[[777,12]]},"104":{"position":[[2041,7]]},"117":{"position":[[2052,7]]},"130":{"position":[[141,8]]},"176":{"position":[[1036,7]]},"188":{"position":[[1782,11],[3301,11]]},"189":{"position":[[1941,11]]},"196":{"position":[[687,7]]}},"keywords":{}}],["effici",{"_index":2094,"title":{},"content":{"51":{"position":[[974,9]]},"130":{"position":[[207,9]]},"132":{"position":[[413,10]]},"137":{"position":[[62,9]]},"175":{"position":[[361,9]]}},"keywords":{}}],["effort",{"_index":2017,"title":{},"content":{"45":{"position":[[2513,6]]},"97":{"position":[[2221,7]]},"125":{"position":[[10163,6]]}},"keywords":{}}],["eight",{"_index":5323,"title":{},"content":{"195":{"position":[[762,5]]}},"keywords":{}}],["eightk",{"_index":4550,"title":{},"content":{"153":{"position":[[590,6],[668,8]]},"195":{"position":[[287,6],[382,8]]}},"keywords":{}}],["eightm",{"_index":4552,"title":{},"content":{"153":{"position":[[709,6],[835,8]]},"195":{"position":[[601,6]]}},"keywords":{}}],["eightm::default",{"_index":4555,"title":{},"content":{"153":{"position":[[1007,18]]},"195":{"position":[[823,18]]}},"keywords":{}}],["eject",{"_index":165,"title":{},"content":{"3":{"position":[[605,5]]}},"keywords":{}}],["elaps",{"_index":3160,"title":{},"content":{"91":{"position":[[4468,7],[5278,7],[5661,7]]},"92":{"position":[[1241,7],[1799,7],[1958,7]]}},"keywords":{}}],["electron",{"_index":4029,"title":{},"content":{"125":{"position":[[831,8],[1436,9],[1463,8],[1613,8],[1721,8],[3560,8],[3824,8],[4634,9],[4852,8],[6215,8],[6272,8],[6855,8],[7171,8],[10561,8],[10692,8],[11223,8],[11684,8]]}},"keywords":{}}],["electron/wasm/rust",{"_index":4204,"title":{},"content":{"125":{"position":[[10997,18]]}},"keywords":{}}],["elem",{"_index":3134,"title":{},"content":{"91":{"position":[[3010,5]]},"92":{"position":[[822,5]]}},"keywords":{}}],["element",{"_index":3585,"title":{},"content":{"105":{"position":[[756,7]]},"156":{"position":[[750,8]]},"185":{"position":[[291,8],[594,7]]},"194":{"position":[[510,7]]}},"keywords":{}}],["elementsin",{"_index":4831,"title":{},"content":{"165":{"position":[[882,10]]}},"keywords":{}}],["elif",{"_index":958,"title":{},"content":{"22":{"position":[[1969,4],[2041,4],[2112,4],[2182,4]]},"93":{"position":[[2113,4]]},"121":{"position":[[1665,4]]}},"keywords":{}}],["elimin",{"_index":4519,"title":{},"content":{"152":{"position":[[754,10]]}},"keywords":{}}],["elseif",{"_index":648,"title":{},"content":{"14":{"position":[[1758,6]]},"15":{"position":[[1148,6]]}},"keywords":{}}],["elsewher",{"_index":3302,"title":{},"content":{"95":{"position":[[96,9]]},"188":{"position":[[725,10]]}},"keywords":{}}],["em",{"_index":2827,"title":{},"content":{"86":{"position":[[148,2],[611,2],[760,2],[1035,2]]}},"keywords":{}}],["emb",{"_index":4101,"title":{},"content":{"125":{"position":[[4817,5]]}},"keywords":{}}],["embed",{"_index":4098,"title":{},"content":{"125":{"position":[[4426,9]]},"160":{"position":[[1771,8],[2649,8],[2812,8]]}},"keywords":{}}],["emerg",{"_index":3171,"title":{},"content":{"91":{"position":[[5416,8]]}},"keywords":{}}],["emphasi",{"_index":4701,"title":{},"content":{"160":{"position":[[3287,8]]}},"keywords":{}}],["emscripten",{"_index":4065,"title":{},"content":{"125":{"position":[[2551,11]]}},"keywords":{}}],["enabl",{"_index":5059,"title":{},"content":{"178":{"position":[[224,7]]},"190":{"position":[[975,7]]}},"keywords":{}}],["encod",{"_index":3489,"title":{"166":{"position":[[14,9]]}},"content":{"102":{"position":[[45,8],[1480,8]]},"104":{"position":[[1696,8]]},"110":{"position":[[578,6]]},"164":{"position":[[828,10]]}},"keywords":{}}],["encount",{"_index":80,"title":{},"content":{"2":{"position":[[78,12]]}},"keywords":{}}],["encourag",{"_index":4839,"title":{},"content":{"166":{"position":[[173,11]]}},"keywords":{}}],["end",{"_index":219,"title":{},"content":{"4":{"position":[[3,5],[1399,4]]},"7":{"position":[[508,3],[526,3],[923,3],[1030,3],[1205,3],[1352,4]]},"9":{"position":[[821,4]]},"11":{"position":[[545,3]]},"12":{"position":[[506,3],[530,3]]},"13":{"position":[[889,3],[893,3],[1086,3],[1090,3],[1439,3],[1654,3]]},"14":{"position":[[696,3],[840,3],[951,3],[1033,3],[1907,3],[1911,3],[2120,3],[2124,3],[2511,3],[2737,3]]},"15":{"position":[[1575,3],[1579,3],[1788,3],[1792,3],[2183,3],[2411,3]]},"30":{"position":[[10354,3]]},"32":{"position":[[1153,4]]},"33":{"position":[[479,4]]},"34":{"position":[[1351,4],[1582,3],[2511,3],[2694,3],[3004,4],[3244,3]]},"39":{"position":[[2171,4]]},"40":{"position":[[1236,3]]},"45":{"position":[[952,4],[1437,3],[2643,3]]},"46":{"position":[[588,3]]},"51":{"position":[[3127,4]]},"53":{"position":[[1627,5]]},"58":{"position":[[337,6],[820,6]]},"76":{"position":[[2153,3],[3306,6]]},"78":{"position":[[318,3]]},"88":{"position":[[595,5],[2463,4]]},"93":{"position":[[4010,5]]},"95":{"position":[[525,3]]},"101":{"position":[[38,6]]},"102":{"position":[[404,3]]},"103":{"position":[[597,3],[1654,3]]},"104":{"position":[[1940,4]]},"105":{"position":[[3327,3]]},"118":{"position":[[272,5]]},"125":{"position":[[4792,3]]},"137":{"position":[[8,4]]},"150":{"position":[[384,4]]},"153":{"position":[[452,3]]},"160":{"position":[[3675,3]]},"161":{"position":[[1507,4]]},"164":{"position":[[1436,4]]},"193":{"position":[[1837,3],[2792,3]]},"199":{"position":[[729,5]]}},"keywords":{}}],["end=datetime(year",{"_index":1241,"title":{},"content":{"28":{"position":[[1304,18],[3104,18]]},"30":{"position":[[1670,18],[3019,18],[4943,18],[6087,18],[9352,18]]}},"keywords":{}}],["end_dat",{"_index":2408,"title":{},"content":{"62":{"position":[[604,8],[668,9]]},"90":{"position":[[3750,8],[3832,9]]}},"keywords":{}}],["end_date=end.strftime(q_format",{"_index":2858,"title":{},"content":{"88":{"position":[[847,32]]},"93":{"position":[[4262,32]]}},"keywords":{}}],["ending_pric",{"_index":1741,"title":{},"content":{"39":{"position":[[2002,12],[2041,12],[2089,12]]}},"keywords":{}}],["end{align*}cn​i=1∑n−1​oi​di​​+on​cn​dn​​on​cn​dn​​−dn​dn​(on​cn​−on​​)dn​​>i=1∑n−1​di​+dn​>i=1∑n−1​(di​−oi​cn​di​​)>i=1∑n−1​di​(1−oi​cn​​)>cn​−on​on​​i=1∑n−1​di​(1−oi​1",{"_index":1555,"title":{},"content":{"32":{"position":[[1906,184]]}},"keywords":{}}],["end{align*}d1​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​e[d1​]=3.5​d2​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​e[d2​]=3.5​e[d1​+d2​]=7=e[dfair​+dfair",{"_index":2609,"title":{},"content":{"71":{"position":[[844,188]]}},"keywords":{}}],["end{align*}d1​=⎩⎨⎧​123456​w.p.1/3w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12​e[d1​]=2.5​d2​=⎩⎨⎧​123456​w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3w.p.1/3​e[d2​]=4.5​e[d1​+d2​]=7=e[dfair​+dfair",{"_index":2592,"title":{},"content":{"70":{"position":[[744,188]]}},"keywords":{}}],["end{align*}l(x)=⎩⎨⎧​p2​p3​…p11​p12​​x=2x=3x=11x=12",{"_index":2641,"title":{},"content":{"74":{"position":[[712,53]]}},"keywords":{}}],["end{align*}l(x)​=i=1∏n​l(x",{"_index":2648,"title":{},"content":{"74":{"position":[[1124,29]]}},"keywords":{}}],["end{align*}log(l)​=i=1∑n​log(l",{"_index":2661,"title":{},"content":{"74":{"position":[[1727,33]]}},"keywords":{}}],["end{align*}max",{"_index":790,"title":{},"content":{"20":{"position":[[752,15]]}},"keywords":{}}],["end{array",{"_index":2585,"title":{},"content":{"70":{"position":[[423,11],[597,11],[670,13]]},"71":{"position":[[523,11],[697,11],[770,13]]},"74":{"position":[[692,11]]}},"keywords":{}}],["end{equation*}hrq​⋅n−hrd​⋅(n−m",{"_index":2461,"title":{},"content":{"64":{"position":[[570,33]]},"65":{"position":[[466,33]]}},"keywords":{}}],["enforc",{"_index":3822,"title":{},"content":{"117":{"position":[[636,7],[818,8]]}},"keywords":{}}],["engin",{"_index":2148,"title":{},"content":{"51":{"position":[[3553,6]]},"125":{"position":[[3393,11]]}},"keywords":{}}],["enhanced_packet",{"_index":4776,"title":{},"content":{"163":{"position":[[1684,16]]}},"keywords":{}}],["enhanced_packet_block(input",{"_index":4779,"title":{},"content":{"163":{"position":[[1744,28]]}},"keywords":{}}],["enjoy",{"_index":1183,"title":{},"content":{"26":{"position":[[821,7],[843,7]]},"41":{"position":[[19,8]]},"125":{"position":[[7258,5]]},"130":{"position":[[279,5]]},"150":{"position":[[184,5],[605,5]]},"165":{"position":[[333,7],[1396,7]]}},"keywords":{}}],["enough",{"_index":827,"title":{},"content":{"20":{"position":[[1693,6]]},"25":{"position":[[2781,6]]},"45":{"position":[[2688,6]]},"53":{"position":[[1403,6]]},"74":{"position":[[1637,7]]},"88":{"position":[[139,6]]},"102":{"position":[[278,7]]},"106":{"position":[[67,7]]},"124":{"position":[[114,7]]},"125":{"position":[[7952,6]]},"132":{"position":[[361,7]]},"150":{"position":[[638,6]]},"161":{"position":[[847,7]]},"181":{"position":[[583,6],[892,7]]},"194":{"position":[[97,6]]},"195":{"position":[[113,7]]}},"keywords":{}}],["enough"",{"_index":3576,"title":{},"content":{"105":{"position":[[238,12]]}},"keywords":{}}],["enougho",{"_index":3669,"title":{},"content":{"108":{"position":[[451,8]]}},"keywords":{}}],["ensur",{"_index":2697,"title":{},"content":{"76":{"position":[[1007,6]]},"90":{"position":[[434,6]]},"160":{"position":[[1391,6]]},"196":{"position":[[1902,7]]}},"keywords":{}}],["enter_protect",{"_index":4466,"title":{},"content":{"146":{"position":[[264,18]]}},"keywords":{}}],["entir",{"_index":2023,"title":{},"content":{"45":{"position":[[2776,6]]},"58":{"position":[[775,6]]},"63":{"position":[[117,6]]},"74":{"position":[[1010,6]]},"88":{"position":[[661,6]]},"91":{"position":[[3229,6]]},"92":{"position":[[1041,6]]},"93":{"position":[[76,6],[481,6],[4076,6]]},"103":{"position":[[2424,8]]},"144":{"position":[[30,6]]},"174":{"position":[[918,9]]}},"keywords":{}}],["entri",{"_index":178,"title":{},"content":{"3":{"position":[[850,5]]},"136":{"position":[[230,5]]}},"keywords":{}}],["enum",{"_index":3886,"title":{"194":{"position":[[0,6]]}},"content":{"121":{"position":[[866,6]]},"159":{"position":[[651,6]]},"194":{"position":[[170,4],[219,4],[478,4],[610,4],[656,5]]}},"keywords":{}}],["enum_compar",{"_index":5314,"title":{},"content":{"194":{"position":[[306,14]]}},"keywords":{}}],["enumerate(all_word",{"_index":2105,"title":{},"content":{"51":{"position":[[1337,20]]}},"keywords":{}}],["env",{"_index":4167,"title":{},"content":{"125":{"position":[[8552,5],[9020,5]]}},"keywords":{}}],["environ",{"_index":3676,"title":{},"content":{"108":{"position":[[755,11]]},"113":{"position":[[469,11]]},"176":{"position":[[1318,11],[1378,11]]}},"keywords":{}}],["epoch",{"_index":1471,"title":{},"content":{"30":{"position":[[8933,5],[9024,6]]}},"keywords":{}}],["eq",{"_index":838,"title":{},"content":{"20":{"position":[[2040,5]]}},"keywords":{}}],["equal",{"_index":4518,"title":{},"content":{"152":{"position":[[712,6]]}},"keywords":{}}],["equipmentfor",{"_index":5008,"title":{},"content":{"175":{"position":[[426,12]]}},"keywords":{}}],["equival",{"_index":3566,"title":{},"content":{"104":{"position":[[1132,10]]},"132":{"position":[[104,10]]},"173":{"position":[[292,10]]},"196":{"position":[[1486,10]]}},"keywords":{}}],["eric",{"_index":2257,"title":{},"content":{"53":{"position":[[1228,4]]}},"keywords":{}}],["error",{"_index":94,"title":{},"content":{"2":{"position":[[298,6]]},"3":{"position":[[67,6]]},"74":{"position":[[1445,6]]},"96":{"position":[[260,5],[1242,6],[1771,6],[1780,6]]},"97":{"position":[[1794,7],[4070,7],[4080,6],[4511,6]]},"98":{"position":[[1009,6]]},"115":{"position":[[913,6],[2446,6],[2480,6],[2565,6]]},"116":{"position":[[903,6],[2304,6],[2338,6],[2638,5]]},"125":{"position":[[4527,6],[7727,6],[8471,5],[8531,6],[8941,5],[8999,6],[11244,5]]},"127":{"position":[[703,5],[719,5],[743,6],[815,5]]},"153":{"position":[[499,7]]},"160":{"position":[[4266,5]]},"179":{"position":[[1754,6]]},"184":{"position":[[974,5]]},"188":{"position":[[3659,6]]},"190":{"position":[[773,6]]}},"keywords":{}}],["error=()>",{"_index":4476,"title":{},"content":{"147":{"position":[[250,12]]}},"keywords":{}}],["error[e0204",{"_index":5367,"title":{},"content":{"198":{"position":[[1032,13]]}},"keywords":{}}],["error[e0277",{"_index":3378,"title":{},"content":{"97":{"position":[[1835,13]]},"115":{"position":[[927,13],[1241,13],[1621,13],[1898,13]]},"116":{"position":[[926,13],[1193,13],[1526,13],[1803,13]]},"184":{"position":[[1025,13]]},"185":{"position":[[706,13]]}},"keywords":{}}],["error[e0369",{"_index":3338,"title":{},"content":{"96":{"position":[[1251,13]]}},"keywords":{}}],["error[e0373",{"_index":3414,"title":{},"content":{"97":{"position":[[4520,13]]}},"keywords":{}}],["error[e0507",{"_index":3422,"title":{},"content":{"97":{"position":[[4978,13]]}},"keywords":{}}],["es",{"_index":4185,"title":{},"content":{"125":{"position":[[9474,2]]}},"keywords":{}}],["es6",{"_index":4143,"title":{},"content":{"125":{"position":[[6792,3]]}},"keywords":{}}],["especi",{"_index":2957,"title":{},"content":{"89":{"position":[[901,10]]},"139":{"position":[[204,10]]},"142":{"position":[[153,10]]},"150":{"position":[[751,10]]}},"keywords":{}}],["essenti",{"_index":2352,"title":{},"content":{"61":{"position":[[190,11]]},"96":{"position":[[840,11]]},"97":{"position":[[5410,11]]},"102":{"position":[[1262,11]]},"125":{"position":[[9876,9]]},"133":{"position":[[380,11]]}},"keywords":{}}],["essentiallyjust",{"_index":4845,"title":{},"content":{"166":{"position":[[474,15]]}},"keywords":{}}],["establish",{"_index":4085,"title":{},"content":{"125":{"position":[[3704,11]]}},"keywords":{}}],["estim",{"_index":2118,"title":{},"content":{"51":{"position":[[2030,9]]},"57":{"position":[[587,8]]},"58":{"position":[[444,9],[657,10]]},"65":{"position":[[156,8],[2213,8]]},"105":{"position":[[391,8],[903,8]]}},"keywords":{}}],["etc",{"_index":1911,"title":{},"content":{"44":{"position":[[554,4]]},"91":{"position":[[3991,6]]},"92":{"position":[[1463,6]]},"96":{"position":[[1990,5]]},"97":{"position":[[3112,4]]},"98":{"position":[[608,5]]},"104":{"position":[[1724,5]]},"125":{"position":[[1426,4],[6495,5]]},"159":{"position":[[995,5],[1075,5]]},"160":{"position":[[2579,5]]},"178":{"position":[[110,6]]}},"keywords":{}}],["etern",{"_index":4624,"title":{},"content":{"158":{"position":[[222,9]]}},"keywords":{}}],["etf",{"_index":1824,"title":{},"content":{"40":{"position":[[2600,5],[3360,3],[3598,3]]},"93":{"position":[[2948,3]]}},"keywords":{}}],["etf'",{"_index":1835,"title":{},"content":{"40":{"position":[[3262,5]]}},"keywords":{}}],["etf/1449138789749.ajax",{"_index":3249,"title":{},"content":{"93":{"position":[[3087,24]]}},"keywords":{}}],["ethic",{"_index":2261,"title":{},"content":{"53":{"position":[[1264,6],[1980,6]]}},"keywords":{}}],["eurosfor",{"_index":5003,"title":{},"content":{"175":{"position":[[73,8]]}},"keywords":{}}],["evalu",{"_index":4712,"title":{},"content":{"160":{"position":[[3892,10]]}},"keywords":{}}],["evaluate_gnb(dim",{"_index":1994,"title":{},"content":{"45":{"position":[[2016,19],[2220,18],[3000,18]]}},"keywords":{}}],["evaluate_gnb_full(dim",{"_index":2024,"title":{},"content":{"45":{"position":[[2798,24]]}},"keywords":{}}],["evaluation_tim",{"_index":1746,"title":{},"content":{"39":{"position":[[2262,16],[2587,17]]}},"keywords":{}}],["even",{"_index":34,"title":{},"content":{"1":{"position":[[376,7]]},"3":{"position":[[31,4],[784,4]]},"14":{"position":[[169,4]]},"22":{"position":[[2821,4]]},"30":{"position":[[2623,4],[4301,4]]},"32":{"position":[[121,4],[1362,4],[2146,5]]},"33":{"position":[[1196,4]]},"34":{"position":[[257,4]]},"38":{"position":[[409,4]]},"40":{"position":[[1376,4],[3478,4]]},"46":{"position":[[393,4]]},"58":{"position":[[267,4]]},"61":{"position":[[1037,4]]},"65":{"position":[[2559,7]]},"66":{"position":[[498,4]]},"71":{"position":[[1045,4]]},"83":{"position":[[177,4],[378,4]]},"85":{"position":[[8,4]]},"89":{"position":[[110,4]]},"93":{"position":[[256,4]]},"97":{"position":[[297,4]]},"101":{"position":[[681,4]]},"106":{"position":[[414,4],[457,4],[734,4]]},"122":{"position":[[1037,4],[1296,4]]},"125":{"position":[[2249,4],[10188,4]]},"134":{"position":[[391,4]]},"145":{"position":[[268,4]]},"148":{"position":[[229,4]]},"174":{"position":[[1301,4]]},"179":{"position":[[436,4]]},"181":{"position":[[828,5]]},"184":{"position":[[226,4]]},"185":{"position":[[430,4]]},"188":{"position":[[1826,4],[3164,4]]},"193":{"position":[[2399,4]]},"195":{"position":[[1023,4]]},"196":{"position":[[1068,4],[1448,4],[1657,4]]},"197":{"position":[[1179,4]]}},"keywords":{}}],["evening/weekend/christma",{"_index":4488,"title":{},"content":{"150":{"position":[[69,25]]}},"keywords":{}}],["event",{"_index":2688,"title":{"87":{"position":[[0,5]]},"90":{"position":[[0,5]]},"91":{"position":[[0,5]]},"92":{"position":[[0,5]]}},"content":{"76":{"position":[[544,6]]},"90":{"position":[[63,5],[797,5],[2182,5],[3204,7],[3280,6],[3371,7],[3943,5],[3952,7],[4020,6],[4297,7],[4886,7],[5119,6],[5296,6]]},"91":{"position":[[19,5],[1752,6],[2441,6],[2478,7],[2615,7],[3436,5],[3500,6],[4028,6],[4091,7],[4241,7]]},"92":{"position":[[254,6],[291,7],[427,7]]},"93":{"position":[[1200,5],[3779,5],[4859,6],[4886,5],[5274,6],[5301,5]]}},"keywords":{}}],["event.th",{"_index":3067,"title":{},"content":{"90":{"position":[[5215,9]]}},"keywords":{}}],["event_d",{"_index":3041,"title":{},"content":{"90":{"position":[[4027,11],[4156,12]]}},"keywords":{}}],["event_data",{"_index":3035,"title":{},"content":{"90":{"position":[[3842,10]]},"91":{"position":[[3569,10],[3703,12]]}},"keywords":{}}],["event_str",{"_index":3281,"title":{},"content":{"93":{"position":[[4824,10],[4895,11],[5239,10],[5310,11]]}},"keywords":{}}],["eventu",{"_index":2065,"title":{},"content":{"50":{"position":[[130,10]]},"76":{"position":[[930,10]]},"111":{"position":[[112,10]]},"125":{"position":[[8815,10]]},"199":{"position":[[565,10]]}},"keywords":{}}],["everybodi",{"_index":3486,"title":{},"content":{"101":{"position":[[943,10]]}},"keywords":{}}],["everyon",{"_index":2264,"title":{},"content":{"53":{"position":[[1303,8],[2018,9]]}},"keywords":{}}],["everyth",{"_index":8,"title":{},"content":{"1":{"position":[[44,10]]},"43":{"position":[[1069,10]]},"52":{"position":[[527,10]]},"61":{"position":[[668,10]]},"75":{"position":[[1187,10]]},"76":{"position":[[1446,10]]},"91":{"position":[[3837,10]]},"105":{"position":[[432,10]]},"109":{"position":[[598,10]]},"112":{"position":[[16,10]]},"120":{"position":[[462,10]]},"124":{"position":[[188,10]]},"125":{"position":[[2191,10],[2674,10],[3950,10],[4157,10],[9436,10]]},"133":{"position":[[358,10]]},"156":{"position":[[223,10]]},"159":{"position":[[574,10]]},"196":{"position":[[287,10]]}},"keywords":{}}],["everything'",{"_index":5272,"title":{},"content":{"193":{"position":[[110,12]]}},"keywords":{}}],["everywher",{"_index":4036,"title":{},"content":{"125":{"position":[[1072,11]]},"180":{"position":[[589,11]]}},"keywords":{}}],["evid",{"_index":1413,"title":{},"content":{"30":{"position":[[5693,8]]},"89":{"position":[[139,8]]}},"keywords":{}}],["ex",{"_index":3211,"title":{},"content":{"93":{"position":[[1948,3]]}},"keywords":{}}],["exact",{"_index":2478,"title":{},"content":{"64":{"position":[[1198,5]]}},"keywords":{}}],["exactli",{"_index":1556,"title":{},"content":{"32":{"position":[[2106,7]]},"44":{"position":[[1274,7]]},"45":{"position":[[3333,7]]},"58":{"position":[[282,7]]},"65":{"position":[[173,7],[1562,7]]},"73":{"position":[[85,7],[224,7],[706,7]]},"91":{"position":[[177,7],[3760,7]]},"97":{"position":[[6186,7]]},"101":{"position":[[501,7]]},"112":{"position":[[228,7]]},"125":{"position":[[7987,7]]},"128":{"position":[[1889,7]]},"132":{"position":[[470,7]]},"139":{"position":[[163,7],[881,7]]},"143":{"position":[[9,7]]},"160":{"position":[[3132,7]]},"170":{"position":[[475,7]]},"196":{"position":[[1028,7]]},"199":{"position":[[742,7]]}},"keywords":{}}],["examin",{"_index":1193,"title":{"28":{"position":[[0,9]]}},"content":{"28":{"position":[[354,7]]}},"keywords":{}}],["exampl",{"_index":185,"title":{"8":{"position":[[0,7]]},"105":{"position":[[17,8]]},"140":{"position":[[0,7]]},"141":{"position":[[0,7]]},"142":{"position":[[0,7]]}},"content":{"3":{"position":[[1002,8]]},"4":{"position":[[345,8],[1318,7]]},"10":{"position":[[170,7]]},"14":{"position":[[277,8],[577,7]]},"15":{"position":[[279,8],[538,7]]},"34":{"position":[[3894,8]]},"40":{"position":[[3046,8]]},"49":{"position":[[248,8],[300,7]]},"50":{"position":[[264,7]]},"51":{"position":[[3284,8]]},"52":{"position":[[106,7]]},"72":{"position":[[24,8],[408,8]]},"82":{"position":[[1110,9]]},"83":{"position":[[428,7]]},"86":{"position":[[737,7]]},"88":{"position":[[20,8]]},"89":{"position":[[30,9],[66,8]]},"90":{"position":[[3469,7],[4860,8]]},"91":{"position":[[393,8]]},"96":{"position":[[244,7],[623,8]]},"97":{"position":[[1062,9],[1122,7],[2825,8],[2907,7]]},"104":{"position":[[323,8]]},"112":{"position":[[1004,7],[1469,8]]},"113":{"position":[[2540,8]]},"125":{"position":[[2929,7],[8859,9],[8888,7]]},"129":{"position":[[270,9],[2804,7]]},"135":{"position":[[313,8]]},"155":{"position":[[704,8]]},"163":{"position":[[803,8],[2145,7]]},"164":{"position":[[663,8]]},"172":{"position":[[1021,8],[2601,8]]},"173":{"position":[[709,9]]},"176":{"position":[[936,8]]},"179":{"position":[[327,7],[1203,7]]},"181":{"position":[[383,8]]},"183":{"position":[[230,7]]},"185":{"position":[[379,8],[565,7]]},"186":{"position":[[211,7]]},"193":{"position":[[896,8]]},"196":{"position":[[660,7],[1513,8]]},"199":{"position":[[991,8]]}},"keywords":{}}],["example,refcell::new",{"_index":5127,"title":{},"content":{"184":{"position":[[892,22]]}},"keywords":{}}],["example::factor",{"_index":5118,"title":{},"content":{"183":{"position":[[404,17],[550,17]]}},"keywords":{}}],["example::main",{"_index":4270,"title":{},"content":{"128":{"position":[[1266,14]]},"129":{"position":[[512,14]]}},"keywords":{}}],["example::my_funct",{"_index":4272,"title":{},"content":{"128":{"position":[[1471,20],[1504,21]]}},"keywords":{}}],["examplerun",{"_index":4181,"title":{},"content":{"125":{"position":[[9296,14]]}},"keywords":{}}],["exce",{"_index":5321,"title":{},"content":{"195":{"position":[[414,7]]}},"keywords":{}}],["except",{"_index":627,"title":{},"content":{"14":{"position":[[104,9]]},"22":{"position":[[1692,6]]},"30":{"position":[[9885,6],[9892,9]]},"40":{"position":[[3157,10]]},"91":{"position":[[3107,6],[3716,6]]},"92":{"position":[[919,6],[1326,9]]},"93":{"position":[[5004,6],[5419,6]]},"97":{"position":[[5295,11]]},"116":{"position":[[2387,10]]},"121":{"position":[[1229,10]]},"160":{"position":[[2381,7]]}},"keywords":{}}],["excess",{"_index":4397,"title":{},"content":{"136":{"position":[[648,10]]}},"keywords":{}}],["exchang",{"_index":3255,"title":{},"content":{"93":{"position":[[3278,8]]}},"keywords":{}}],["excit",{"_index":1335,"title":{},"content":{"30":{"position":[[461,7]]},"98":{"position":[[1140,7]]},"121":{"position":[[651,8]]},"122":{"position":[[14,8]]}},"keywords":{}}],["exclud",{"_index":4945,"title":{},"content":{"173":{"position":[[586,9]]}},"keywords":{}}],["exclus",{"_index":4944,"title":{},"content":{"173":{"position":[[435,11]]}},"keywords":{}}],["execut",{"_index":3291,"title":{},"content":{"93":{"position":[[5066,7]]},"135":{"position":[[191,9],[342,10]]},"172":{"position":[[2007,9]]},"174":{"position":[[41,9]]},"178":{"position":[[365,10]]},"179":{"position":[[1530,8]]},"183":{"position":[[894,10]]}},"keywords":{}}],["exercis",{"_index":2449,"title":{},"content":{"63":{"position":[[148,9]]}},"keywords":{}}],["exist",{"_index":195,"title":{},"content":{"3":{"position":[[1177,8]]},"30":{"position":[[2603,5]]},"91":{"position":[[3147,6],[3984,6]]},"92":{"position":[[959,6]]},"122":{"position":[[1081,7]]},"124":{"position":[[705,7]]},"129":{"position":[[858,6],[1081,6],[2429,6]]},"137":{"position":[[105,5]]},"150":{"position":[[299,8]]}},"keywords":{}}],["exit",{"_index":3793,"title":{},"content":{"115":{"position":[[2983,5]]},"152":{"position":[[1052,4]]}},"keywords":{}}],["exit_protect",{"_index":4468,"title":{},"content":{"146":{"position":[[361,17]]}},"keywords":{}}],["exp",{"_index":398,"title":{},"content":{"7":{"position":[[457,6]]},"13":{"position":[[1791,5]]},"14":{"position":[[2874,4]]},"15":{"position":[[2548,4]]}},"keywords":{}}],["exp((prod(forward_structure[i:end",{"_index":571,"title":{},"content":{"13":{"position":[[843,35]]}},"keywords":{}}],["exp(forward_structure[i",{"_index":649,"title":{},"content":{"14":{"position":[[1820,24],[1879,24]]},"15":{"position":[[1411,24],[1547,24]]}},"keywords":{}}],["exp(sqrt(t",{"_index":400,"title":{},"content":{"7":{"position":[[479,11]]}},"keywords":{}}],["expans",{"_index":1955,"title":{},"content":{"44":{"position":[[1927,9]]},"45":{"position":[[557,10]]}},"keywords":{}}],["expect",{"_index":675,"title":{},"content":{"15":{"position":[[639,6]]},"20":{"position":[[2752,8],[2967,9],[2994,9]]},"24":{"position":[[299,6]]},"26":{"position":[[41,8]]},"33":{"position":[[1133,9]]},"34":{"position":[[684,12],[734,12],[1625,9],[2089,8],[3112,6]]},"39":{"position":[[1036,9],[1302,8],[2185,9]]},"40":{"position":[[1179,9]]},"41":{"position":[[492,8]]},"51":{"position":[[1905,9]]},"58":{"position":[[567,11],[587,10],[621,8]]},"69":{"position":[[308,8],[368,8]]},"70":{"position":[[1324,10]]},"71":{"position":[[1059,8]]},"72":{"position":[[83,8],[144,8],[293,8],[346,8]]},"88":{"position":[[2315,8]]},"96":{"position":[[1787,8],[1867,7]]},"103":{"position":[[2170,9]]},"106":{"position":[[124,9]]},"120":{"position":[[1091,6]]},"125":{"position":[[2184,6],[9858,6]]},"142":{"position":[[263,6]]},"148":{"position":[[209,7],[480,6]]},"161":{"position":[[1455,8]]},"172":{"position":[[1927,7]]},"175":{"position":[[784,6]]},"179":{"position":[[1012,8]]},"188":{"position":[[1900,8]]},"189":{"position":[[2034,9]]},"195":{"position":[[1054,8]]}},"keywords":{}}],["expected_clos",{"_index":1634,"title":{},"content":{"34":{"position":[[2053,14],[2151,15],[2261,14]]},"39":{"position":[[1268,14],[1362,15],[1481,14]]}},"keywords":{}}],["expected_drawdown",{"_index":857,"title":{},"content":{"20":{"position":[[2580,17]]}},"keywords":{}}],["expected_profit",{"_index":1639,"title":{},"content":{"34":{"position":[[2243,15]]},"39":{"position":[[1463,15]]}},"keywords":{}}],["expected_return",{"_index":853,"title":{},"content":{"20":{"position":[[2473,15]]}},"keywords":{}}],["expediti",{"_index":4720,"title":{},"content":{"160":{"position":[[4293,14]]}},"keywords":{}}],["expensivesystem",{"_index":4958,"title":{},"content":{"173":{"position":[[1081,15]]}},"keywords":{}}],["experi",{"_index":201,"title":{},"content":{"3":{"position":[[1244,11]]},"29":{"position":[[320,11]]},"35":{"position":[[396,10]]},"97":{"position":[[372,10],[990,10]]},"100":{"position":[[219,10]]},"106":{"position":[[971,11]]},"121":{"position":[[297,11]]},"150":{"position":[[522,11]]},"189":{"position":[[917,11]]}},"keywords":{}}],["experienc",{"_index":2031,"title":{},"content":{"46":{"position":[[365,11]]}},"keywords":{}}],["expires_in",{"_index":2379,"title":{},"content":{"61":{"position":[[1683,13]]}},"keywords":{}}],["explain",{"_index":2628,"title":{},"content":{"73":{"position":[[831,8]]},"74":{"position":[[937,8]]},"76":{"position":[[105,7]]},"97":{"position":[[5219,7]]},"104":{"position":[[496,7],[678,10]]},"129":{"position":[[1340,9]]}},"keywords":{}}],["explan",{"_index":3063,"title":{},"content":{"90":{"position":[[4723,11]]}},"keywords":{}}],["explicitli",{"_index":2302,"title":{},"content":{"55":{"position":[[171,10]]},"188":{"position":[[1186,10],[1343,10]]}},"keywords":{}}],["explod",{"_index":4442,"title":{},"content":{"143":{"position":[[245,8]]}},"keywords":{}}],["explor",{"_index":206,"title":{"43":{"position":[[5,12]]}},"content":{"3":{"position":[[1328,9]]},"28":{"position":[[27,7]]},"128":{"position":[[316,8],[1233,9]]},"129":{"position":[[392,8],[1374,8]]},"152":{"position":[[1671,8]]},"153":{"position":[[1042,8]]},"155":{"position":[[1619,8]]},"156":{"position":[[710,8]]},"180":{"position":[[537,8]]},"181":{"position":[[365,8]]},"183":{"position":[[632,8]]},"192":{"position":[[575,8]]},"193":{"position":[[1977,8],[2932,8],[3784,8]]},"194":{"position":[[445,8]]},"196":{"position":[[1204,9],[1615,9],[1817,9]]},"197":{"position":[[1430,8]]},"198":{"position":[[1178,8]]},"199":{"position":[[1718,8]]}},"keywords":{}}],["exploratori",{"_index":1860,"title":{},"content":{"43":{"position":[[48,11]]}},"keywords":{}}],["expor",{"_index":4709,"title":{},"content":{"160":{"position":[[3824,8]]}},"keywords":{}}],["export",{"_index":3197,"title":{},"content":{"93":{"position":[[1193,6]]},"125":{"position":[[6624,8]]}},"keywords":{}}],["expos",{"_index":4189,"title":{},"content":{"125":{"position":[[9667,7]]},"176":{"position":[[562,6]]}},"keywords":{}}],["express",{"_index":3928,"title":{},"content":{"121":{"position":[[2699,11]]},"196":{"position":[[107,11]]}},"keywords":{}}],["extend",{"_index":284,"title":{},"content":{"4":{"position":[[1177,6]]},"110":{"position":[[76,6]]}},"keywords":{}}],["extens",{"_index":3927,"title":{},"content":{"121":{"position":[[2667,11]]}},"keywords":{}}],["extern",{"_index":3700,"title":{},"content":{"111":{"position":[[303,6]]},"113":{"position":[[334,6]]},"190":{"position":[[615,8]]}},"keywords":{}}],["extra",{"_index":1704,"title":{},"content":{"38":{"position":[[1104,5]]},"88":{"position":[[2182,5]]},"111":{"position":[[734,5]]},"113":{"position":[[222,5]]},"120":{"position":[[202,6]]},"124":{"position":[[439,5]]},"140":{"position":[[201,5]]},"160":{"position":[[2165,5]]},"192":{"position":[[606,5]]},"193":{"position":[[3484,5]]}},"keywords":{}}],["extrapol",{"_index":2335,"title":{"63":{"position":[[5,14]]}},"content":{"58":{"position":[[521,13],[758,13]]},"62":{"position":[[178,13]]},"66":{"position":[[221,13]]}},"keywords":{}}],["extrem",{"_index":5041,"title":{},"content":{"176":{"position":[[84,7]]}},"keywords":{}}],["eyebrow",{"_index":1514,"title":{},"content":{"32":{"position":[[94,8]]}},"keywords":{}}],["f",{"_index":1269,"title":{},"content":{"28":{"position":[[2075,1],[3730,1]]},"30":{"position":[[2052,1],[3546,1],[3745,1],[5302,1],[6620,1],[6825,1]]},"88":{"position":[[1071,2],[2679,2]]},"90":{"position":[[1310,2]]},"91":{"position":[[408,2]]}},"keywords":{}}],["f.line(year",{"_index":1275,"title":{},"content":{"28":{"position":[[2222,13],[3895,13]]},"30":{"position":[[2175,13],[3661,13],[3880,13],[5434,13],[6734,13],[6959,13]]}},"keywords":{}}],["f.set_size_inches(18",{"_index":2937,"title":{},"content":{"88":{"position":[[3529,21]]},"91":{"position":[[438,21]]}},"keywords":{}}],["f64",{"_index":3941,"title":{},"content":{"122":{"position":[[409,4]]}},"keywords":{}}],["f_{i",{"_index":467,"title":{},"content":{"9":{"position":[[447,4]]}},"keywords":{}}],["face",{"_index":2698,"title":{},"content":{"76":{"position":[[1080,4]]}},"keywords":{}}],["facebook",{"_index":2888,"title":{},"content":{"88":{"position":[[1734,9],[2329,8],[3694,9]]}},"keywords":{}}],["fact",{"_index":1286,"title":{},"content":{"28":{"position":[[2605,4]]},"30":{"position":[[4340,4]]},"96":{"position":[[829,5]]}},"keywords":{}}],["facto",{"_index":3955,"title":{},"content":{"122":{"position":[[1160,5]]}},"keywords":{}}],["factor",{"_index":2228,"title":{},"content":{"53":{"position":[[777,6]]},"181":{"position":[[78,7],[205,6],[333,6],[342,6],[396,6]]},"183":{"position":[[303,7],[429,6],[454,6],[575,6],[600,6],[609,6],[742,6]]}},"keywords":{}}],["fail",{"_index":2673,"title":{},"content":{"75":{"position":[[1060,4],[1137,4]]},"76":{"position":[[2250,6]]},"82":{"position":[[1314,5]]},"188":{"position":[[456,4]]}},"keywords":{}}],["fair",{"_index":2558,"title":{},"content":{"68":{"position":[[244,4],[343,4],[875,4]]},"69":{"position":[[49,4],[397,4]]},"71":{"position":[[1116,4]]},"72":{"position":[[116,4],[178,4],[375,4],[588,4]]},"76":{"position":[[1993,4]]},"77":{"position":[[156,4]]},"81":{"position":[[27,4]]},"86":{"position":[[11,4]]}},"keywords":{}}],["fair_1",{"_index":2560,"title":{},"content":{"68":{"position":[[492,6]]}},"keywords":{}}],["fair_2",{"_index":2563,"title":{},"content":{"68":{"position":[[532,6]]}},"keywords":{}}],["fair_2).plot(kind='hist",{"_index":2565,"title":{},"content":{"68":{"position":[[591,25]]}},"keywords":{}}],["fairli",{"_index":1122,"title":{},"content":{"24":{"position":[[3037,6]]},"40":{"position":[[3122,6]]},"41":{"position":[[551,6]]},"93":{"position":[[1090,6]]},"150":{"position":[[22,6]]},"160":{"position":[[1219,6]]}},"keywords":{}}],["fall",{"_index":2823,"title":{},"content":{"85":{"position":[[518,4]]},"156":{"position":[[335,4]]}},"keywords":{}}],["fals",{"_index":928,"title":{},"content":{"22":{"position":[[1212,5],[1232,5],[2318,5]]},"91":{"position":[[3309,5]]},"92":{"position":[[1121,5]]},"93":{"position":[[1505,5],[2251,5]]},"121":{"position":[[1058,5],[1082,6]]},"136":{"position":[[421,6],[428,6],[441,6]]}},"keywords":{}}],["famili",{"_index":1201,"title":{},"content":{"28":{"position":[[179,6]]},"172":{"position":[[1451,6]]}},"keywords":{}}],["familiar",{"_index":3400,"title":{},"content":{"97":{"position":[[3341,9]]},"110":{"position":[[133,8]]},"128":{"position":[[1297,9]]},"155":{"position":[[559,9]]},"163":{"position":[[581,9]]}},"keywords":{}}],["fan",{"_index":1024,"title":{},"content":{"24":{"position":[[474,3]]},"25":{"position":[[199,3]]},"40":{"position":[[2337,4]]}},"keywords":{}}],["fanci",{"_index":2818,"title":{},"content":{"85":{"position":[[37,5]]},"192":{"position":[[612,5]]}},"keywords":{}}],["fang",{"_index":1783,"title":{},"content":{"40":{"position":[[36,4],[1396,4],[1614,4]]}},"keywords":{}}],["fang_df",{"_index":1785,"title":{},"content":{"40":{"position":[[108,7]]}},"keywords":{}}],["fang_df.xs('day",{"_index":1790,"title":{},"content":{"40":{"position":[[233,18]]}},"keywords":{}}],["fang_df.xs('scor",{"_index":1796,"title":{},"content":{"40":{"position":[[401,19]]}},"keywords":{}}],["fantast",{"_index":2942,"title":{},"content":{"88":{"position":[[3771,9]]}},"keywords":{}}],["far",{"_index":526,"title":{"64":{"position":[[23,5]]}},"content":{"12":{"position":[[171,3]]},"29":{"position":[[361,3]]},"39":{"position":[[97,4]]},"40":{"position":[[3380,3],[3494,3]]},"41":{"position":[[4,3],[574,4]]},"46":{"position":[[485,4]]},"54":{"position":[[301,4]]},"57":{"position":[[496,3],[521,3]]},"58":{"position":[[328,4],[504,3],[710,3]]},"64":{"position":[[84,4],[1767,4],[1896,4]]},"65":{"position":[[68,4]]},"71":{"position":[[1488,3]]},"82":{"position":[[10,3]]},"86":{"position":[[534,3],[1164,3]]},"97":{"position":[[3388,4]]},"101":{"position":[[606,3]]},"104":{"position":[[1299,3]]},"105":{"position":[[33,4]]},"111":{"position":[[592,4]]},"112":{"position":[[40,4]]},"125":{"position":[[4774,3]]},"160":{"position":[[603,3]]},"166":{"position":[[255,3]]},"170":{"position":[[315,3]]},"173":{"position":[[1399,3]]},"176":{"position":[[1063,3]]},"198":{"position":[[104,3]]}},"keywords":{}}],["far.most",{"_index":2334,"title":{},"content":{"58":{"position":[[467,8]]}},"keywords":{}}],["fast",{"_index":2506,"title":{},"content":{"65":{"position":[[741,4]]},"98":{"position":[[634,4]]},"125":{"position":[[11462,4]]},"160":{"position":[[1265,4],[1449,5]]},"164":{"position":[[1490,4]]}},"keywords":{}}],["faster",{"_index":243,"title":{},"content":{"4":{"position":[[536,7]]},"86":{"position":[[1069,6]]},"160":{"position":[[3093,6]]},"172":{"position":[[1268,6]]}},"keywords":{}}],["fastest",{"_index":4629,"title":{},"content":{"159":{"position":[[325,7]]},"170":{"position":[[208,7]]}},"keywords":{}}],["fatal",{"_index":5205,"title":{},"content":{"188":{"position":[[3646,5]]}},"keywords":{}}],["favor.clos",{"_index":1570,"title":{},"content":{"33":{"position":[[315,11]]}},"keywords":{}}],["favoriterust",{"_index":4837,"title":{},"content":{"166":{"position":[[54,12]]}},"keywords":{}}],["fb",{"_index":2889,"title":{},"content":{"88":{"position":[[1745,2],[3161,2],[3274,3],[3340,3]]},"91":{"position":[[1426,2]]}},"keywords":{}}],["fb[datetime(2016",{"_index":3079,"title":{},"content":{"91":{"position":[[549,17]]}},"keywords":{}}],["fb_plot",{"_index":3076,"title":{},"content":{"91":{"position":[[463,7],[525,8]]}},"keywords":{}}],["fb_plot.legend(loc=2",{"_index":3086,"title":{},"content":{"91":{"position":[[849,21]]}},"keywords":{}}],["fb_plot.plot(fb_truncated.index",{"_index":3083,"title":{},"content":{"91":{"position":[[657,32]]}},"keywords":{}}],["fb_plot.set_title('fb",{"_index":3087,"title":{},"content":{"91":{"position":[[871,21]]}},"keywords":{}}],["fb_plot.vlines(date2num(datetime(2016",{"_index":3085,"title":{},"content":{"91":{"position":[[718,38]]}},"keywords":{}}],["fb_truncat",{"_index":3078,"title":{},"content":{"91":{"position":[[534,12]]}},"keywords":{}}],["fb_truncated['close']/2",{"_index":3082,"title":{},"content":{"91":{"position":[[633,23]]}},"keywords":{}}],["fb_truncated['open']/2",{"_index":3081,"title":{},"content":{"91":{"position":[[608,22]]}},"keywords":{}}],["fear",{"_index":5310,"title":{},"content":{"194":{"position":[[154,4]]}},"keywords":{}}],["featur",{"_index":1887,"title":{},"content":{"43":{"position":[[1142,9]]},"44":{"position":[[335,8],[964,9]]},"45":{"position":[[230,8],[384,8]]},"97":{"position":[[23,7]]},"102":{"position":[[512,9],[565,8]]},"127":{"position":[[347,9]]},"130":{"position":[[268,8],[438,7]]},"160":{"position":[[855,8]]},"166":{"position":[[431,9]]},"188":{"position":[[333,9]]}},"keywords":{}}],["feature(alloc",{"_index":4680,"title":{},"content":{"160":{"position":[[1643,18]]}},"keywords":{}}],["features"",{"_index":3494,"title":{},"content":{"102":{"position":[[595,14]]}},"keywords":{}}],["februari",{"_index":2537,"title":{},"content":{"65":{"position":[[2521,8]]}},"keywords":{}}],["feedback",{"_index":3971,"title":{},"content":{"123":{"position":[[179,8],[305,8],[565,8]]}},"keywords":{}}],["feel",{"_index":2250,"title":{"150":{"position":[[11,4]]}},"content":{"53":{"position":[[1153,4],[2096,4],[2137,4]]},"55":{"position":[[83,5]]},"120":{"position":[[509,5]]},"125":{"position":[[1232,4],[2800,4]]},"164":{"position":[[1549,4]]}},"keywords":{}}],["fellow",{"_index":3410,"title":{},"content":{"97":{"position":[[4203,7]]}},"keywords":{}}],["fenc",{"_index":3741,"title":{},"content":{"113":{"position":[[1067,5]]}},"keywords":{}}],["fetch",{"_index":988,"title":{"23":{"position":[[0,8]]}},"content":{"59":{"position":[[220,5]]},"62":{"position":[[231,5]]},"95":{"position":[[68,5]]},"125":{"position":[[3879,7]]}},"keywords":{}}],["fetch_event_data('celg",{"_index":3045,"title":{},"content":{"90":{"position":[[4131,24]]}},"keywords":{}}],["fetch_event_data(tick",{"_index":3019,"title":{},"content":{"90":{"position":[[3179,24]]}},"keywords":{}}],["fetch_ticker('aapl",{"_index":2876,"title":{},"content":{"88":{"position":[[1419,20]]}},"keywords":{}}],["fetch_ticker('fb",{"_index":2890,"title":{},"content":{"88":{"position":[[1750,18]]}},"keywords":{}}],["fetch_ticker(fix",{"_index":3287,"title":{},"content":{"93":{"position":[[4952,19],[5367,19]]}},"keywords":{}}],["fetch_ticker(tick",{"_index":2851,"title":{},"content":{"88":{"position":[[567,20]]},"90":{"position":[[3799,20]]},"93":{"position":[[3982,20]]}},"keywords":{}}],["few",{"_index":1338,"title":{},"content":{"30":{"position":[[552,3],[5716,3]]},"51":{"position":[[2826,3]]},"58":{"position":[[58,3]]},"65":{"position":[[226,3]]},"68":{"position":[[770,3]]},"91":{"position":[[3863,3]]},"150":{"position":[[152,3]]},"173":{"position":[[487,3]]}},"keywords":{}}],["fewer",{"_index":2370,"title":{},"content":{"61":{"position":[[1400,5]]}},"keywords":{}}],["ffmpeg",{"_index":3504,"title":{},"content":{"103":{"position":[[238,7]]}},"keywords":{}}],["fibonacci",{"_index":5166,"title":{},"content":{"188":{"position":[[1227,11],[1414,11],[1527,9]]}},"keywords":{}}],["fibonacci(n",{"_index":5167,"title":{},"content":{"188":{"position":[[1259,12],[1442,12]]}},"keywords":{}}],["fibonacci(unsign",{"_index":5163,"title":{},"content":{"188":{"position":[[989,18]]}},"keywords":{}}],["field",{"_index":3335,"title":{},"content":{"96":{"position":[[1002,5]]},"127":{"position":[[954,6]]}},"keywords":{}}],["fifth",{"_index":2175,"title":{},"content":{"52":{"position":[[316,5],[437,6]]}},"keywords":{}}],["fight",{"_index":2235,"title":{"97":{"position":[[9,8]]}},"content":{"53":{"position":[[906,6]]},"97":{"position":[[409,9],[2520,5]]},"115":{"position":[[3124,8]]}},"keywords":{}}],["figur",{"_index":215,"title":{},"content":{"3":{"position":[[1514,6]]},"30":{"position":[[0,8],[121,7]]},"32":{"position":[[1380,6]]},"64":{"position":[[19,8]]},"65":{"position":[[1351,8],[1533,6],[2225,6]]},"73":{"position":[[213,6]]},"77":{"position":[[192,6]]},"91":{"position":[[2460,6]]},"92":{"position":[[273,6]]},"97":{"position":[[2116,6],[5194,6],[6175,6],[6476,6]]},"100":{"position":[[263,7]]},"122":{"position":[[970,6]]},"125":{"position":[[9993,6]]},"153":{"position":[[40,8]]},"161":{"position":[[443,7]]},"164":{"position":[[1105,6]]},"174":{"position":[[509,7],[743,6]]},"189":{"position":[[1685,6]]},"193":{"position":[[757,6]]},"196":{"position":[[637,6]]}},"keywords":{}}],["figure(title="",{"_index":1270,"title":{},"content":{"28":{"position":[[2079,21],[3734,21]]}},"keywords":{}}],["figure(title='monthli",{"_index":1362,"title":{},"content":{"30":{"position":[[2056,21],[3550,21],[3749,21],[5306,21],[6624,21],[6829,21]]}},"keywords":{}}],["file",{"_index":127,"title":{},"content":{"2":{"position":[[795,4]]},"30":{"position":[[907,5],[8108,4],[8150,4]]},"60":{"position":[[129,5],[191,4]]},"91":{"position":[[1781,4]]},"101":{"position":[[7,5],[31,6],[487,5],[671,4],[732,4],[873,4],[1025,5]]},"102":{"position":[[1402,5]]},"103":{"position":[[215,4]]},"105":{"position":[[2646,5]]},"108":{"position":[[57,5]]},"110":{"position":[[257,5]]},"111":{"position":[[175,4],[250,5],[625,5],[667,6],[740,5],[771,4]]},"112":{"position":[[603,4],[954,4]]},"113":{"position":[[633,4]]},"123":{"position":[[1042,5]]},"125":{"position":[[4013,4],[4675,7],[4832,4],[6614,4],[7147,4],[7543,5],[7790,4],[7878,5]]},"129":{"position":[[2466,4]]},"134":{"position":[[231,4]]},"163":{"position":[[829,6]]},"173":{"position":[[996,5]]},"188":{"position":[[3749,4],[3879,4],[3958,4]]}},"keywords":{}}],["file("schema/point.capnp"",{"_index":3704,"title":{},"content":{"111":{"position":[[406,37]]}},"keywords":{}}],["filetype=csv&filename=iwv_holdings&datatype=fund",{"_index":3250,"title":{},"content":{"93":{"position":[[3112,59]]}},"keywords":{}}],["fill",{"_index":2182,"title":{},"content":{"52":{"position":[[630,4]]},"113":{"position":[[904,7],[1635,4]]},"161":{"position":[[1153,4]]}},"keywords":{}}],["fillstrategiescan",{"_index":5025,"title":{},"content":{"175":{"position":[[1036,17]]}},"keywords":{}}],["filter",{"_index":3110,"title":{},"content":{"91":{"position":[[2005,8]]},"93":{"position":[[4418,8]]},"105":{"position":[[176,7]]}},"keywords":{}}],["filter(lambda",{"_index":3111,"title":{},"content":{"91":{"position":[[2016,13]]},"93":{"position":[[2832,13],[4429,13]]}},"keywords":{}}],["final",{"_index":524,"title":{"12":{"position":[[0,5]]},"26":{"position":[[0,5]]},"176":{"position":[[0,5]]}},"content":{"40":{"position":[[1194,5],[2561,5]]},"44":{"position":[[192,5]]},"57":{"position":[[450,5]]},"65":{"position":[[1445,7],[2183,5]]},"72":{"position":[[615,7]]},"81":{"position":[[11,7]]},"83":{"position":[[422,5]]},"88":{"position":[[126,7]]},"91":{"position":[[5701,8]]},"95":{"position":[[206,8]]},"97":{"position":[[6295,5]]},"98":{"position":[[829,5]]},"113":{"position":[[1742,8]]},"121":{"position":[[2386,8]]},"125":{"position":[[9487,8]]},"128":{"position":[[89,5]]},"143":{"position":[[493,8]]},"153":{"position":[[1,8]]},"155":{"position":[[732,8]]},"160":{"position":[[4348,8]]},"165":{"position":[[924,5]]},"172":{"position":[[2333,8]]},"173":{"position":[[826,8]]},"176":{"position":[[737,5],[1395,8]]},"181":{"position":[[633,8]]},"186":{"position":[[1,8]]},"188":{"position":[[3358,8],[4255,8]]},"189":{"position":[[2857,8]]},"190":{"position":[[812,8]]},"193":{"position":[[1537,5],[1640,8],[2942,8]]},"194":{"position":[[73,7]]},"196":{"position":[[238,7]]},"197":{"position":[[793,5]]}},"keywords":{}}],["final_d1",{"_index":2755,"title":{},"content":{"78":{"position":[[269,9]]}},"keywords":{}}],["final_d2",{"_index":2756,"title":{},"content":{"78":{"position":[[279,8]]}},"keywords":{}}],["final_mean",{"_index":593,"title":{},"content":{"13":{"position":[[1658,10],[1778,10]]},"14":{"position":[[2741,10],[2861,10]]},"15":{"position":[[2415,10],[2535,10]]}},"keywords":{}}],["final_mot",{"_index":529,"title":{},"content":{"12":{"position":[[336,12],[459,12],[517,12]]}},"keywords":{}}],["financi",{"_index":4999,"title":{},"content":{"175":{"position":[[27,9]]}},"keywords":{}}],["find",{"_index":184,"title":{},"content":{"3":{"position":[[983,4]]},"4":{"position":[[507,7]]},"15":{"position":[[530,4]]},"30":{"position":[[7064,4]]},"44":{"position":[[58,4]]},"45":{"position":[[1839,4]]},"51":{"position":[[876,4],[908,4],[2009,4],[2218,4]]},"64":{"position":[[1233,4]]},"65":{"position":[[1281,4]]},"74":{"position":[[1490,4]]},"96":{"position":[[368,4]]},"97":{"position":[[2898,4]]},"102":{"position":[[237,4],[524,4],[753,4]]},"104":{"position":[[125,4],[628,4],[764,4]]},"112":{"position":[[572,4],[681,4],[731,4]]},"122":{"position":[[555,4]]},"129":{"position":[[994,4]]},"160":{"position":[[2271,4]]},"164":{"position":[[655,4]]},"174":{"position":[[1333,7]]}},"keywords":{}}],["fine",{"_index":3450,"title":{},"content":{"98":{"position":[[886,4]]},"112":{"position":[[212,5]]},"120":{"position":[[5,5]]},"129":{"position":[[1664,4]]},"193":{"position":[[123,5]]},"199":{"position":[[1465,4]]}},"keywords":{}}],["finish",{"_index":2246,"title":{},"content":{"53":{"position":[[1097,8]]},"76":{"position":[[3375,8]]},"82":{"position":[[1085,6]]},"116":{"position":[[2816,6]]},"125":{"position":[[10912,6]]},"134":{"position":[[208,9]]},"188":{"position":[[2211,6]]},"190":{"position":[[8,10]]},"193":{"position":[[587,9]]}},"keywords":{}}],["fire",{"_index":4373,"title":{},"content":{"134":{"position":[[120,4]]}},"keywords":{}}],["firefox/46.0",{"_index":3229,"title":{},"content":{"93":{"position":[[2423,13]]}},"keywords":{}}],["firm",{"_index":5000,"title":{},"content":{"175":{"position":[[37,5]]}},"keywords":{}}],["first",{"_index":18,"title":{},"content":{"1":{"position":[[181,5]]},"2":{"position":[[15,5],[233,5]]},"3":{"position":[[1306,5]]},"6":{"position":[[127,6]]},"9":{"position":[[712,5]]},"18":{"position":[[4,5]]},"23":{"position":[[266,5]]},"24":{"position":[[201,5]]},"30":{"position":[[965,5]]},"34":{"position":[[3062,5]]},"38":{"position":[[450,6]]},"40":{"position":[[590,6],[905,5],[2148,5]]},"43":{"position":[[1,5]]},"44":{"position":[[4,5],[459,5]]},"51":{"position":[[70,6],[350,6],[400,5],[869,6],[2863,5]]},"52":{"position":[[153,5],[461,5],[574,5],[751,5],[920,5],[936,5]]},"53":{"position":[[467,5],[1181,5],[1277,5],[1993,6]]},"57":{"position":[[349,5]]},"61":{"position":[[1428,6]]},"64":{"position":[[5,5],[206,6],[1227,5]]},"65":{"position":[[265,5],[1508,6]]},"68":{"position":[[4,5],[198,5]]},"74":{"position":[[341,5]]},"85":{"position":[[75,5]]},"88":{"position":[[220,5]]},"90":{"position":[[478,5]]},"91":{"position":[[5,5],[1808,5]]},"93":{"position":[[4539,5]]},"96":{"position":[[1054,5]]},"97":{"position":[[1261,5]]},"100":{"position":[[384,5]]},"103":{"position":[[184,5],[930,6],[1580,6]]},"104":{"position":[[936,6]]},"106":{"position":[[179,5]]},"110":{"position":[[183,6]]},"112":{"position":[[1227,6]]},"115":{"position":[[6,5],[2890,6]]},"121":{"position":[[1148,5]]},"123":{"position":[[719,6]]},"125":{"position":[[3318,5],[3664,6],[4109,5],[5065,5],[10577,5]]},"127":{"position":[[357,6]]},"128":{"position":[[4,5]]},"129":{"position":[[2590,5]]},"132":{"position":[[8,5],[292,5]]},"136":{"position":[[752,5]]},"152":{"position":[[5,5]]},"155":{"position":[[5,5]]},"161":{"position":[[573,6]]},"164":{"position":[[76,5]]},"165":{"position":[[506,6]]},"173":{"position":[[506,6]]},"176":{"position":[[768,6],[860,5],[1528,5]]},"179":{"position":[[5,5],[988,5],[1488,5]]},"188":{"position":[[1457,6],[2328,5],[2960,5],[3251,5],[3741,7],[4076,6]]},"189":{"position":[[269,5],[1678,6],[2327,6],[2620,5]]},"190":{"position":[[134,6]]},"192":{"position":[[25,6],[234,5]]},"198":{"position":[[69,6]]}},"keywords":{}}],["first_word",{"_index":2084,"title":{},"content":{"51":{"position":[[519,11]]}},"keywords":{}}],["first_word_dist",{"_index":2088,"title":{},"content":{"51":{"position":[[619,15]]}},"keywords":{}}],["first_word_dist.reset_index()['index",{"_index":2162,"title":{},"content":{"51":{"position":[[4031,39]]}},"keywords":{}}],["first_words[first_words.str.isalpha",{"_index":2087,"title":{},"content":{"51":{"position":[[580,38]]}},"keywords":{}}],["first_words_alpha",{"_index":2086,"title":{},"content":{"51":{"position":[[560,17]]}},"keywords":{}}],["first_words_alpha.value_count",{"_index":2089,"title":{},"content":{"51":{"position":[[637,32]]}},"keywords":{}}],["fit",{"_index":1982,"title":{},"content":{"45":{"position":[[1357,3]]},"82":{"position":[[1256,3]]}},"keywords":{}}],["fitbit",{"_index":2311,"title":{},"content":{"57":{"position":[[188,6]]},"59":{"position":[[1,6]]},"60":{"position":[[53,7]]},"61":{"position":[[320,7],[453,7],[534,7],[656,7],[734,7],[2208,6]]},"62":{"position":[[211,6]]}},"keywords":{}}],["fitbit_uri",{"_index":2373,"title":{},"content":{"61":{"position":[[1514,10],[1781,10]]}},"keywords":{}}],["five",{"_index":2170,"title":{},"content":{"52":{"position":[[119,4]]}},"keywords":{}}],["five_day_ev",{"_index":3142,"title":{},"content":{"91":{"position":[[3357,15],[3657,15],[4129,15]]}},"keywords":{}}],["five_day_events[1",{"_index":3153,"title":{},"content":{"91":{"position":[[4147,21]]}},"keywords":{}}],["fix",{"_index":2544,"title":{"191":{"position":[[21,5]]}},"content":{"66":{"position":[[387,5]]},"91":{"position":[[3826,5]]},"93":{"position":[[4791,5],[5206,5]]},"97":{"position":[[5618,3]]},"98":{"position":[[845,5]]},"140":{"position":[[114,5]]},"159":{"position":[[421,5],[497,5]]},"160":{"position":[[2847,5]]},"164":{"position":[[1358,7]]},"175":{"position":[[1635,5]]},"180":{"position":[[264,5]]}},"keywords":{}}],["fi−1,if_{i",{"_index":469,"title":{},"content":{"9":{"position":[[488,10]]}},"keywords":{}}],["flac",{"_index":3471,"title":{},"content":{"101":{"position":[[373,5]]},"103":{"position":[[210,4]]}},"keywords":{}}],["flag",{"_index":4722,"title":{},"content":{"160":{"position":[[4379,4]]},"194":{"position":[[525,5]]}},"keywords":{}}],["flamegraph",{"_index":4377,"title":{"135":{"position":[[8,12]]}},"content":{},"keywords":{}}],["flatbuff",{"_index":4819,"title":{"165":{"position":[[0,12]]}},"content":{"165":{"position":[[112,11],[246,11],[347,12],[513,11],[1065,11],[1203,11],[1410,12]]},"166":{"position":[[342,11]]},"168":{"position":[[288,11]]},"169":{"position":[[401,11]]}},"keywords":{}}],["flexibl",{"_index":4192,"title":{},"content":{"125":{"position":[[9798,12]]},"165":{"position":[[303,12]]}},"keywords":{}}],["fli",{"_index":4925,"title":{},"content":{"172":{"position":[[1792,3]]}},"keywords":{}}],["flip",{"_index":1131,"title":{},"content":{"24":{"position":[[3243,5]]},"26":{"position":[[107,4],[259,4]]}},"keywords":{}}],["float",{"_index":3584,"title":{},"content":{"105":{"position":[[684,8],[733,7]]},"127":{"position":[[235,5]]}},"keywords":{}}],["float(str",{"_index":948,"title":{},"content":{"22":{"position":[[1667,14]]}},"keywords":{}}],["floor",{"_index":2214,"title":{},"content":{"53":{"position":[[500,5]]}},"keywords":{}}],["flounder",{"_index":133,"title":{"3":{"position":[[0,11]]}},"content":{},"keywords":{}}],["flow",{"_index":5015,"title":{},"content":{"175":{"position":[[634,4]]}},"keywords":{}}],["flung",{"_index":4658,"title":{},"content":{"160":{"position":[[607,5]]}},"keywords":{}}],["fn",{"_index":3327,"title":{},"content":{"96":{"position":[[653,2],[1072,2],[1602,2],[2148,2]]},"97":{"position":[[1460,2],[3635,2]]},"111":{"position":[[324,2]]},"113":{"position":[[726,2]]},"115":{"position":[[109,2]]},"116":{"position":[[209,2]]},"117":{"position":[[1001,2]]},"128":{"position":[[1106,2],[1132,2]]},"129":{"position":[[418,2],[1464,2],[1530,2]]},"136":{"position":[[267,2]]},"140":{"position":[[1,2]]},"141":{"position":[[1,2]]},"142":{"position":[[1,2]]},"144":{"position":[[174,2],[280,2]]},"145":{"position":[[138,2]]},"146":{"position":[[166,2]]},"147":{"position":[[189,2],[314,2]]},"152":{"position":[[470,2],[1106,2],[1320,2],[1485,2]]},"153":{"position":[[747,2]]},"155":{"position":[[1343,2],[1406,2],[1467,2],[1530,2]]},"156":{"position":[[627,2],[916,2],[1403,2],[1568,2]]},"163":{"position":[[1741,2]]},"178":{"position":[[646,2]]},"179":{"position":[[387,2],[565,2],[907,2],[973,2],[1281,2]]},"180":{"position":[[422,2]]},"181":{"position":[[102,2],[218,2]]},"183":{"position":[[327,2],[467,2]]},"184":{"position":[[311,2],[448,2],[556,2],[651,2],[684,2],[820,2],[925,3]]},"186":{"position":[[334,2]]},"192":{"position":[[188,2]]},"193":{"position":[[1052,2],[1742,2],[2456,2],[2697,2],[3231,2],[3532,2]]},"194":{"position":[[303,2]]},"195":{"position":[[635,2]]},"196":{"position":[[937,2],[1145,2],[1527,2],[1738,2]]},"197":{"position":[[308,2],[437,2],[586,2],[932,2],[1151,2]]},"199":{"position":[[1235,2],[1372,2],[1528,2]]}},"keywords":{}}],["fn(&mut",{"_index":3373,"title":{},"content":{"97":{"position":[[1500,11]]}},"keywords":{}}],["fnonc",{"_index":5333,"title":{},"content":{"196":{"position":[[961,8]]}},"keywords":{}}],["focu",{"_index":230,"title":{},"content":{"4":{"position":[[184,5],[1439,5]]},"92":{"position":[[173,5]]},"135":{"position":[[51,5]]},"160":{"position":[[580,5],[3412,5]]},"161":{"position":[[488,5]]},"176":{"position":[[1503,5]]}},"keywords":{}}],["folder",{"_index":144,"title":{},"content":{"3":{"position":[[245,6]]},"111":{"position":[[224,6]]},"112":{"position":[[674,6]]}},"keywords":{}}],["follow",{"_index":316,"title":{},"content":{"6":{"position":[[264,9]]},"9":{"position":[[392,7]]},"13":{"position":[[111,9]]},"14":{"position":[[251,9],[1222,9]]},"30":{"position":[[8117,9]]},"32":{"position":[[451,9]]},"49":{"position":[[45,9],[346,8],[387,8],[530,6]]},"51":{"position":[[3160,7]]},"71":{"position":[[162,9]]},"74":{"position":[[463,7]]},"75":{"position":[[117,8]]},"90":{"position":[[5106,9],[5202,9],[5283,9]]},"91":{"position":[[248,9],[5920,6]]},"102":{"position":[[470,8],[968,8]]},"108":{"position":[[831,9]]},"109":{"position":[[204,9]]},"110":{"position":[[401,9]]},"111":{"position":[[271,9]]},"112":{"position":[[1030,9]]},"122":{"position":[[454,6]]},"123":{"position":[[97,9]]},"156":{"position":[[1790,6]]},"165":{"position":[[612,10]]}},"keywords":{}}],["font",{"_index":945,"title":{},"content":{"22":{"position":[[1618,6]]}},"keywords":{}}],["fontsize=18",{"_index":1795,"title":{},"content":{"40":{"position":[[383,13],[540,13],[1917,13],[2076,13],[2860,13],[3020,13]]}},"keywords":{}}],["food",{"_index":2240,"title":{},"content":{"53":{"position":[[980,4]]}},"keywords":{}}],["fool",{"_index":4338,"title":{},"content":{"130":{"position":[[525,4]]}},"keywords":{}}],["foot",{"_index":3889,"title":{},"content":{"121":{"position":[[950,4]]}},"keywords":{}}],["for<'r",{"_index":3380,"title":{},"content":{"97":{"position":[[1865,11]]}},"keywords":{}}],["forc",{"_index":3418,"title":{},"content":{"97":{"position":[[4676,5],[5944,6]]},"98":{"position":[[747,7],[1071,6]]},"104":{"position":[[851,6],[1400,5]]},"122":{"position":[[920,6]]},"152":{"position":[[929,7]]},"156":{"position":[[194,6]]},"189":{"position":[[1510,5]]}},"keywords":{}}],["fordtlb_load_misses.miss_causes_a_walk",{"_index":5047,"title":{},"content":{"176":{"position":[[692,39]]}},"keywords":{}}],["forecast",{"_index":1429,"title":{},"content":{"30":{"position":[[7426,8],[8099,8],[9967,8],[10358,8]]},"89":{"position":[[310,8]]}},"keywords":{}}],["forecast.io",{"_index":1345,"title":{},"content":{"30":{"position":[[794,12]]}},"keywords":{}}],["forecast_bas",{"_index":1468,"title":{},"content":{"30":{"position":[[8790,13],[8875,13],[8969,13]]}},"keywords":{}}],["forecast_df",{"_index":1352,"title":{},"content":{"30":{"position":[[1257,11]]}},"keywords":{}}],["forecast_df['cari",{"_index":1354,"title":{},"content":{"30":{"position":[[1326,19]]}},"keywords":{}}],["forecasts_df",{"_index":1229,"title":{},"content":{"28":{"position":[[925,12]]}},"keywords":{}}],["foreword",{"_index":4644,"title":{"160":{"position":[[21,8]]}},"content":{},"keywords":{}}],["forextern",{"_index":5222,"title":{},"content":{"188":{"position":[[4287,11]]}},"keywords":{}}],["forg",{"_index":4132,"title":{},"content":{"125":{"position":[[6281,6],[6864,5]]}},"keywords":{}}],["forgot",{"_index":4752,"title":{},"content":{"161":{"position":[[1229,6]]}},"keywords":{}}],["form",{"_index":3334,"title":{},"content":{"96":{"position":[[937,5]]},"197":{"position":[[34,6]]}},"keywords":{}}],["formal",{"_index":4723,"title":{},"content":{"160":{"position":[[4504,8]]}},"keywords":{}}],["format",{"_index":2736,"title":{"162":{"position":[[7,6]]}},"content":{"76":{"position":[[2558,11]]},"96":{"position":[[1981,8],[2127,10]]},"101":{"position":[[360,7],[564,7]]},"108":{"position":[[97,6]]},"110":{"position":[[597,7]]},"120":{"position":[[341,7]]},"121":{"position":[[1753,6]]},"125":{"position":[[7933,6]]},"163":{"position":[[135,7],[314,6],[2189,7],[2320,8]]},"164":{"position":[[82,6],[1169,6]]},"165":{"position":[[288,6],[595,7]]},"166":{"position":[[201,6],[279,7],[828,7]]},"167":{"position":[[286,6]]},"168":{"position":[[108,6]]},"169":{"position":[[182,7],[243,6]]},"170":{"position":[[341,7]]}},"keywords":{}}],["format!("y",{"_index":3353,"title":{},"content":{"96":{"position":[[2252,17]]}},"keywords":{}}],["format(horizon,five_day_events.shape[0",{"_index":3156,"title":{},"content":{"91":{"position":[[4249,42]]}},"keywords":{}}],["format(i",{"_index":906,"title":{},"content":{"22":{"position":[[726,15]]}},"keywords":{}}],["format(lat",{"_index":1470,"title":{},"content":{"30":{"position":[[8900,20],[8994,23]]}},"keywords":{}}],["format(tick",{"_index":3232,"title":{},"content":{"93":{"position":[[2538,15]]}},"keywords":{}}],["format_str",{"_index":2407,"title":{},"content":{"62":{"position":[[546,10]]}},"keywords":{}}],["formul",{"_index":2943,"title":{"89":{"position":[[0,11]]}},"content":{},"keywords":{}}],["formula",{"_index":1527,"title":{"37":{"position":[[35,7]]}},"content":{"32":{"position":[[712,7],[789,8],[983,7],[1066,7]]},"33":{"position":[[36,7]]},"34":{"position":[[196,7],[385,7]]},"38":{"position":[[5,7],[242,7]]}},"keywords":{}}],["formula,w",{"_index":1591,"title":{},"content":{"34":{"position":[[42,10]]}},"keywords":{}}],["forth",{"_index":4337,"title":{},"content":{"130":{"position":[[515,5]]}},"keywords":{}}],["forward",{"_index":277,"title":{},"content":{"4":{"position":[[1056,7]]},"9":{"position":[[199,7],[321,7],[529,7]]},"11":{"position":[[226,7]]},"12":{"position":[[260,7]]},"63":{"position":[[168,8]]},"65":{"position":[[746,7]]},"91":{"position":[[2926,7]]},"92":{"position":[[738,7]]},"106":{"position":[[1138,7]]},"124":{"position":[[830,7]]},"161":{"position":[[1653,7]]},"175":{"position":[[1530,10]]}},"keywords":{}}],["forward"",{"_index":5028,"title":{},"content":{"175":{"position":[[1142,13]]}},"keywords":{}}],["forward[i",{"_index":531,"title":{},"content":{"12":{"position":[[378,11]]}},"keywords":{}}],["forward_structur",{"_index":566,"title":{},"content":{"13":{"position":[[695,18],[1094,17],[1242,18]]},"14":{"position":[[1552,18],[2128,17],[2303,18]]},"15":{"position":[[923,18],[1796,17],[1973,18]]}},"keywords":{}}],["forward_term",{"_index":471,"title":{},"content":{"9":{"position":[[544,12]]}},"keywords":{}}],["forward_term(term",{"_index":501,"title":{},"content":{"10":{"position":[[419,18]]},"12":{"position":[[284,19]]},"13":{"position":[[1114,18]]},"14":{"position":[[2148,18]]},"15":{"position":[[1816,18]]}},"keywords":{}}],["forward_yield",{"_index":500,"title":{},"content":{"10":{"position":[[403,13]]},"11":{"position":[[389,14]]}},"keywords":{}}],["forward_yield[1",{"_index":503,"title":{},"content":{"10":{"position":[[467,16]]}},"keywords":{}}],["found",{"_index":1988,"title":{},"content":{"45":{"position":[[1789,5]]},"96":{"position":[[767,5],[1186,5],[1724,5],[2270,5]]},"122":{"position":[[602,5]]},"125":{"position":[[8524,6],[8992,6]]},"160":{"position":[[4048,5]]},"193":{"position":[[559,5]]}},"keywords":{}}],["foundat",{"_index":311,"title":{},"content":{"6":{"position":[[151,10]]},"128":{"position":[[26,10]]}},"keywords":{}}],["four",{"_index":2512,"title":{},"content":{"65":{"position":[[1101,4],[1211,4]]},"91":{"position":[[1455,4]]},"115":{"position":[[899,4]]}},"keywords":{}}],["four_year_period",{"_index":2507,"title":{},"content":{"65":{"position":[[811,17],[898,17]]}},"keywords":{}}],["fourth",{"_index":2173,"title":{},"content":{"52":{"position":[[275,6],[429,7]]}},"keywords":{}}],["frac{1}{o_i",{"_index":1554,"title":{},"content":{"32":{"position":[[1891,14]]}},"keywords":{}}],["frac{c_n",{"_index":1548,"title":{},"content":{"32":{"position":[[1752,10]]}},"keywords":{}}],["frac{c_nd_i}{o_i",{"_index":1547,"title":{},"content":{"32":{"position":[[1726,21]]}},"keywords":{}}],["frac{c_nd_n}{o_n",{"_index":1542,"title":{},"content":{"32":{"position":[[1611,18],[1668,18]]}},"keywords":{}}],["frac{c_n}{o_i",{"_index":1551,"title":{},"content":{"32":{"position":[[1811,18]]}},"keywords":{}}],["frac{d_i}{o_i",{"_index":1531,"title":{},"content":{"32":{"position":[[838,15],[1593,15]]}},"keywords":{}}],["frac{o_n}{c_n",{"_index":1552,"title":{},"content":{"32":{"position":[[1844,14]]}},"keywords":{}}],["fragment",{"_index":4147,"title":{},"content":{"125":{"position":[[7441,10]]}},"keywords":{}}],["frame",{"_index":510,"title":{},"content":{"11":{"position":[[151,6]]},"28":{"position":[[1116,5],[1142,6],[2906,5],[2939,6]]},"30":{"position":[[1488,5],[1514,6],[4751,5],[4784,6]]},"121":{"position":[[1314,7]]}},"keywords":{}}],["frame.iloc[i",{"_index":1033,"title":{},"content":{"24":{"position":[[631,12]]}},"keywords":{}}],["frame.iloc[i].nam",{"_index":1031,"title":{},"content":{"24":{"position":[[598,18]]},"25":{"position":[[323,18]]}},"keywords":{}}],["frame.iloc[i]['clos",{"_index":1139,"title":{},"content":{"25":{"position":[[387,22]]}},"keywords":{}}],["frame.iloc[i]['open",{"_index":1036,"title":{},"content":{"24":{"position":[[667,21]]},"25":{"position":[[353,21]]}},"keywords":{}}],["frame['cloudcov",{"_index":1238,"title":{},"content":{"28":{"position":[[1156,19]]},"30":{"position":[[1528,19]]}},"keywords":{}}],["frame['precipprob",{"_index":1297,"title":{},"content":{"28":{"position":[[2953,26]]},"30":{"position":[[4798,26]]}},"keywords":{}}],["frames,130",{"_index":3903,"title":{},"content":{"121":{"position":[[1547,10]]}},"keywords":{}}],["framework",{"_index":186,"title":{},"content":{"3":{"position":[[1024,10],[1075,11],[1438,9]]},"4":{"position":[[892,10],[1136,11],[1210,9]]},"125":{"position":[[9743,9]]}},"keywords":{}}],["frameworks"",{"_index":4158,"title":{},"content":{"125":{"position":[[8248,17]]}},"keywords":{}}],["frank",{"_index":5105,"title":{},"content":{"181":{"position":[[963,6]]}},"keywords":{}}],["freak",{"_index":1844,"title":{},"content":{"40":{"position":[[3662,6]]},"53":{"position":[[826,8]]},"121":{"position":[[1406,7]]}},"keywords":{}}],["free",{"_index":3502,"title":{},"content":{"103":{"position":[[70,5]]},"121":{"position":[[2012,5]]},"125":{"position":[[2805,4]]},"133":{"position":[[396,5]]},"160":{"position":[[567,5]]},"173":{"position":[[354,4]]},"188":{"position":[[2380,4]]},"190":{"position":[[163,4],[231,4]]}},"keywords":{}}],["free"",{"_index":3453,"title":{},"content":{"98":{"position":[[998,10]]}},"keywords":{}}],["free/xxvii/01",{"_index":3509,"title":{},"content":{"103":{"position":[[294,13]]}},"keywords":{}}],["freez",{"_index":4907,"title":{},"content":{"172":{"position":[[514,6]]}},"keywords":{}}],["freq='d",{"_index":1242,"title":{},"content":{"28":{"position":[[1342,9],[3142,9]]},"30":{"position":[[1708,9],[3057,9],[4981,9],[6125,9]]}},"keywords":{}}],["freq='min",{"_index":2432,"title":{},"content":{"62":{"position":[[1399,11]]}},"keywords":{}}],["frequenc",{"_index":1891,"title":{},"content":{"43":{"position":[[1369,9]]},"104":{"position":[[513,9],[1260,9],[1338,9],[1516,9],[1553,9],[1767,9],[1825,9]]}},"keywords":{}}],["frequency"",{"_index":3555,"title":{},"content":{"104":{"position":[[359,15],[1185,15]]}},"keywords":{}}],["frequent",{"_index":2568,"title":{},"content":{"68":{"position":[[736,8]]},"174":{"position":[[1155,10]]}},"keywords":{}}],["friday",{"_index":3025,"title":{},"content":{"90":{"position":[[3495,6]]}},"keywords":{}}],["friend",{"_index":2180,"title":{},"content":{"52":{"position":[[482,7]]},"130":{"position":[[535,7]]},"173":{"position":[[1324,6]]}},"keywords":{}}],["frivol",{"_index":4659,"title":{},"content":{"160":{"position":[[618,9]]}},"keywords":{}}],["from=start",{"_index":1626,"title":{},"content":{"34":{"position":[[1671,11]]}},"keywords":{}}],["fromiex",{"_index":4762,"title":{},"content":{"163":{"position":[[87,8]]}},"keywords":{}}],["front",{"_index":4834,"title":{},"content":{"165":{"position":[[1240,5]]}},"keywords":{}}],["frustrat",{"_index":3391,"title":{},"content":{"97":{"position":[[2210,10]]},"115":{"position":[[2713,12]]}},"keywords":{}}],["fs",{"_index":3261,"title":{},"content":{"93":{"position":[[3397,2]]}},"keywords":{}}],["fs[futur",{"_index":3269,"title":{},"content":{"93":{"position":[[3628,10]]}},"keywords":{}}],["full",{"_index":507,"title":{"11":{"position":[[4,4]]}},"content":{"11":{"position":[[134,4]]},"12":{"position":[[43,4]]},"20":{"position":[[855,4]]},"61":{"position":[[1905,4],[2192,4]]},"104":{"position":[[307,4]]}},"keywords":{}}],["full_daterang",{"_index":2429,"title":{},"content":{"62":{"position":[[1321,14]]}},"keywords":{}}],["full_mot",{"_index":515,"title":{},"content":{"11":{"position":[[336,11],[500,11]]}},"keywords":{}}],["full_simul",{"_index":527,"title":{},"content":{"12":{"position":[[214,15]]}},"keywords":{}}],["full_simulation(s0",{"_index":535,"title":{},"content":{"12":{"position":[[540,19]]},"13":{"position":[[1321,19]]},"14":{"position":[[2393,19]]},"15":{"position":[[2065,19]]}},"keywords":{}}],["full_term",{"_index":516,"title":{},"content":{"11":{"position":[[363,9]]}},"keywords":{}}],["full_term[i",{"_index":519,"title":{},"content":{"11":{"position":[[418,13]]}},"keywords":{}}],["fulli",{"_index":2969,"title":{},"content":{"90":{"position":[[499,5]]},"98":{"position":[[761,5]]},"104":{"position":[[37,5]]}},"keywords":{}}],["fun",{"_index":294,"title":{},"content":{"4":{"position":[[1428,4]]},"20":{"position":[[2046,6],[2087,6],[2136,6],[2177,6]]},"50":{"position":[[94,3]]},"51":{"position":[[1512,3]]},"86":{"position":[[954,4]]},"100":{"position":[[330,3]]},"125":{"position":[[420,3]]},"163":{"position":[[2453,4]]}},"keywords":{}}],["function",{"_index":53,"title":{"74":{"position":[[24,9]]},"146":{"position":[[6,8]]},"193":{"position":[[0,8]]}},"content":{"1":{"position":[[603,8]]},"7":{"position":[[530,8]]},"8":{"position":[[60,9]]},"13":{"position":[[1270,10]]},"14":{"position":[[2342,10]]},"15":{"position":[[2014,10]]},"38":{"position":[[707,8],[1243,8]]},"73":{"position":[[760,8],[911,9]]},"74":{"position":[[26,9],[1239,8]]},"75":{"position":[[47,8],[636,8]]},"76":{"position":[[32,9]]},"85":{"position":[[437,8]]},"86":{"position":[[825,8]]},"97":{"position":[[1142,9],[1283,8],[1312,10],[1372,8],[1435,8],[1655,8],[1695,8],[2373,8],[2665,8],[3101,10],[3292,8],[4300,8],[4349,9],[4385,8],[4566,9],[4629,8],[6027,8],[6354,10]]},"98":{"position":[[55,13]]},"103":{"position":[[1524,9]]},"105":{"position":[[371,8]]},"113":{"position":[[2441,11]]},"120":{"position":[[830,8]]},"121":{"position":[[1213,14],[2343,9]]},"125":{"position":[[4215,8]]},"127":{"position":[[1495,8]]},"128":{"position":[[1657,12],[1826,10],[1932,8]]},"129":{"position":[[844,8],[1019,8],[1067,8],[1131,8],[1261,9],[1298,8],[1693,8],[1812,9],[1875,8]]},"135":{"position":[[206,9],[289,9],[378,9]]},"141":{"position":[[372,9]]},"144":{"position":[[37,8]]},"147":{"position":[[111,10],[414,8]]},"150":{"position":[[358,11]]},"153":{"position":[[287,8]]},"157":{"position":[[229,14]]},"160":{"position":[[589,13]]},"173":{"position":[[303,14]]},"181":{"position":[[493,10]]},"188":{"position":[[394,8],[773,8],[851,8],[1426,8],[2792,8],[4089,9],[4418,9],[4531,10]]},"189":{"position":[[260,8],[331,8],[500,9],[671,8],[1493,8],[1718,8],[2985,9]]},"190":{"position":[[236,9]]},"193":{"position":[[28,9],[188,9],[420,8],[574,8],[786,10],[1725,10],[2007,8],[2074,9],[2280,8]]},"195":{"position":[[718,8]]},"196":{"position":[[25,9],[379,10],[457,10],[488,9],[807,9],[1054,9],[1362,9],[1473,12]]},"197":{"position":[[763,8],[1102,8]]},"199":{"position":[[441,9],[686,8],[720,8]]}},"keywords":{}}],["function(current_open",{"_index":1604,"title":{},"content":{"34":{"position":[[1066,22]]}},"keywords":{}}],["function(current_pric",{"_index":1620,"title":{},"content":{"34":{"position":[[1424,23]]}},"keywords":{}}],["function(initial_pric",{"_index":564,"title":{},"content":{"13":{"position":[[616,23]]},"14":{"position":[[1457,23]]},"15":{"position":[[828,23]]}},"keywords":{}}],["function(invest",{"_index":1644,"title":{},"content":{"34":{"position":[[2712,21]]}},"keywords":{}}],["function(nam",{"_index":1622,"title":{},"content":{"34":{"position":[[1597,14]]}},"keywords":{}}],["function(s0",{"_index":388,"title":{},"content":{"7":{"position":[[277,12]]},"12":{"position":[[232,12]]}},"keywords":{}}],["function(yearly_term",{"_index":472,"title":{},"content":{"9":{"position":[[559,21]]}},"keywords":{}}],["functioncompil",{"_index":3917,"title":{},"content":{"121":{"position":[[2142,15]]}},"keywords":{}}],["functool",{"_index":1446,"title":{},"content":{"30":{"position":[[8343,9]]},"51":{"position":[[1066,9]]}},"keywords":{}}],["fundament",{"_index":2029,"title":{},"content":{"46":{"position":[[70,11],[287,13]]},"63":{"position":[[3,11]]},"101":{"position":[[768,11]]},"125":{"position":[[9634,11]]},"198":{"position":[[535,14]]}},"keywords":{}}],["further",{"_index":1412,"title":{"55":{"position":[[4,7]]}},"content":{"30":{"position":[[5685,7]]},"43":{"position":[[164,7]]},"90":{"position":[[23,8]]},"160":{"position":[[3397,8]]},"189":{"position":[[596,8]]}},"keywords":{}}],["futur",{"_index":874,"title":{"22":{"position":[[12,7]]}},"content":{"22":{"position":[[1165,7]]},"23":{"position":[[22,7]]},"24":{"position":[[69,7],[231,6],[315,7],[1883,7],[2033,8],[2107,6],[2117,8],[2146,8],[2192,6],[2202,8],[2236,8],[2286,6],[2296,8],[2953,7],[3282,7],[3406,7]]},"25":{"position":[[1607,7],[1757,8],[1831,6],[1841,8],[1870,8],[1916,6],[1926,8],[1960,8],[2010,6],[2020,8],[2635,7]]},"26":{"position":[[65,7],[394,7],[444,7],[737,7]]},"30":{"position":[[8261,6]]},"38":{"position":[[1007,7],[1269,7]]},"39":{"position":[[1816,6]]},"91":{"position":[[2943,6]]},"92":{"position":[[755,6]]},"93":{"position":[[1437,7],[3588,6]]},"98":{"position":[[147,7],[197,6]]},"106":{"position":[[1185,7]]},"125":{"position":[[3251,6]]},"148":{"position":[[466,7]]},"158":{"position":[[490,6]]},"160":{"position":[[4394,6]]},"161":{"position":[[1684,7]]},"173":{"position":[[2089,6]]},"184":{"position":[[1224,6]]}},"keywords":{}}],["future<item=vec<u8>",{"_index":4475,"title":{},"content":{"147":{"position":[[220,29]]}},"keywords":{}}],["future.result",{"_index":3272,"title":{},"content":{"93":{"position":[[3714,18]]}},"keywords":{}}],["futures.as_completed(f",{"_index":3268,"title":{},"content":{"93":{"position":[[3598,25]]}},"keywords":{}}],["futures.threadpoolexecutor(max_workers=8",{"_index":3259,"title":{},"content":{"93":{"position":[[3346,41]]}},"keywords":{}}],["futures::future::futur",{"_index":4472,"title":{},"content":{"147":{"position":[[127,24]]}},"keywords":{}}],["futures::future::ok",{"_index":4473,"title":{},"content":{"147":{"position":[[156,20]]}},"keywords":{}}],["g1",{"_index":4906,"title":{},"content":{"172":{"position":[[500,2]]}},"keywords":{}}],["gain",{"_index":2361,"title":{},"content":{"61":{"position":[[948,4]]}},"keywords":{}}],["game",{"_index":2619,"title":{},"content":{"72":{"position":[[687,5]]},"139":{"position":[[951,5]]}},"keywords":{}}],["gap",{"_index":2183,"title":{},"content":{"52":{"position":[[639,3]]}},"keywords":{}}],["garbag",{"_index":3445,"title":{},"content":{"98":{"position":[[575,7]]},"132":{"position":[[159,7]]},"172":{"position":[[1,7],[36,7]]},"176":{"position":[[467,7]]},"199":{"position":[[579,7]]}},"keywords":{}}],["garden",{"_index":4756,"title":{},"content":{"161":{"position":[[1486,6]]}},"keywords":{}}],["gatsbi",{"_index":283,"title":{},"content":{"4":{"position":[[1160,6]]}},"keywords":{}}],["gaug",{"_index":1381,"title":{},"content":{"30":{"position":[[2869,5]]}},"keywords":{}}],["gaussian",{"_index":1978,"title":{},"content":{"45":{"position":[[1232,8],[1653,8]]}},"keywords":{}}],["gaussiannb",{"_index":1990,"title":{},"content":{"45":{"position":[[1933,10],[2109,12],[2889,12]]}},"keywords":{}}],["gave",{"_index":187,"title":{},"content":{"3":{"position":[[1037,4]]},"97":{"position":[[2582,4]]},"113":{"position":[[2003,4]]},"132":{"position":[[766,4]]},"174":{"position":[[72,4],[122,4]]}},"keywords":{}}],["gbm",{"_index":385,"title":{},"content":{"7":{"position":[[227,3]]}},"keywords":{}}],["gc",{"_index":4905,"title":{},"content":{"172":{"position":[[486,2],[1118,2]]}},"keywords":{}}],["gc_threshold",{"_index":4899,"title":{},"content":{"172":{"position":[[250,12]]}},"keywords":{}}],["ge",{"_index":783,"title":{},"content":{"20":{"position":[[671,3]]}},"keywords":{}}],["gecko/20100101",{"_index":3228,"title":{},"content":{"93":{"position":[[2407,15]]}},"keywords":{}}],["gener",{"_index":764,"title":{"197":{"position":[[0,9]]}},"content":{"20":{"position":[[187,8]]},"24":{"position":[[3132,7]]},"30":{"position":[[952,8],[2350,9],[8084,10],[8136,9]]},"64":{"position":[[267,10]]},"74":{"position":[[249,7]]},"75":{"position":[[384,8]]},"89":{"position":[[300,9]]},"90":{"position":[[3992,8],[5194,7]]},"104":{"position":[[1681,8]]},"106":{"position":[[169,8]]},"108":{"position":[[133,10]]},"109":{"position":[[501,9]]},"111":{"position":[[82,9]]},"112":{"position":[[111,9],[245,9],[339,9],[464,9],[1210,9]]},"113":{"position":[[64,8],[831,7],[1939,7],[2138,7]]},"121":{"position":[[1105,8]]},"125":{"position":[[6713,9]]},"128":{"position":[[392,10],[1191,9],[1630,9]]},"141":{"position":[[308,9]]},"155":{"position":[[289,7]]},"172":{"position":[[195,10],[335,12]]},"190":{"position":[[680,9]]},"197":{"position":[[823,9]]},"199":{"position":[[1128,10]]}},"keywords":{}}],["generator"",{"_index":4767,"title":{},"content":{"163":{"position":[[649,16]]}},"keywords":{}}],["genuin",{"_index":254,"title":{},"content":{"4":{"position":[[722,7]]}},"keywords":{}}],["geom.lin",{"_index":439,"title":{},"content":{"7":{"position":[[1244,10]]}},"keywords":{}}],["get",{"_index":481,"title":{"59":{"position":[[0,7]]}},"content":{"10":{"position":[[66,7]]},"30":{"position":[[9119,7]]},"65":{"position":[[2143,4]]},"66":{"position":[[462,4]]},"91":{"position":[[5752,7]]},"95":{"position":[[532,7]]},"97":{"position":[[2499,7],[4791,7]]},"102":{"position":[[788,4]]},"115":{"position":[[2630,7]]},"121":{"position":[[1364,7]]},"123":{"position":[[973,7]]},"181":{"position":[[642,7]]},"183":{"position":[[436,4],[582,4]]},"188":{"position":[[76,4]]},"196":{"position":[[1372,7]]}},"keywords":{}}],["get_forecast(*loc",{"_index":1492,"title":{},"content":{"30":{"position":[[9862,18]]}},"keywords":{}}],["get_forecast(lat",{"_index":1465,"title":{},"content":{"30":{"position":[[8754,17]]}},"keywords":{}}],["get_i",{"_index":3727,"title":{},"content":{"112":{"position":[[1531,8],[1617,7]]}},"keywords":{}}],["get_int(&self",{"_index":5340,"title":{},"content":{"197":{"position":[[311,18],[440,18],[589,18]]}},"keywords":{}}],["get_x",{"_index":3725,"title":{},"content":{"112":{"position":[[1513,8],[1605,7]]}},"keywords":{}}],["getint",{"_index":5339,"title":{},"content":{"197":{"position":[[299,6],[415,6],[563,6],[918,9],[960,7]]}},"keywords":{}}],["gil",{"_index":4900,"title":{"187":{"position":[[12,3]]}},"content":{"172":{"position":[[299,3]]},"188":{"position":[[306,4],[430,4],[568,3],[965,4],[1209,3],[1332,3],[1772,4],[2354,4],[2930,3],[3207,3],[3337,3],[3406,3],[4195,4],[4354,4],[4458,3],[4513,3]]},"189":{"position":[[656,3],[841,3],[1277,3],[1999,3],[2299,3],[2602,3],[2903,3]]},"190":{"position":[[159,3],[227,3],[340,4],[841,3],[948,3]]}},"keywords":{}}],["gil/lib/python3.7/sit",{"_index":5210,"title":{},"content":{"188":{"position":[[3799,22]]}},"keywords":{}}],["git",{"_index":4072,"title":{},"content":{"125":{"position":[[3049,3]]}},"keywords":{}}],["github",{"_index":99,"title":{},"content":{"2":{"position":[[368,6]]},"148":{"position":[[397,7]]}},"keywords":{}}],["give",{"_index":1346,"title":{},"content":{"30":{"position":[[822,4]]},"40":{"position":[[3535,4]]},"51":{"position":[[3271,4]]},"61":{"position":[[881,4]]},"65":{"position":[[197,4],[2583,5]]},"68":{"position":[[173,4]]},"69":{"position":[[145,4]]},"88":{"position":[[178,4],[623,6]]},"90":{"position":[[5146,4]]},"93":{"position":[[4038,6]]},"97":{"position":[[1114,4],[2311,4],[3975,4],[5436,4],[5634,4],[5795,4]]},"98":{"position":[[906,4]]},"102":{"position":[[1418,4]]},"106":{"position":[[789,4]]},"120":{"position":[[728,4],[959,5]]},"123":{"position":[[894,6]]},"125":{"position":[[9780,4]]},"128":{"position":[[325,5],[692,4],[1450,4]]},"129":{"position":[[885,6],[1121,4],[1311,4],[1892,4]]}},"keywords":{}}],["given",{"_index":404,"title":{},"content":{"7":{"position":[[567,5]]},"9":{"position":[[252,5]]},"17":{"position":[[18,5]]},"25":{"position":[[1,5]]},"26":{"position":[[384,5]]},"34":{"position":[[447,5]]},"49":{"position":[[1,5],[221,5],[601,5]]},"51":{"position":[[805,5],[3196,5]]},"57":{"position":[[652,5]]},"65":{"position":[[1187,5]]},"69":{"position":[[1,5],[212,6]]},"74":{"position":[[105,5]]},"83":{"position":[[1,5],[134,5]]},"85":{"position":[[414,5]]},"89":{"position":[[542,5]]},"90":{"position":[[764,5],[2149,5]]},"91":{"position":[[1390,5],[1674,5]]},"93":{"position":[[191,5]]},"100":{"position":[[196,5]]},"102":{"position":[[479,5],[717,5],[977,5]]},"123":{"position":[[14,5]]},"125":{"position":[[1570,5]]},"137":{"position":[[174,5]]},"142":{"position":[[98,5]]},"155":{"position":[[952,5]]},"163":{"position":[[55,5]]},"179":{"position":[[454,5]]},"193":{"position":[[96,5]]},"197":{"position":[[1014,5]]}},"keywords":{}}],["glass",{"_index":4754,"title":{},"content":{"161":{"position":[[1321,5],[1407,5]]}},"keywords":{}}],["global",{"_index":4371,"title":{"177":{"position":[[21,6]]}},"content":{"133":{"position":[[313,7]]},"159":{"position":[[391,6]]},"182":{"position":[[438,8]]},"185":{"position":[[106,8]]}},"keywords":{}}],["global_alloc",{"_index":4370,"title":{},"content":{"133":{"position":[[286,19]]},"144":{"position":[[115,19]]},"145":{"position":[[91,19]]},"146":{"position":[[119,19]]},"152":{"position":[[1128,19]]},"156":{"position":[[1211,19]]}},"keywords":{}}],["global_articl",{"_index":909,"title":{},"content":{"22":{"position":[[765,15],[1049,15]]}},"keywords":{}}],["globalalloc",{"_index":4529,"title":{},"content":{"152":{"position":[[1280,11]]},"156":{"position":[[1363,11]]}},"keywords":{}}],["gnb",{"_index":1998,"title":{},"content":{"45":{"position":[[2103,3],[2883,3]]}},"keywords":{}}],["gnb.fit(x_xform",{"_index":1999,"title":{},"content":{"45":{"position":[[2122,16],[2902,16]]}},"keywords":{}}],["gnb.score(x_xform",{"_index":2000,"title":{},"content":{"45":{"position":[[2149,18],[2929,18]]}},"keywords":{}}],["go",{"_index":308,"title":{},"content":{"6":{"position":[[92,2],[197,5]]},"7":{"position":[[706,5],[1123,5]]},"8":{"position":[[7,2]]},"9":{"position":[[117,5]]},"12":{"position":[[11,5]]},"14":{"position":[[1176,5]]},"15":{"position":[[559,2],[666,2]]},"22":{"position":[[7,5]]},"23":{"position":[[42,5]]},"26":{"position":[[727,2]]},"30":{"position":[[1089,5]]},"33":{"position":[[1156,2]]},"34":{"position":[[1148,5]]},"35":{"position":[[285,5]]},"40":{"position":[[2370,2]]},"43":{"position":[[80,5],[1080,5]]},"45":{"position":[[580,5],[1557,5]]},"49":{"position":[[146,2]]},"51":{"position":[[2758,2]]},"52":{"position":[[510,2],[554,5]]},"53":{"position":[[122,3],[1921,5]]},"57":{"position":[[333,5],[540,3],[634,2]]},"60":{"position":[[70,2]]},"61":{"position":[[1314,2],[1880,2]]},"64":{"position":[[95,5],[213,5],[1184,2],[1218,5]]},"66":{"position":[[756,5]]},"68":{"position":[[122,5]]},"76":{"position":[[1616,2]]},"77":{"position":[[7,2]]},"81":{"position":[[19,2]]},"88":{"position":[[2279,5],[2342,5],[3636,2]]},"90":{"position":[[11,2]]},"91":{"position":[[5048,5]]},"92":{"position":[[11,5],[1362,2],[1579,5]]},"95":{"position":[[516,5]]},"96":{"position":[[1344,5]]},"97":{"position":[[1231,5],[2086,5],[2134,5],[5210,5],[6203,5]]},"98":{"position":[[1204,5]]},"100":{"position":[[5,5]]},"101":{"position":[[415,2]]},"103":{"position":[[374,2],[431,5],[2276,5]]},"110":{"position":[[7,5],[196,5],[384,5]]},"112":{"position":[[260,2]]},"113":{"position":[[153,5],[267,2],[2497,2]]},"115":{"position":[[27,5]]},"120":{"position":[[214,2]]},"123":{"position":[[76,5],[326,5],[816,5]]},"124":{"position":[[336,5],[772,5]]},"125":{"position":[[1496,6],[1925,5],[2526,5],[2645,5],[9966,5],[10886,5]]},"128":{"position":[[1900,5]]},"130":{"position":[[512,2]]},"132":{"position":[[481,5]]},"135":{"position":[[42,5]]},"158":{"position":[[263,5]]},"160":{"position":[[751,5],[3386,5]]},"170":{"position":[[486,5]]},"174":{"position":[[1063,2]]},"175":{"position":[[506,5]]},"193":{"position":[[698,2]]}},"keywords":{}}],["goal",{"_index":236,"title":{},"content":{"4":{"position":[[301,5]]},"17":{"position":[[1,5]]},"125":{"position":[[3930,4]]},"186":{"position":[[174,6]]}},"keywords":{}}],["god",{"_index":2238,"title":{},"content":{"53":{"position":[[937,3]]}},"keywords":{}}],["godli",{"_index":2223,"title":{},"content":{"53":{"position":[[688,5]]}},"keywords":{}}],["goe",{"_index":1517,"title":{},"content":{"32":{"position":[[293,4]]},"33":{"position":[[911,4],[938,4]]},"38":{"position":[[196,4]]},"57":{"position":[[108,4]]},"58":{"position":[[598,4],[642,4]]},"61":{"position":[[213,4]]},"75":{"position":[[1198,4]]},"91":{"position":[[324,4]]},"193":{"position":[[2341,4]]},"196":{"position":[[1440,4]]}},"keywords":{}}],["gold",{"_index":1097,"title":{},"content":{"24":{"position":[[2564,4],[2756,4],[3154,4]]},"25":{"position":[[2287,4],[2479,4]]}},"keywords":{}}],["gone",{"_index":1347,"title":{},"content":{"30":{"position":[[861,4]]},"43":{"position":[[192,4]]},"103":{"position":[[2433,5]]},"125":{"position":[[324,5]]}},"keywords":{}}],["good",{"_index":191,"title":{},"content":{"3":{"position":[[1109,4]]},"4":{"position":[[329,4]]},"24":{"position":[[221,4]]},"26":{"position":[[464,4],[569,4]]},"40":{"position":[[1101,4]]},"44":{"position":[[154,4],[168,5],[413,4]]},"53":{"position":[[626,5],[1708,4],[1889,4]]},"82":{"position":[[1021,5],[1141,4]]},"83":{"position":[[77,4]]},"88":{"position":[[229,4]]},"98":{"position":[[9,4]]},"100":{"position":[[287,4]]},"122":{"position":[[678,4]]},"125":{"position":[[871,4],[1258,4],[10150,4],[11497,4],[11623,4]]},"150":{"position":[[257,4]]},"153":{"position":[[259,5]]},"173":{"position":[[1965,4]]},"193":{"position":[[837,4]]},"195":{"position":[[952,4]]}},"keywords":{}}],["goog/nasdaq_bib",{"_index":1828,"title":{},"content":{"40":{"position":[[2666,18]]}},"keywords":{}}],["goog/nasdaq_ibb",{"_index":1829,"title":{},"content":{"40":{"position":[[2685,19]]}},"keywords":{}}],["goog/nyse_voo",{"_index":716,"title":{},"content":{"17":{"position":[[206,15]]}},"keywords":{}}],["googl",{"_index":1748,"title":{},"content":{"39":{"position":[[2314,6]]},"96":{"position":[[1373,8],[1508,9]]},"175":{"position":[[294,7]]}},"keywords":{}}],["google'sbenchmark",{"_index":5052,"title":{},"content":{"176":{"position":[[1226,17]]}},"keywords":{}}],["gotten",{"_index":3316,"title":{},"content":{"96":{"position":[[125,6]]},"98":{"position":[[544,6]]},"113":{"position":[[31,6]]},"122":{"position":[[392,6]]}},"keywords":{}}],["govern",{"_index":5275,"title":{},"content":{"193":{"position":[[367,7]]}},"keywords":{}}],["graalvm",{"_index":4932,"title":{},"content":{"172":{"position":[[2192,7]]}},"keywords":{}}],["grammar",{"_index":2281,"title":{},"content":{"53":{"position":[[1773,7],[1832,8],[1894,7]]}},"keywords":{}}],["grant",{"_index":2368,"title":{},"content":{"61":{"position":[[1369,5]]}},"keywords":{}}],["granular",{"_index":2501,"title":{},"content":{"65":{"position":[[251,12]]}},"keywords":{}}],["graph",{"_index":1800,"title":{},"content":{"40":{"position":[[582,7]]},"45":{"position":[[3315,6]]}},"keywords":{}}],["graphic",{"_index":1888,"title":{},"content":{"43":{"position":[[1173,11]]}},"keywords":{}}],["great",{"_index":252,"title":{},"content":{"4":{"position":[[703,5]]},"24":{"position":[[3477,5]]},"29":{"position":[[314,5]]},"76":{"position":[[2318,5]]},"89":{"position":[[975,6]]},"120":{"position":[[801,5]]},"121":{"position":[[211,5]]},"125":{"position":[[11427,6]]},"132":{"position":[[582,5]]},"137":{"position":[[85,5]]},"158":{"position":[[252,5]]},"160":{"position":[[671,5],[929,5]]},"161":{"position":[[1535,6]]},"172":{"position":[[1664,5],[1825,5]]},"188":{"position":[[149,5]]},"194":{"position":[[734,5]]},"199":{"position":[[611,5]]}},"keywords":{}}],["greater",{"_index":1416,"title":{},"content":{"30":{"position":[[5971,7]]},"32":{"position":[[1161,7],[2201,7]]},"33":{"position":[[168,7],[640,7]]}},"keywords":{}}],["green",{"_index":3068,"title":{},"content":{"90":{"position":[[5225,5]]}},"keywords":{}}],["ground",{"_index":2213,"title":{},"content":{"53":{"position":[[493,6]]}},"keywords":{}}],["grow",{"_index":1200,"title":{},"content":{"28":{"position":[[163,7]]}},"keywords":{}}],["gt",{"_index":417,"title":{},"content":{"7":{"position":[[822,4]]},"13":{"position":[[976,4],[1165,4]]},"14":{"position":[[1994,4],[2199,4]]},"15":{"position":[[1042,4],[1161,4],[1662,4],[1867,4]]},"24":{"position":[[1375,4],[1398,4]]},"25":{"position":[[1095,4],[1118,4]]},"30":{"position":[[3277,4],[6345,4]]},"32":{"position":[[854,4]]},"34":{"position":[[1555,4]]},"39":{"position":[[747,4]]},"52":{"position":[[964,4]]},"76":{"position":[[2688,4],[2771,4]]},"92":{"position":[[909,5]]},"96":{"position":[[184,4],[692,4],[1111,4],[1641,4],[2187,4]]},"97":{"position":[[1495,4],[1522,4],[1943,4],[3678,4],[5030,4]]},"115":{"position":[[1096,4],[1443,4],[1726,4],[2184,4]]},"116":{"position":[[1048,4],[1348,4],[1631,4],[2042,4]]},"125":{"position":[[4285,4]]},"129":{"position":[[1489,4]]},"136":{"position":[[296,4]]},"147":{"position":[[210,4]]},"152":{"position":[[1357,4]]},"156":{"position":[[1440,4]]},"163":{"position":[[1785,4]]},"172":{"position":[[245,4]]},"180":{"position":[[447,4]]},"181":{"position":[[127,4],[249,4]]},"183":{"position":[[352,4],[498,4]]},"184":{"position":[[566,4]]},"189":{"position":[[1102,4],[1372,4],[3096,4]]},"193":{"position":[[1095,4],[2499,4],[3270,4],[3584,4]]},"196":{"position":[[951,4]]},"197":{"position":[[331,4],[460,4],[609,4]]}},"keywords":{}}],["gt;>>",{"_index":4309,"title":{},"content":{"129":{"position":[[2112,12],[2379,12],[2441,12],[2547,12],[2604,12],[2623,12]]}},"keywords":{}}],["guarante",{"_index":115,"title":{"31":{"position":[[0,10]]}},"content":{"2":{"position":[[618,9]]},"20":{"position":[[1136,9]]},"32":{"position":[[243,9],[392,9],[728,10],[1015,10],[1331,9],[2330,10]]},"36":{"position":[[58,9]]},"97":{"position":[[55,9],[146,10]]},"106":{"position":[[823,9]]},"115":{"position":[[2838,9]]},"117":{"position":[[378,12]]},"122":{"position":[[1100,10]]},"143":{"position":[[445,9]]},"159":{"position":[[532,9],[895,10]]},"160":{"position":[[3122,9]]},"172":{"position":[[1517,10]]},"175":{"position":[[600,10]]},"178":{"position":[[17,10]]},"181":{"position":[[700,10]]},"183":{"position":[[63,10],[178,9]]},"195":{"position":[[19,10]]}},"keywords":{}}],["guard",{"_index":3444,"title":{},"content":{"98":{"position":[[532,6]]},"158":{"position":[[476,5]]}},"keywords":{}}],["guardrail",{"_index":12,"title":{},"content":{"1":{"position":[[112,10]]}},"keywords":{}}],["guess",{"_index":1439,"title":{},"content":{"30":{"position":[[7828,5]]},"44":{"position":[[1031,5],[1519,5],[1630,5],[1703,5]]},"45":{"position":[[24,5],[179,5],[1004,6],[1893,6],[2606,5],[2707,5]]},"51":{"position":[[1919,8]]},"75":{"position":[[147,5],[228,5]]},"76":{"position":[[1984,8],[2122,7],[2324,7],[3291,6],[3313,5]]},"82":{"position":[[1146,6]]},"93":{"position":[[3,5]]},"97":{"position":[[4053,7]]},"120":{"position":[[13,5]]}},"keywords":{}}],["guess"",{"_index":1972,"title":{},"content":{"45":{"position":[[657,11],[2345,12],[2420,12],[3125,12],[3200,12]]}},"keywords":{}}],["gui",{"_index":4035,"title":{},"content":{"125":{"position":[[994,3]]}},"keywords":{}}],["guid",{"_index":4485,"title":{},"content":{"148":{"position":[[509,5]]},"172":{"position":[[1179,5],[2250,6]]},"176":{"position":[[743,7]]}},"keywords":{}}],["guide.xlabel(xlabel",{"_index":442,"title":{},"content":{"7":{"position":[[1297,21]]}},"keywords":{}}],["guide.xticks(ticks=x_tick",{"_index":440,"title":{},"content":{"7":{"position":[[1255,27]]}},"keywords":{}}],["guide.ylabel("value"",{"_index":443,"title":{},"content":{"7":{"position":[[1319,32]]}},"keywords":{}}],["guidelin",{"_index":5356,"title":{},"content":{"198":{"position":[[217,9]]}},"keywords":{}}],["guy"",{"_index":4730,"title":{},"content":{"161":{"position":[[354,9]]}},"keywords":{}}],["guywho",{"_index":3879,"title":{},"content":{"121":{"position":[[318,6]]}},"keywords":{}}],["h",{"_index":2130,"title":{},"content":{"51":{"position":[[2506,1]]}},"keywords":{}}],["h:%m:%",{"_index":2424,"title":{},"content":{"62":{"position":[[1115,11]]}},"keywords":{}}],["hack",{"_index":2362,"title":{},"content":{"61":{"position":[[1070,7]]}},"keywords":{}}],["half",{"_index":1133,"title":{},"content":{"24":{"position":[[3394,4]]},"26":{"position":[[432,4]]},"90":{"position":[[3293,4]]},"188":{"position":[[2774,4]]}},"keywords":{}}],["hall",{"_index":2575,"title":{},"content":{"68":{"position":[[978,4]]}},"keywords":{}}],["hand",{"_index":261,"title":{},"content":{"4":{"position":[[809,4]]},"58":{"position":[[939,5]]},"74":{"position":[[228,5]]},"77":{"position":[[184,4]]},"86":{"position":[[892,5]]},"111":{"position":[[795,5]]},"139":{"position":[[321,4]]},"163":{"position":[[793,5],[2504,5]]},"172":{"position":[[2223,5]]}},"keywords":{}}],["handl",{"_index":222,"title":{"61":{"position":[[0,8]]},"128":{"position":[[10,8]]}},"content":{"4":{"position":[[54,6]]},"39":{"position":[[2307,6]]},"61":{"position":[[1262,8]]},"90":{"position":[[3446,6]]},"95":{"position":[[36,6]]},"96":{"position":[[2000,6]]},"97":{"position":[[3320,8],[3485,8],[3984,6],[4121,8],[6511,8]]},"115":{"position":[[698,6],[1130,6],[1477,6],[1760,6],[2218,6]]},"116":{"position":[[717,6],[1082,6],[1382,6],[1665,6],[2076,6]]},"117":{"position":[[1574,6]]},"120":{"position":[[100,8]]},"125":{"position":[[6325,6]]},"127":{"position":[[1532,7]]},"129":{"position":[[2714,7]]},"130":{"position":[[71,7]]},"163":{"position":[[735,6]]},"165":{"position":[[550,6],[1144,7]]},"166":{"position":[[376,6]]},"173":{"position":[[1118,6],[1389,9],[1803,6],[1882,7],[2177,6]]},"175":{"position":[[1054,6],[1105,6]]},"196":{"position":[[583,6]]}},"keywords":{}}],["handle(&self",{"_index":3403,"title":{},"content":{"97":{"position":[[3638,17]]}},"keywords":{}}],["handle.join().unwrap",{"_index":3770,"title":{},"content":{"115":{"position":[[815,22]]},"116":{"position":[[835,23]]},"117":{"position":[[1855,23]]}},"keywords":{}}],["handle_data(self",{"_index":951,"title":{},"content":{"22":{"position":[[1729,17]]},"93":{"position":[[1718,17]]}},"keywords":{}}],["handle_endtag(self",{"_index":963,"title":{},"content":{"22":{"position":[[2273,19]]},"93":{"position":[[2187,19]]}},"keywords":{}}],["handle_starttag(self",{"_index":887,"title":{},"content":{"22":{"position":[[300,21],[1367,21]]},"93":{"position":[[1636,21]]}},"keywords":{}}],["handlebar",{"_index":3307,"title":{},"content":{"95":{"position":[[235,10]]}},"keywords":{}}],["handler",{"_index":52,"title":{},"content":{"1":{"position":[[589,7]]},"96":{"position":[[266,7]]},"97":{"position":[[637,7],[3232,7],[3609,7]]},"125":{"position":[[6870,7]]},"173":{"position":[[1490,7]]}},"keywords":{}}],["handlerhost",{"_index":4103,"title":{},"content":{"125":{"position":[[4914,11]]}},"keywords":{}}],["handles"",{"_index":4145,"title":{},"content":{"125":{"position":[[7091,13]]}},"keywords":{}}],["handshak",{"_index":5018,"title":{},"content":{"175":{"position":[[847,11]]}},"keywords":{}}],["hang",{"_index":3525,"title":{},"content":{"103":{"position":[[1021,7],[1104,9]]}},"keywords":{}}],["happen",{"_index":1135,"title":{},"content":{"25":{"position":[[138,8]]},"26":{"position":[[56,7]]},"28":{"position":[[2339,7]]},"30":{"position":[[7925,10]]},"40":{"position":[[1217,7],[1360,9]]},"44":{"position":[[1048,9],[1138,6]]},"51":{"position":[[2814,6]]},"61":{"position":[[2121,7]]},"70":{"position":[[6,7]]},"76":{"position":[[1652,7]]},"88":{"position":[[3717,9]]},"90":{"position":[[803,7],[2188,7]]},"91":{"position":[[4774,7]]},"125":{"position":[[2437,8],[10753,10],[10983,6]]},"135":{"position":[[353,8],[427,8],[494,8]]},"139":{"position":[[906,7]]},"143":{"position":[[217,9]]},"147":{"position":[[543,7]]},"156":{"position":[[1035,7]]},"161":{"position":[[744,7]]},"172":{"position":[[55,7],[286,8]]},"173":{"position":[[1373,7],[1710,9],[2225,7]]},"199":{"position":[[480,8]]}},"keywords":{}}],["happi",{"_index":1859,"title":{"42":{"position":[[30,9]]}},"content":{"43":{"position":[[918,6]]},"53":{"position":[[644,5]]},"122":{"position":[[1324,5]]},"123":{"position":[[548,5]]},"150":{"position":[[981,5]]}},"keywords":{}}],["hard",{"_index":1177,"title":{},"content":{"26":{"position":[[707,5]]},"53":{"position":[[1199,4]]},"69":{"position":[[253,4]]},"76":{"position":[[3388,4]]},"93":{"position":[[1023,4]]},"96":{"position":[[21,5],[222,5],[409,4]]},"122":{"position":[[697,5]]},"124":{"position":[[789,5]]},"125":{"position":[[900,4],[1013,5],[1140,4]]},"135":{"position":[[557,4]]},"176":{"position":[[627,4]]},"197":{"position":[[1445,4]]}},"keywords":{}}],["hardcor",{"_index":4692,"title":{},"content":{"160":{"position":[[2395,8]]}},"keywords":{}}],["harder",{"_index":5334,"title":{},"content":{"196":{"position":[[1407,7]]}},"keywords":{}}],["hardest",{"_index":4361,"title":{},"content":{"133":{"position":[[13,7]]}},"keywords":{}}],["hardwar",{"_index":4939,"title":{"174":{"position":[[0,9]]}},"content":{"173":{"position":[[70,9]]},"174":{"position":[[1275,8]]}},"keywords":{}}],["harnessforeachformat",{"_index":4851,"title":{},"content":{"167":{"position":[[23,21]]}},"keywords":{}}],["harri",{"_index":2221,"title":{},"content":{"53":{"position":[[665,6]]}},"keywords":{}}],["hasarrow",{"_index":5329,"title":{},"content":{"196":{"position":[[370,8]]}},"keywords":{}}],["hasgon",{"_index":4572,"title":{},"content":{"155":{"position":[[1133,7]]}},"keywords":{}}],["hashmap",{"_index":4640,"title":{},"content":{"159":{"position":[[1052,9]]}},"keywords":{}}],["hashtag",{"_index":2060,"title":{},"content":{"49":{"position":[[477,9],[591,9],[619,9],[668,8]]},"51":{"position":[[1522,9],[1553,8],[1676,8],[1941,8],[2182,8],[2228,8],[2257,8],[2593,8],[2661,7],[2912,8]]},"52":{"position":[[143,8],[357,7],[444,9],[599,9],[820,8]]}},"keywords":{}}],["hashtag_dist",{"_index":2127,"title":{},"content":{"51":{"position":[[2403,12],[3848,14]]},"52":{"position":[[383,13],[852,13]]}},"keywords":{}}],["hashtag_dist.hashtag",{"_index":2157,"title":{},"content":{"51":{"position":[[3886,22]]}},"keywords":{}}],["hashtag_dist.prob",{"_index":2158,"title":{},"content":{"51":{"position":[[3909,18]]}},"keywords":{}}],["hashtags)).strip",{"_index":2193,"title":{},"content":{"52":{"position":[[1163,18]]}},"keywords":{}}],["hashtags.fil",{"_index":2136,"title":{},"content":{"51":{"position":[[2964,13]]}},"keywords":{}}],["hashtags.mean",{"_index":2121,"title":{},"content":{"51":{"position":[[2093,15]]}},"keywords":{}}],["hashtags.plot(kind='hist",{"_index":2112,"title":{},"content":{"51":{"position":[[1744,26]]}},"keywords":{}}],["hashtags.unique().max",{"_index":2111,"title":{},"content":{"51":{"position":[[1720,23]]}},"keywords":{}}],["haskel",{"_index":2236,"title":{},"content":{"53":{"position":[[913,8]]}},"keywords":{}}],["hasmanydifferentcollectionalgorithmsto",{"_index":4903,"title":{},"content":{"172":{"position":[[364,38]]}},"keywords":{}}],["hasn't",{"_index":4205,"title":{},"content":{"125":{"position":[[11109,6]]}},"keywords":{}}],["hast",{"_index":2627,"title":{},"content":{"73":{"position":[[565,8]]}},"keywords":{}}],["hate",{"_index":4028,"title":{},"content":{"125":{"position":[[823,4]]}},"keywords":{}}],["have",{"_index":794,"title":{},"content":{"20":{"position":[[846,6]]},"28":{"position":[[1577,6],[3363,6]]},"30":{"position":[[7409,6]]},"61":{"position":[[160,6]]},"72":{"position":[[511,6]]},"97":{"position":[[173,6],[253,6]]},"98":{"position":[[559,6]]},"121":{"position":[[1,6],[666,6]]},"161":{"position":[[0,6]]},"175":{"position":[[115,6]]},"179":{"position":[[1460,6]]},"193":{"position":[[691,6]]}},"keywords":{}}],["haven't",{"_index":668,"title":{},"content":{"15":{"position":[[165,7]]},"34":{"position":[[3215,7]]},"106":{"position":[[1044,7]]},"124":{"position":[[644,7]]}},"keywords":{}}],["haze",{"_index":3365,"title":{},"content":{"97":{"position":[[606,7]]}},"keywords":{}}],["hcat(final_mot",{"_index":533,"title":{},"content":{"12":{"position":[[474,18]]}},"keywords":{}}],["hcat(full_mot",{"_index":522,"title":{},"content":{"11":{"position":[[514,17]]}},"keywords":{}}],["he'",{"_index":2960,"title":{},"content":{"89":{"position":[[970,4]]}},"keywords":{}}],["header",{"_index":3230,"title":{},"content":{"93":{"position":[[2437,7]]}},"keywords":{}}],["header=10",{"_index":3251,"title":{},"content":{"93":{"position":[[3172,10]]}},"keywords":{}}],["headers=headers).cont",{"_index":3238,"title":{},"content":{"93":{"position":[[2696,26]]}},"keywords":{}}],["headers={"us",{"_index":917,"title":{},"content":{"22":{"position":[[929,19],[2427,19]]}},"keywords":{}}],["health",{"_index":2321,"title":{},"content":{"58":{"position":[[33,6]]}},"keywords":{}}],["heap",{"_index":4437,"title":{"157":{"position":[[0,4]]}},"content":{"141":{"position":[[180,5],[292,4]]},"152":{"position":[[109,4],[530,4]]},"155":{"position":[[486,5],[647,4],[844,4],[971,4],[1193,4],[1247,4]]},"156":{"position":[[22,4],[209,4],[446,4],[509,5],[971,4]]},"157":{"position":[[78,5],[118,4],[715,4]]},"158":{"position":[[382,4]]},"159":{"position":[[277,4],[946,4],[1028,4],[1108,4],[1214,4]]},"160":{"position":[[1350,6]]},"164":{"position":[[384,4]]},"172":{"position":[[1058,4],[1154,4]]},"193":{"position":[[2038,4],[2127,4],[2414,4]]},"194":{"position":[[129,4],[201,4],[689,4]]},"195":{"position":[[1011,4]]},"196":{"position":[[155,4],[1918,4]]},"197":{"position":[[219,5],[1543,4]]},"198":{"position":[[491,4],[793,4],[858,4],[904,4]]},"199":{"position":[[550,5],[902,4],[970,5],[1050,4]]}},"keywords":{}}],["heaptrack",{"_index":4339,"title":{"131":{"position":[[16,9]]},"134":{"position":[[8,10]]}},"content":{"132":{"position":[[1052,10]]},"134":{"position":[[27,9],[147,9]]}},"keywords":{}}],["heaptrack.my_appplication.xxxx.gz",{"_index":4375,"title":{},"content":{"134":{"position":[[277,34]]}},"keywords":{}}],["heaptrack_gui",{"_index":4376,"title":{},"content":{"134":{"position":[[335,14]]}},"keywords":{}}],["hear",{"_index":1332,"title":{},"content":{"30":{"position":[[377,7]]},"101":{"position":[[960,4]]},"103":{"position":[[418,4]]},"104":{"position":[[440,4],[1879,5]]},"123":{"position":[[437,4]]}},"keywords":{}}],["heard",{"_index":257,"title":{},"content":{"4":{"position":[[746,5]]}},"keywords":{}}],["heart",{"_index":2317,"title":{},"content":{"57":{"position":[[681,5]]},"58":{"position":[[308,5],[545,5],[630,5]]},"62":{"position":[[93,5],[875,6],[999,5],[1719,5]]},"64":{"position":[[1970,5]]},"65":{"position":[[43,5],[184,5],[1314,5],[2577,5]]}},"keywords":{}}],["heart'][0]['datetim",{"_index":2417,"title":{},"content":{"62":{"position":[[939,22]]}},"keywords":{}}],["heartbeat",{"_index":2308,"title":{"64":{"position":[[9,10]]},"65":{"position":[[9,10]]}},"content":{"57":{"position":[[45,10]]},"58":{"position":[[685,10]]},"62":{"position":[[1607,10]]},"64":{"position":[[60,10],[628,10],[673,10],[1157,11],[1258,10],[1834,11],[1882,10],[1921,11]]},"65":{"position":[[286,10],[514,10],[549,10],[1034,10],[1143,10],[1992,10],[2092,10]]}},"keywords":{}}],["heartbeats_4year",{"_index":2503,"title":{},"content":{"65":{"position":[[630,16],[698,16],[849,16],[918,16]]}},"keywords":{}}],["heartbeats_quart",{"_index":2521,"title":{},"content":{"65":{"position":[[1662,18],[1809,18],[1878,18]]}},"keywords":{}}],["heartbeats_until_2016",{"_index":2488,"title":{},"content":{"64":{"position":[[1618,21],[1719,21]]}},"keywords":{}}],["heartrat",{"_index":2377,"title":{},"content":{"61":{"position":[[1644,12]]}},"keywords":{}}],["heavi",{"_index":2069,"title":{},"content":{"51":{"position":[[55,5]]}},"keywords":{}}],["heavili",{"_index":4280,"title":{},"content":{"129":{"position":[[490,7]]}},"keywords":{}}],["heck",{"_index":4382,"title":{},"content":{"135":{"position":[[640,4]]}},"keywords":{}}],["height=300",{"_index":1390,"title":{},"content":{"30":{"position":[[3836,11],[6915,11]]}},"keywords":{}}],["hell",{"_index":4031,"title":{},"content":{"125":{"position":[[922,4]]}},"keywords":{}}],["hello",{"_index":3839,"title":{"118":{"position":[[0,6]]}},"content":{},"keywords":{}}],["hello_world(req",{"_index":3328,"title":{},"content":{"96":{"position":[[656,16],[1075,16],[1605,16],[2151,16]]}},"keywords":{}}],["help",{"_index":13,"title":{},"content":{"1":{"position":[[123,4],[472,8]]},"3":{"position":[[259,5]]},"4":{"position":[[515,4]]},"24":{"position":[[3430,7]]},"44":{"position":[[1870,7]]},"89":{"position":[[940,7]]},"91":{"position":[[374,7]]},"96":{"position":[[1535,7]]},"97":{"position":[[587,7],[4225,5],[4233,5],[4648,7],[4667,5],[5874,5]]},"104":{"position":[[9,4]]},"105":{"position":[[383,4]]},"115":{"position":[[2512,4]]},"122":{"position":[[1333,4]]},"124":{"position":[[474,4]]},"137":{"position":[[114,4]]},"148":{"position":[[504,4]]},"159":{"position":[[78,7]]},"160":{"position":[[4011,8],[4101,7]]},"170":{"position":[[50,7]]},"174":{"position":[[370,4],[1122,8]]},"176":{"position":[[1179,8]]},"181":{"position":[[9,7]]}},"keywords":{}}],["henc",{"_index":270,"title":{},"content":{"4":{"position":[[930,6]]}},"keywords":{}}],["here",{"_index":630,"title":{"54":{"position":[[15,5]]}},"content":{"14":{"position":[[286,6]]},"15":{"position":[[546,5]]},"28":{"position":[[2530,5],[4031,5]]},"30":{"position":[[9529,4]]},"41":{"position":[[80,4]]},"51":{"position":[[1016,5]]},"53":{"position":[[113,4]]},"59":{"position":[[241,5]]},"61":{"position":[[259,4],[1335,5],[1838,4],[2108,5]]},"64":{"position":[[1409,4]]},"66":{"position":[[431,4]]},"91":{"position":[[3207,4]]},"92":{"position":[[1019,4],[1294,4]]},"96":{"position":[[1353,5]]},"97":{"position":[[1251,5],[2161,4]]},"103":{"position":[[2285,4]]},"105":{"position":[[2658,4]]},"108":{"position":[[311,5]]},"109":{"position":[[107,5]]},"113":{"position":[[184,4],[315,5],[376,4]]},"117":{"position":[[95,4]]},"118":{"position":[[115,4]]},"125":{"position":[[2050,4],[2700,4],[2794,5],[10942,4]]},"128":{"position":[[514,4]]},"129":{"position":[[614,4]]},"135":{"position":[[233,4]]},"145":{"position":[[199,5]]},"155":{"position":[[379,4],[693,5]]},"156":{"position":[[1043,4]]},"159":{"position":[[350,4]]},"198":{"position":[[137,5]]}},"keywords":{}}],["here'",{"_index":2357,"title":{},"content":{"61":{"position":[[636,6]]},"97":{"position":[[4943,6]]},"113":{"position":[[2462,6]]},"125":{"position":[[7463,6]]},"129":{"position":[[787,6]]},"182":{"position":[[389,6]]}},"keywords":{}}],["hereif",{"_index":3717,"title":{},"content":{"112":{"position":[[1012,6]]}},"keywords":{}}],["hesit",{"_index":3873,"title":{},"content":{"121":{"position":[[110,8]]}},"keywords":{}}],["hey",{"_index":4046,"title":{},"content":{"125":{"position":[[1337,3]]}},"keywords":{}}],["hidden",{"_index":2632,"title":{},"content":{"74":{"position":[[117,6]]}},"keywords":{}}],["hide_bann",{"_index":3505,"title":{},"content":{"103":{"position":[[247,11]]}},"keywords":{}}],["high",{"_index":797,"title":{"171":{"position":[[12,4]]}},"content":{"20":{"position":[[947,4]]},"30":{"position":[[4643,4]]},"45":{"position":[[126,5],[3506,4]]},"46":{"position":[[110,4]]},"70":{"position":[[64,5],[1250,7]]},"71":{"position":[[47,5],[135,5]]},"73":{"position":[[670,4]]},"82":{"position":[[159,5]]},"98":{"position":[[384,4]]},"104":{"position":[[508,4],[1333,4],[1548,4],[1762,4],[1820,4]]},"105":{"position":[[3322,4]]},"125":{"position":[[7005,4]]},"148":{"position":[[37,4],[437,4]]},"163":{"position":[[1263,6]]},"165":{"position":[[177,4]]},"166":{"position":[[137,4]]},"176":{"position":[[1,4],[1414,4]]}},"keywords":{}}],["higher",{"_index":1308,"title":{},"content":{"28":{"position":[[4268,6]]},"29":{"position":[[83,6]]},"38":{"position":[[494,6]]},"40":{"position":[[966,6]]},"75":{"position":[[685,6]]},"76":{"position":[[2538,7]]},"78":{"position":[[912,7]]},"82":{"position":[[287,7],[357,7],[427,7],[497,7],[567,7],[637,7],[707,7],[777,7],[847,7],[918,7]]},"88":{"position":[[3818,7]]},"170":{"position":[[319,6]]}},"keywords":{}}],["highest",{"_index":4708,"title":{},"content":{"160":{"position":[[3781,7]]}},"keywords":{}}],["highli",{"_index":1691,"title":{},"content":{"38":{"position":[[309,6],[1172,6]]},"173":{"position":[[1523,6]]}},"keywords":{}}],["highlight",{"_index":4360,"title":{},"content":{"132":{"position":[[985,9]]}},"keywords":{}}],["hilari",{"_index":2284,"title":{},"content":{"53":{"position":[[1938,9],[2057,9]]},"125":{"position":[[511,9]]}},"keywords":{}}],["hindsight",{"_index":177,"title":{},"content":{"3":{"position":[[839,10]]}},"keywords":{}}],["hire",{"_index":4499,"title":{},"content":{"150":{"position":[[580,6]]}},"keywords":{}}],["histogram",{"_index":1801,"title":{},"content":{"40":{"position":[[601,10]]}},"keywords":{}}],["histori",{"_index":1574,"title":{},"content":{"33":{"position":[[440,7]]},"50":{"position":[[29,8]]},"88":{"position":[[3140,9],[3519,9]]},"160":{"position":[[335,7]]}},"keywords":{}}],["hit",{"_index":1428,"title":{},"content":{"30":{"position":[[7129,3]]}},"keywords":{}}],["hold",{"_index":1535,"title":{},"content":{"32":{"position":[[991,5]]},"93":{"position":[[2990,8]]},"97":{"position":[[3450,4]]},"125":{"position":[[10427,5]]},"128":{"position":[[1392,7]]},"164":{"position":[[392,4]]},"192":{"position":[[93,4]]},"193":{"position":[[1164,4]]}},"keywords":{}}],["home",{"_index":3718,"title":{},"content":{"112":{"position":[[1049,5]]},"160":{"position":[[2931,4]]}},"keywords":{}}],["home/bspeice/development/isomorphic_rust/stdweb/dist",{"_index":4178,"title":{},"content":{"125":{"position":[[9029,55]]}},"keywords":{}}],["home/bspeice/development/isomorphic_rust/yew/dist",{"_index":4168,"title":{},"content":{"125":{"position":[[8561,52]]}},"keywords":{}}],["homebrew",{"_index":3670,"title":{},"content":{"108":{"position":[[476,8]]},"134":{"position":[[37,9]]}},"keywords":{}}],["homework",{"_index":2229,"title":{},"content":{"53":{"position":[[800,9]]}},"keywords":{}}],["honest",{"_index":3820,"title":{},"content":{"117":{"position":[[513,7]]}},"keywords":{}}],["honestli",{"_index":3188,"title":{},"content":{"93":{"position":[[181,9]]},"97":{"position":[[2993,8]]}},"keywords":{}}],["hood",{"_index":3547,"title":{},"content":{"103":{"position":[[2300,5]]},"125":{"position":[[6744,4]]},"127":{"position":[[905,5]]}},"keywords":{}}],["hope",{"_index":1181,"title":{},"content":{"26":{"position":[[809,4]]},"53":{"position":[[1682,5]]},"97":{"position":[[5864,4]]},"104":{"position":[[1484,4]]},"115":{"position":[[506,6]]},"121":{"position":[[2598,4]]},"124":{"position":[[599,6]]},"148":{"position":[[410,6]]},"197":{"position":[[1055,4]]}},"keywords":{}}],["hopefulli",{"_index":1222,"title":{},"content":{"28":{"position":[[765,9]]},"45":{"position":[[1822,10]]},"46":{"position":[[558,9]]},"51":{"position":[[3064,10]]}},"keywords":{}}],["horizon",{"_index":3023,"title":{},"content":{"90":{"position":[[3329,7]]},"91":{"position":[[1680,8],[2448,9],[2512,9],[2661,9],[3507,9],[4987,7],[5734,8],[5912,7],[5975,9]]},"92":{"position":[[261,9],[324,9],[473,9]]}},"keywords":{}}],["horizon*2",{"_index":3144,"title":{},"content":{"91":{"position":[[3388,9]]}},"keywords":{}}],["horizon+1",{"_index":3021,"title":{},"content":{"90":{"position":[[3230,9]]}},"keywords":{}}],["horizon=5",{"_index":3020,"title":{},"content":{"90":{"position":[[3212,11]]}},"keywords":{}}],["horribl",{"_index":3117,"title":{},"content":{"91":{"position":[[2222,8]]}},"keywords":{}}],["horror",{"_index":258,"title":{},"content":{"4":{"position":[[761,6]]}},"keywords":{}}],["hot",{"_index":2218,"title":{},"content":{"53":{"position":[[599,3]]},"161":{"position":[[1432,3]]}},"keywords":{}}],["hour",{"_index":1022,"title":{},"content":{"24":{"position":[[391,5]]},"26":{"position":[[183,5]]},"46":{"position":[[25,5]]},"97":{"position":[[895,5],[2201,5],[5185,5]]}},"keywords":{}}],["hr_d",{"_index":2460,"title":{},"content":{"64":{"position":[[553,4]]},"65":{"position":[[447,4]]}},"keywords":{}}],["hr_datafram",{"_index":2425,"title":{},"content":{"62":{"position":[[1137,13]]}},"keywords":{}}],["hr_df_concat",{"_index":2427,"title":{},"content":{"62":{"position":[[1210,12]]}},"keywords":{}}],["hr_df_concat.index",{"_index":2431,"title":{},"content":{"62":{"position":[[1375,19]]}},"keywords":{}}],["hr_df_concat.reindex(full_daterang",{"_index":2434,"title":{},"content":{"62":{"position":[[1424,36]]}},"keywords":{}}],["hr_df_full",{"_index":2433,"title":{},"content":{"62":{"position":[[1411,10]]}},"keywords":{}}],["hr_df_full.index",{"_index":2438,"title":{},"content":{"62":{"position":[[1554,17]]}},"keywords":{}}],["hr_df_full.index.day",{"_index":2469,"title":{},"content":{"64":{"position":[[885,21]]},"65":{"position":[[1730,21]]}},"keywords":{}}],["hr_df_full['value'].mean",{"_index":2484,"title":{},"content":{"64":{"position":[[1486,26]]}},"keywords":{}}],["hr_df_full['value'].sum",{"_index":2439,"title":{},"content":{"62":{"position":[[1576,27]]},"64":{"position":[[795,25]]}},"keywords":{}}],["hr_df_full[(hr_df_full.index.month",{"_index":2468,"title":{},"content":{"64":{"position":[[838,34]]},"65":{"position":[[1683,34]]}},"keywords":{}}],["hr_q",{"_index":2459,"title":{},"content":{"64":{"position":[[538,4]]},"65":{"position":[[432,4]]}},"keywords":{}}],["hr_respons",{"_index":2413,"title":{},"content":{"62":{"position":[[757,12],[1196,13]]}},"keywords":{}}],["href",{"_index":896,"title":{},"content":{"22":{"position":[[510,4],[547,7]]}},"keywords":{}}],["hrqhr_qhrq",{"_index":2462,"title":{},"content":{"64":{"position":[[605,12]]},"65":{"position":[[501,12]]}},"keywords":{}}],["hrq⋅n−hrd⋅(n−m)\\begin{equ",{"_index":2458,"title":{},"content":{"64":{"position":[[505,32]]},"65":{"position":[[399,32]]}},"keywords":{}}],["html",{"_index":878,"title":{},"content":{"22":{"position":[[27,4]]},"125":{"position":[[3852,4]]}},"keywords":{}}],["html.parser",{"_index":3198,"title":{},"content":{"93":{"position":[[1270,11]]}},"keywords":{}}],["html5ever",{"_index":3304,"title":{},"content":{"95":{"position":[[124,9]]}},"keywords":{}}],["htmlparser",{"_index":3199,"title":{},"content":{"93":{"position":[[1289,10]]}},"keywords":{}}],["http://itouchmap.com/latlong.html",{"_index":1449,"title":{},"content":{"30":{"position":[[8436,33]]}},"keywords":{}}],["http://math.stackexchange.com/a/1710392/320784",{"_index":2679,"title":{},"content":{"76":{"position":[[295,46]]}},"keywords":{}}],["http://matplotlib.org/examples/pylab_examples/finance_demo.html",{"_index":2862,"title":{},"content":{"88":{"position":[[992,63]]}},"keywords":{}}],["http://www.streetinsider.com/ec_earnings.php?q",{"_index":3231,"title":{},"content":{"93":{"position":[[2485,52]]}},"keywords":{}}],["http://www.treasury.gov/resourc",{"_index":490,"title":{},"content":{"10":{"position":[[207,32]]}},"keywords":{}}],["https://api.fitbit.com/1/us",{"_index":2411,"title":{},"content":{"62":{"position":[[684,31]]}},"keywords":{}}],["https://doc.rust",{"_index":5139,"title":{},"content":{"186":{"position":[[232,16]]}},"keywords":{}}],["https://github.com/rust",{"_index":3744,"title":{},"content":{"113":{"position":[[1185,23]]}},"keywords":{}}],["https://github.com/speic",{"_index":4073,"title":{},"content":{"125":{"position":[[3059,25]]}},"keywords":{}}],["https://www.fitbit.com/oauth2/author",{"_index":2374,"title":{},"content":{"61":{"position":[[1527,41]]}},"keywords":{}}],["huge",{"_index":799,"title":{},"content":{"20":{"position":[[974,4]]},"24":{"position":[[469,4]]},"25":{"position":[[194,4]]},"40":{"position":[[2253,4]]},"46":{"position":[[227,4]]},"93":{"position":[[201,4]]},"101":{"position":[[60,5],[98,5]]},"106":{"position":[[380,4]]},"125":{"position":[[3378,4],[4558,4]]},"161":{"position":[[643,4]]},"172":{"position":[[1416,4]]},"174":{"position":[[785,4]]}},"keywords":{}}],["huh",{"_index":3433,"title":{},"content":{"97":{"position":[[6125,4]]}},"keywords":{}}],["human",{"_index":2546,"title":{},"content":{"66":{"position":[[534,6]]},"104":{"position":[[1654,6]]},"123":{"position":[[756,5]]},"176":{"position":[[974,6],[1044,6]]},"189":{"position":[[1011,6]]}},"keywords":{}}],["humansvszombi",{"_index":2256,"title":{},"content":{"53":{"position":[[1211,16]]}},"keywords":{}}],["humantimecould",{"_index":3998,"title":{},"content":{"124":{"position":[[459,14]]}},"keywords":{}}],["hype",{"_index":2207,"title":{},"content":{"53":{"position":[[368,5]]}},"keywords":{}}],["hyper",{"_index":3301,"title":{},"content":{"95":{"position":[[59,5]]},"97":{"position":[[2282,5]]},"173":{"position":[[897,5]]}},"keywords":{}}],["hypervisor",{"_index":4990,"title":{},"content":{"174":{"position":[[859,10]]}},"keywords":{}}],["i'd",{"_index":1134,"title":{},"content":{"25":{"position":[[35,3]]},"28":{"position":[[420,3]]},"32":{"position":[[688,3]]},"38":{"position":[[1015,3]]},"41":{"position":[[219,3]]},"43":{"position":[[1032,3]]},"44":{"position":[[1893,3]]},"50":{"position":[[118,3]]},"54":{"position":[[116,3]]},"61":{"position":[[2027,3]]},"65":{"position":[[107,3]]},"96":{"position":[[431,3]]},"124":{"position":[[135,3]]},"125":{"position":[[10231,3]]}},"keywords":{}}],["i'll",{"_index":1189,"title":{},"content":{"26":{"position":[[897,4]]},"29":{"position":[[368,4]]},"30":{"position":[[7997,4]]},"32":{"position":[[1357,4]]},"38":{"position":[[771,4]]},"49":{"position":[[657,4]]},"50":{"position":[[240,4]]},"51":{"position":[[1,4]]},"53":{"position":[[1722,4]]},"61":{"position":[[691,4],[1309,4]]},"62":{"position":[[110,4],[273,4]]},"63":{"position":[[158,4]]},"64":{"position":[[1391,4]]},"65":{"position":[[1485,4]]},"74":{"position":[[894,4]]},"100":{"position":[[110,4]]},"103":{"position":[[76,4]]},"104":{"position":[[78,4]]},"108":{"position":[[253,4]]},"112":{"position":[[1081,4]]},"118":{"position":[[0,4]]},"122":{"position":[[186,4]]},"125":{"position":[[2500,4]]},"132":{"position":[[980,4]]},"160":{"position":[[4357,4]]},"161":{"position":[[301,4]]},"170":{"position":[[421,4]]},"194":{"position":[[773,4]]},"198":{"position":[[146,4]]}},"keywords":{}}],["i'm",{"_index":233,"title":{},"content":{"4":{"position":[[234,3]]},"7":{"position":[[1065,3]]},"22":{"position":[[2702,3]]},"24":{"position":[[459,3]]},"25":{"position":[[184,3]]},"30":{"position":[[327,3],[691,3],[8212,3]]},"35":{"position":[[281,3],[466,3]]},"39":{"position":[[395,3]]},"41":{"position":[[8,3]]},"43":{"position":[[406,3]]},"45":{"position":[[411,3],[572,3]]},"46":{"position":[[321,3],[354,3]]},"50":{"position":[[1,3]]},"51":{"position":[[996,3],[1915,3]]},"53":{"position":[[192,3],[581,3],[1959,4]]},"55":{"position":[[1,3],[73,3]]},"57":{"position":[[468,3]]},"58":{"position":[[7,3],[371,3],[754,3]]},"63":{"position":[[61,3]]},"64":{"position":[[1214,3],[1419,3]]},"65":{"position":[[1521,3],[2263,3]]},"73":{"position":[[261,3]]},"86":{"position":[[221,3]]},"95":{"position":[[512,3]]},"96":{"position":[[274,3]]},"97":{"position":[[227,3],[3122,3],[5206,3]]},"98":{"position":[[1136,3]]},"100":{"position":[[1,3]]},"102":{"position":[[418,3],[1520,3]]},"113":{"position":[[149,3],[2481,3]]},"117":{"position":[[521,3]]},"118":{"position":[[222,3]]},"121":{"position":[[95,3],[466,3],[1454,3],[2566,3]]},"122":{"position":[[848,3],[916,3],[996,3]]},"123":{"position":[[72,3],[322,3],[544,3],[664,3],[963,3]]},"124":{"position":[[588,3],[768,3],[818,3]]},"125":{"position":[[1794,3],[1889,3],[1921,3],[2032,3],[2636,3],[2685,3],[2845,3],[9183,3],[10871,3],[11739,3]]},"127":{"position":[[12,3]]},"132":{"position":[[373,3]]},"148":{"position":[[406,3]]},"150":{"position":[[977,3]]},"161":{"position":[[116,3],[408,3],[1641,3],[1710,3]]},"163":{"position":[[419,3]]}},"keywords":{}}],["i'v",{"_index":256,"title":{},"content":{"4":{"position":[[741,4]]},"30":{"position":[[367,4],[856,4]]},"43":{"position":[[179,4]]},"51":{"position":[[3432,4]]},"52":{"position":[[1,4]]},"53":{"position":[[1415,4]]},"55":{"position":[[153,4]]},"57":{"position":[[544,4]]},"58":{"position":[[212,4],[454,4],[491,4]]},"60":{"position":[[1,4]]},"61":{"position":[[243,4],[2073,4]]},"64":{"position":[[71,4],[1125,4]]},"65":{"position":[[55,4],[2506,4]]},"76":{"position":[[1386,4]]},"91":{"position":[[3821,4]]},"98":{"position":[[539,4]]},"104":{"position":[[1040,4]]},"112":{"position":[[987,4]]},"115":{"position":[[2495,4]]},"118":{"position":[[192,4]]},"121":{"position":[[281,4]]},"122":{"position":[[133,4]]},"124":{"position":[[7,4]]},"130":{"position":[[588,4]]},"132":{"position":[[444,4]]},"150":{"position":[[133,4]]},"161":{"position":[[914,4],[1590,4]]},"166":{"position":[[79,4]]}},"keywords":{}}],["i*d",{"_index":1724,"title":{},"content":{"39":{"position":[[597,4]]}},"keywords":{}}],["i*tick_width",{"_index":428,"title":{},"content":{"7":{"position":[[1016,13]]}},"keywords":{}}],["i.",{"_index":1898,"title":{},"content":{"44":{"position":[[105,5]]},"74":{"position":[[1369,5]]},"75":{"position":[[472,4]]},"91":{"position":[[3935,5]]},"97":{"position":[[5655,5]]},"113":{"position":[[2011,5]]}},"keywords":{}}],["i/o",{"_index":4957,"title":{},"content":{"173":{"position":[[1042,3]]}},"keywords":{}}],["i32",{"_index":4268,"title":{},"content":{"128":{"position":[[1124,4]]}},"keywords":{}}],["i64",{"_index":5278,"title":{},"content":{"193":{"position":[[924,4],[932,4],[1100,3],[2229,4],[2237,4],[2504,3],[3195,4],[3203,4],[3275,3],[3589,3]]}},"keywords":{}}],["i=1:(n",{"_index":395,"title":{},"content":{"7":{"position":[[416,6]]}},"keywords":{}}],["i=1:length(invest",{"_index":1646,"title":{},"content":{"34":{"position":[[2781,24]]}},"keywords":{}}],["i=1:m",{"_index":584,"title":{},"content":{"13":{"position":[[1411,6]]},"14":{"position":[[2483,6]]},"15":{"position":[[2155,6]]}},"keywords":{}}],["i=1:num_simul",{"_index":588,"title":{},"content":{"13":{"position":[[1485,19]]},"14":{"position":[[2557,19]]},"15":{"position":[[2229,19]]}},"keywords":{}}],["i=1:round(num_tick",{"_index":426,"title":{},"content":{"7":{"position":[[971,20]]}},"keywords":{}}],["i=1:t",{"_index":518,"title":{},"content":{"11":{"position":[[408,5]]},"12":{"position":[[368,5]]},"13":{"position":[[760,5],[1305,6]]},"14":{"position":[[1617,5],[2377,6]]},"15":{"position":[[1004,5],[2049,6]]}},"keywords":{}}],["i=1:year",{"_index":478,"title":{},"content":{"9":{"position":[[810,10]]}},"keywords":{}}],["ic⋅i",{"_index":551,"title":{},"content":{"13":{"position":[[331,4]]}},"keywords":{}}],["id",{"_index":203,"title":{},"content":{"3":{"position":[[1283,3]]},"43":{"position":[[568,5]]},"108":{"position":[[877,2]]},"163":{"position":[[1177,2]]}},"keywords":{}}],["id.1",{"_index":1871,"title":{},"content":{"43":{"position":[[574,8]]}},"keywords":{}}],["idea",{"_index":1892,"title":{},"content":{"43":{"position":[[1421,4]]},"54":{"position":[[50,5]]},"57":{"position":[[425,4]]},"90":{"position":[[5157,4]]},"101":{"position":[[439,4]]},"102":{"position":[[188,4],[957,4],[1429,4]]},"106":{"position":[[161,4]]},"112":{"position":[[1129,4]]},"125":{"position":[[11729,4]]},"127":{"position":[[555,4]]},"129":{"position":[[1214,4]]},"132":{"position":[[588,5],[913,4]]},"160":{"position":[[2904,4]]}},"keywords":{}}],["ideal",{"_index":1689,"title":{},"content":{"38":{"position":[[158,8]]},"73":{"position":[[741,8]]}},"keywords":{}}],["ident",{"_index":5243,"title":{},"content":{"189":{"position":[[1953,9]]}},"keywords":{}}],["identifi",{"_index":2482,"title":{},"content":{"64":{"position":[[1446,11]]},"104":{"position":[[1064,10]]}},"keywords":{}}],["identifywhere/when",{"_index":5048,"title":{},"content":{"176":{"position":[[866,18]]}},"keywords":{}}],["idiomat",{"_index":3877,"title":{},"content":{"121":{"position":[[261,9]]}},"keywords":{}}],["idiot",{"_index":2034,"title":{},"content":{"46":{"position":[[475,6]]}},"keywords":{}}],["iex",{"_index":4796,"title":{},"content":{"163":{"position":[[2203,3]]},"167":{"position":[[230,3]]},"168":{"position":[[79,3]]}},"keywords":{}}],["ifnum_alloc",{"_index":4897,"title":{},"content":{"172":{"position":[[219,11]]}},"keywords":{}}],["ignor",{"_index":138,"title":{},"content":{"3":{"position":[[76,7]]},"28":{"position":[[1548,6],[3334,6]]},"51":{"position":[[1032,6]]},"65":{"position":[[1630,6]]},"66":{"position":[[132,7]]},"189":{"position":[[1025,7]]}},"keywords":{}}],["ignore.we'l",{"_index":4704,"title":{},"content":{"160":{"position":[[3524,12]]}},"keywords":{}}],["iii",{"_index":552,"title":{},"content":{"13":{"position":[[341,3]]},"32":{"position":[[650,3]]}},"keywords":{}}],["iiicic_ici",{"_index":1523,"title":{},"content":{"32":{"position":[[524,11]]}},"keywords":{}}],["iiidid_idi",{"_index":1524,"title":{},"content":{"32":{"position":[[574,11]]}},"keywords":{}}],["illeg",{"_index":5065,"title":{},"content":{"179":{"position":[[139,8]]}},"keywords":{}}],["illustr",{"_index":479,"title":{"10":{"position":[[0,12]]}},"content":{},"keywords":{}}],["imagin",{"_index":5354,"title":{},"content":{"197":{"position":[[1453,7]]}},"keywords":{}}],["imit",{"_index":2066,"title":{},"content":{"50":{"position":[[175,7]]}},"keywords":{}}],["imitatemor",{"_index":4220,"title":{},"content":{"125":{"position":[[11639,11]]}},"keywords":{}}],["immedi",{"_index":2613,"title":{},"content":{"72":{"position":[[196,11],[700,11]]},"189":{"position":[[1849,11]]},"193":{"position":[[1109,11]]},"196":{"position":[[761,11],[1148,11]]}},"keywords":{}}],["immut",{"_index":3724,"title":{},"content":{"112":{"position":[[1444,9]]},"136":{"position":[[679,9],[832,10]]},"179":{"position":[[196,9],[463,9]]},"186":{"position":[[384,10]]}},"keywords":{}}],["imp\\sigma_{imp}σimp",{"_index":339,"title":{},"content":{"6":{"position":[[534,21]]}},"keywords":{}}],["impact",{"_index":1702,"title":{},"content":{"38":{"position":[[1052,6]]},"122":{"position":[[91,7]]},"143":{"position":[[484,7]]},"172":{"position":[[98,8],[1421,7]]}},"keywords":{}}],["impecc",{"_index":2282,"title":{},"content":{"53":{"position":[[1821,10]]}},"keywords":{}}],["impl",{"_index":3402,"title":{"129":{"position":[[0,4]]}},"content":{"97":{"position":[[3604,4]]},"112":{"position":[[1490,4],[1587,4]]},"129":{"position":[[151,4],[336,4],[1451,4]]},"147":{"position":[[215,4]]},"152":{"position":[[1275,4]]},"156":{"position":[[1358,4]]},"184":{"position":[[534,4]]},"185":{"position":[[463,4]]},"196":{"position":[[956,4]]},"197":{"position":[[76,4],[410,4],[558,4]]}},"keywords":{}}],["implem",{"_index":5358,"title":{},"content":{"198":{"position":[[258,11]]}},"keywords":{}}],["implement",{"_index":162,"title":{},"content":{"3":{"position":[[557,11]]},"40":{"position":[[752,12]]},"97":{"position":[[3272,10],[3470,9],[4820,9]]},"116":{"position":[[3048,9]]},"117":{"position":[[30,11]]},"121":{"position":[[2511,14]]},"125":{"position":[[588,15]]},"129":{"position":[[96,15]]},"153":{"position":[[296,12]]},"157":{"position":[[618,12]]},"166":{"position":[[775,14]]},"169":{"position":[[250,15]]},"182":{"position":[[596,9]]},"185":{"position":[[64,9],[240,9],[317,9]]},"196":{"position":[[720,15]]},"197":{"position":[[852,14],[907,10]]},"198":{"position":[[720,9],[766,9],[814,9],[1074,11]]}},"keywords":{}}],["impli",{"_index":315,"title":{},"content":{"6":{"position":[[252,7],[469,7],[575,7]]},"9":{"position":[[191,7],[673,7]]},"15":{"position":[[83,8]]},"45":{"position":[[3362,5]]},"46":{"position":[[242,7]]},"74":{"position":[[430,7]]},"91":{"position":[[4668,7]]},"103":{"position":[[1631,7]]}},"keywords":{}}],["implic",{"_index":1563,"title":{"33":{"position":[[12,13]]}},"content":{"160":{"position":[[3303,12]]},"173":{"position":[[2031,13]]},"195":{"position":[[891,12]]}},"keywords":{}}],["implicit",{"_index":2367,"title":{},"content":{"61":{"position":[[1360,8]]},"198":{"position":[[944,8]]}},"keywords":{}}],["implicitli",{"_index":5169,"title":{},"content":{"188":{"position":[[1367,10]]}},"keywords":{}}],["import",{"_index":208,"title":{},"content":{"3":{"position":[[1360,6]]},"4":{"position":[[160,10],[416,9]]},"17":{"position":[[74,6],[89,6],[117,6]]},"20":{"position":[[1002,6],[1041,6]]},"24":{"position":[[3298,9]]},"30":{"position":[[114,6],[171,6],[197,6],[217,6],[250,6],[266,6],[8318,6],[8353,6],[8367,6],[8397,6],[10054,6]]},"33":{"position":[[353,9]]},"39":{"position":[[414,6],[433,6],[453,6],[497,6],[3081,6]]},"43":{"position":[[267,6],[287,6],[306,6],[433,6]]},"44":{"position":[[586,6]]},"45":{"position":[[1926,6],[1971,6]]},"47":{"position":[[78,6]]},"51":{"position":[[83,6],[101,6],[432,6],[1076,6],[1625,6],[3587,6]]},"58":{"position":[[89,9]]},"60":{"position":[[138,6],[209,6]]},"61":{"position":[[1500,6]]},"62":{"position":[[387,6],[408,6],[442,6]]},"65":{"position":[[2301,6]]},"66":{"position":[[716,9]]},"68":{"position":[[402,6],[421,6],[441,6],[801,9]]},"73":{"position":[[593,9]]},"74":{"position":[[1276,9]]},"76":{"position":[[127,6],[157,6]]},"78":{"position":[[99,6]]},"88":{"position":[[264,6],[282,6],[336,6],[376,6],[422,6],[480,6],[508,6],[524,6]]},"90":{"position":[[176,6],[195,6],[243,6],[303,6],[342,6]]},"91":{"position":[[1841,6],[1874,6],[1904,6],[4680,9]]},"93":{"position":[[18,9],[1245,6],[1282,6],[1314,6],[1341,6],[1357,6],[1381,6],[1395,6],[1430,6],[1445,6],[3813,6],[3831,6],[3851,6],[3884,6],[3911,6],[3928,6],[3959,6]]},"98":{"position":[[284,9]]},"103":{"position":[[463,6],[490,6],[843,6],[854,6]]},"105":{"position":[[457,6],[473,6]]},"112":{"position":[[291,9]]},"125":{"position":[[3626,9],[10344,9]]},"139":{"position":[[361,9]]},"147":{"position":[[6,9]]},"152":{"position":[[286,9]]},"160":{"position":[[1465,9],[2678,9]]},"161":{"position":[[554,9]]},"166":{"position":[[112,9]]},"170":{"position":[[119,9]]},"173":{"position":[[192,9],[404,9],[455,9]]},"179":{"position":[[162,9]]},"188":{"position":[[2011,6]]},"189":{"position":[[3026,6]]},"190":{"position":[[24,9]]}},"keywords":{}}],["import.meta.url",{"_index":123,"title":{},"content":{"2":{"position":[[740,16]]}},"keywords":{}}],["important"",{"_index":3559,"title":{},"content":{"104":{"position":[[648,15]]}},"keywords":{}}],["importantli",{"_index":2389,"title":{},"content":{"61":{"position":[[2241,12]]}},"keywords":{}}],["imposs",{"_index":1566,"title":{},"content":{"33":{"position":[[97,10]]},"104":{"position":[[1865,10]]},"150":{"position":[[275,10]]},"165":{"position":[[1369,11]]},"178":{"position":[[587,10]]},"179":{"position":[[820,11]]},"190":{"position":[[1030,10]]},"198":{"position":[[457,10]]}},"keywords":{}}],["impress",{"_index":2217,"title":{},"content":{"53":{"position":[[528,10]]},"117":{"position":[[606,10]]}},"keywords":{}}],["improv",{"_index":1986,"title":{},"content":{"45":{"position":[[1751,8]]},"174":{"position":[[142,12]]}},"keywords":{}}],["in_font_tag",{"_index":929,"title":{},"content":{"22":{"position":[[1218,11]]}},"keywords":{}}],["inadvert",{"_index":5011,"title":{},"content":{"175":{"position":[[492,13]]}},"keywords":{}}],["inc",{"_index":3256,"title":{},"content":{"93":{"position":[[3287,7]]}},"keywords":{}}],["incargo.lock",{"_index":4150,"title":{},"content":{"125":{"position":[[7697,13]]}},"keywords":{}}],["inclin",{"_index":4037,"title":{},"content":{"125":{"position":[[1237,8]]}},"keywords":{}}],["includ",{"_index":1349,"title":{},"content":{"30":{"position":[[917,8]]},"51":{"position":[[183,7]]},"65":{"position":[[359,9]]},"90":{"position":[[3255,9],[3358,9]]},"92":{"position":[[1429,8]]},"111":{"position":[[782,9]]},"112":{"position":[[992,8]]},"113":{"position":[[430,9],[641,7]]},"125":{"position":[[2856,9]]},"150":{"position":[[940,8]]},"185":{"position":[[451,8]]},"189":{"position":[[1570,7]]},"197":{"position":[[1236,8]]}},"keywords":{}}],["include!(concat!(env!("out_dir"",{"_index":3736,"title":{},"content":{"113":{"position":[[649,43]]}},"keywords":{}}],["incorrectli",{"_index":163,"title":{},"content":{"3":{"position":[[572,12]]}},"keywords":{}}],["increas",{"_index":1589,"title":{},"content":{"33":{"position":[[1216,9]]},"65":{"position":[[237,10]]},"76":{"position":[[1063,8]]}},"keywords":{}}],["incred",{"_index":1706,"title":{},"content":{"39":{"position":[[18,10]]},"44":{"position":[[942,10],[1859,10]]},"45":{"position":[[115,10]]},"76":{"position":[[694,10]]},"86":{"position":[[513,10]]},"89":{"position":[[462,10]]},"91":{"position":[[4651,11],[4802,10],[5494,10],[5765,10],[5876,11]]},"96":{"position":[[316,10]]},"97":{"position":[[2952,10]]},"98":{"position":[[1087,10]]},"101":{"position":[[153,10]]},"103":{"position":[[2031,10],[2215,10]]},"105":{"position":[[2814,10]]},"121":{"position":[[1859,10]]},"125":{"position":[[10290,10]]},"129":{"position":[[1165,10]]},"130":{"position":[[79,10]]},"150":{"position":[[246,10]]},"161":{"position":[[1421,10]]},"170":{"position":[[39,10]]},"174":{"position":[[442,11]]}},"keywords":{}}],["increment",{"_index":2453,"title":{},"content":{"64":{"position":[[295,10]]}},"keywords":{}}],["incur",{"_index":1688,"title":{},"content":{"38":{"position":[[123,5],[1164,5]]}},"keywords":{}}],["inde",{"_index":1838,"title":{},"content":{"40":{"position":[[3423,7]]},"45":{"position":[[3441,6]]},"83":{"position":[[50,6]]},"86":{"position":[[685,7]]},"103":{"position":[[1864,6]]}},"keywords":{}}],["indefinit",{"_index":3984,"title":{},"content":{"123":{"position":[[822,13]]}},"keywords":{}}],["indent",{"_index":3912,"title":{},"content":{"121":{"position":[[1939,11]]}},"keywords":{}}],["index",{"_index":992,"title":{},"content":{"23":{"position":[[104,6]]},"24":{"position":[[1993,5]]},"25":{"position":[[1717,5]]},"39":{"position":[[382,5]]},"76":{"position":[[631,5]]},"90":{"position":[[814,5],[2199,5]]}},"keywords":{}}],["index'",{"_index":1017,"title":{},"content":{"24":{"position":[[107,7],[172,7]]}},"keywords":{}}],["index=b_class",{"_index":1918,"title":{},"content":{"44":{"position":[[757,14]]}},"keywords":{}}],["index_dict",{"_index":1071,"title":{},"content":{"24":{"position":[[1651,10]]},"25":{"position":[[1371,10]]}},"keywords":{}}],["index_dict[index",{"_index":1082,"title":{},"content":{"24":{"position":[[2084,18]]},"25":{"position":[[1808,18]]}},"keywords":{}}],["index_dict_dt",{"_index":1051,"title":{},"content":{"24":{"position":[[1090,13]]},"25":{"position":[[810,13]]}},"keywords":{}}],["index_dt",{"_index":1061,"title":{},"content":{"24":{"position":[[1248,8],[1310,8]]},"25":{"position":[[968,8],[1030,8]]}},"keywords":{}}],["index_valu",{"_index":1065,"title":{},"content":{"24":{"position":[[1330,11],[1386,11],[1433,11],[1478,11]]},"25":{"position":[[1050,11],[1106,11],[1153,11],[1198,11]]}},"keywords":{}}],["indic",{"_index":990,"title":{},"content":{"23":{"position":[[78,7]]},"24":{"position":[[1799,7],[2002,8],[3461,8],[3511,8]]},"25":{"position":[[1523,7],[1726,8]]},"26":{"position":[[522,8],[613,7]]},"41":{"position":[[139,8]]},"51":{"position":[[1312,7],[1410,8]]},"165":{"position":[[1265,8]]},"188":{"position":[[873,9]]},"192":{"position":[[708,9]]}},"keywords":{}}],["individu",{"_index":1952,"title":{},"content":{"44":{"position":[[1770,10]]},"71":{"position":[[1082,10]]},"74":{"position":[[448,10]]},"172":{"position":[[119,10]]}},"keywords":{}}],["induc",{"_index":824,"title":{},"content":{"20":{"position":[[1638,6]]}},"keywords":{}}],["industri",{"_index":1,"title":{"0":{"position":[[12,10]]}},"content":{"4":{"position":[[955,10]]},"23":{"position":[[121,11]]},"93":{"position":[[911,12]]},"174":{"position":[[1306,10]]},"176":{"position":[[41,9]]}},"keywords":{}}],["ineffici",{"_index":3118,"title":{},"content":{"91":{"position":[[2231,12]]}},"keywords":{}}],["ineq",{"_index":839,"title":{},"content":{"20":{"position":[[2079,7],[2126,7],[2169,7]]}},"keywords":{}}],["infer",{"_index":5300,"title":{},"content":{"193":{"position":[[2063,5],[2158,10]]}},"keywords":{}}],["infin",{"_index":829,"title":{},"content":{"20":{"position":[[1709,8]]}},"keywords":{}}],["influenc",{"_index":1853,"title":{},"content":{"41":{"position":[[507,9]]}},"keywords":{}}],["info",{"_index":3818,"title":{},"content":{"117":{"position":[[461,4]]}},"keywords":{}}],["inform",{"_index":1020,"title":{},"content":{"24":{"position":[[365,11]]},"35":{"position":[[304,11]]},"45":{"position":[[3566,6]]},"60":{"position":[[166,11]]},"61":{"position":[[1972,11]]},"64":{"position":[[1458,12]]},"83":{"position":[[506,11]]},"88":{"position":[[2188,12]]},"90":{"position":[[115,11]]},"97":{"position":[[662,11]]},"104":{"position":[[258,11],[407,11]]},"136":{"position":[[782,12]]},"155":{"position":[[890,12]]}},"keywords":{}}],["infrastructur",{"_index":5017,"title":{},"content":{"175":{"position":[[742,14]]}},"keywords":{}}],["ingest",{"_index":3305,"title":{},"content":{"95":{"position":[[147,6]]}},"keywords":{}}],["inherit",{"_index":4237,"title":{},"content":{"127":{"position":[[866,7],[1419,8]]}},"keywords":{}}],["inhow",{"_index":4655,"title":{},"content":{"160":{"position":[[382,5]]}},"keywords":{}}],["init",{"_index":1623,"title":{},"content":{"34":{"position":[[1619,5],[1811,6]]},"39":{"position":[[1030,5]]},"109":{"position":[[177,4]]},"173":{"position":[[674,4]]},"186":{"position":[[308,5],[365,6],[544,4]]}},"keywords":{}}],["init.call_onc",{"_index":5141,"title":{},"content":{"186":{"position":[[441,17],[601,17]]}},"keywords":{}}],["initi",{"_index":389,"title":{"180":{"position":[[0,15]]},"184":{"position":[[0,15]]}},"content":{"7":{"position":[[312,7]]},"8":{"position":[[79,7]]},"14":{"position":[[207,7]]},"30":{"position":[[7820,7]]},"34":{"position":[[3532,7]]},"39":{"position":[[2176,8]]},"44":{"position":[[1023,7]]},"45":{"position":[[624,7]]},"47":{"position":[[24,7]]},"91":{"position":[[4112,7]]},"178":{"position":[[285,14]]},"179":{"position":[[1472,11]]},"183":{"position":[[788,14]]},"184":{"position":[[24,15],[61,12],[826,10]]},"185":{"position":[[408,12]]}},"keywords":{}}],["initialization"",{"_index":4561,"title":{},"content":{"155":{"position":[[344,21]]}},"keywords":{}}],["inlin",{"_index":1721,"title":{},"content":{"39":{"position":[[528,6]]},"43":{"position":[[350,6]]},"51":{"position":[[1669,6]]},"68":{"position":[[485,6]]},"88":{"position":[[556,6]]},"113":{"position":[[242,7]]},"152":{"position":[[240,9]]},"159":{"position":[[796,11]]},"181":{"position":[[593,6]]},"193":{"position":[[2094,9],[2360,8],[2388,6]]}},"keywords":{}}],["inline(alway",{"_index":5304,"title":{},"content":{"193":{"position":[[2438,17]]}},"keywords":{}}],["inner",{"_index":5071,"title":{},"content":{"179":{"position":[[532,5]]}},"keywords":{}}],["innov",{"_index":4050,"title":{},"content":{"125":{"position":[[1583,11],[10742,10]]},"160":{"position":[[3863,11]]}},"keywords":{}}],["inopportun",{"_index":4507,"title":{},"content":{"150":{"position":[[889,11]]}},"keywords":{}}],["inopt",{"_index":5308,"title":{},"content":{"194":{"position":[[49,8]]}},"keywords":{}}],["input",{"_index":2051,"title":{},"content":{"49":{"position":[[10,5]]},"50":{"position":[[14,5]]},"97":{"position":[[2410,6]]},"163":{"position":[[2026,11]]}},"keywords":{}}],["input"",{"_index":3866,"title":{},"content":{"120":{"position":[[1061,11]]}},"keywords":{}}],["inrust",{"_index":5051,"title":{},"content":{"176":{"position":[[1214,7]]}},"keywords":{}}],["insid",{"_index":3767,"title":{},"content":{"115":{"position":[[477,6]]},"188":{"position":[[612,6]]}},"keywords":{}}],["insight",{"_index":1118,"title":{},"content":{"24":{"position":[[2922,9]]},"104":{"position":[[1599,8]]}},"keywords":{}}],["inspect",{"_index":4417,"title":{},"content":{"139":{"position":[[307,10]]}},"keywords":{}}],["inspir",{"_index":2830,"title":{},"content":{"86":{"position":[[706,8]]}},"keywords":{}}],["instal",{"_index":106,"title":{"108":{"position":[[8,10]]}},"content":{"2":{"position":[[449,10]]},"3":{"position":[[1272,7]]},"108":{"position":[[241,10],[285,12],[430,7],[496,7],[520,7]]},"113":{"position":[[10,7]]},"125":{"position":[[3138,7],[7644,9]]},"134":{"position":[[17,9]]},"176":{"position":[[339,9]]}},"keywords":{}}],["instanc",{"_index":3647,"title":{},"content":{"105":{"position":[[2562,9]]},"127":{"position":[[484,8]]},"129":{"position":[[899,8],[955,8],[1103,8],[1322,9],[1714,9],[1837,9],[1904,9],[2091,8],[2730,8]]},"130":{"position":[[306,8]]}},"keywords":{}}],["instantiatestream",{"_index":4110,"title":{},"content":{"125":{"position":[[5163,20],[5452,20]]}},"keywords":{}}],["instead",{"_index":89,"title":{},"content":{"2":{"position":[[219,8]]},"4":{"position":[[171,8]]},"30":{"position":[[9536,7]]},"34":{"position":[[3671,8]]},"45":{"position":[[1012,8]]},"74":{"position":[[1248,8]]},"86":{"position":[[282,7]]},"88":{"position":[[710,8],[2371,7]]},"92":{"position":[[64,8],[82,7]]},"93":{"position":[[4125,8]]},"97":{"position":[[843,8],[2619,8],[2687,7],[5679,7],[5704,7]]},"101":{"position":[[206,8]]},"125":{"position":[[1643,8],[5078,8]]},"129":{"position":[[914,7]]},"132":{"position":[[971,8]]},"135":{"position":[[299,8]]},"139":{"position":[[296,7]]},"152":{"position":[[203,8],[901,8]]},"160":{"position":[[1080,8]]},"172":{"position":[[2631,7]]},"183":{"position":[[776,8]]},"189":{"position":[[951,7]]},"194":{"position":[[145,8],[778,7]]}},"keywords":{}}],["instinct",{"_index":4621,"title":{},"content":{"158":{"position":[[188,9]]}},"keywords":{}}],["instruct",{"_index":3070,"title":{},"content":{"90":{"position":[[5308,9]]},"108":{"position":[[298,12]]},"128":{"position":[[984,12]]},"174":{"position":[[331,13]]},"181":{"position":[[185,11],[312,12],[442,11],[618,13]]},"192":{"position":[[618,12],[696,11]]},"193":{"position":[[295,12],[3496,12]]},"195":{"position":[[490,10]]},"196":{"position":[[1088,11],[1232,12],[1422,11],[1643,12],[1714,11],[1845,12]]}},"keywords":{}}],["int",{"_index":4226,"title":{},"content":{"127":{"position":[[226,3],[635,3],[750,3],[1161,3],[1285,3]]},"128":{"position":[[259,3],[272,3]]},"188":{"position":[[3529,3]]},"189":{"position":[[977,5],[1096,4],[1107,4],[1366,4],[1377,4],[3090,4],[3101,4]]},"199":{"position":[[116,3],[191,4],[276,3]]}},"keywords":{}}],["int((array.shape[1",{"_index":2979,"title":{},"content":{"90":{"position":[[898,19],[2283,19]]}},"keywords":{}}],["int(birthday_heartbeat",{"_index":2489,"title":{},"content":{"64":{"position":[[1642,23]]}},"keywords":{}}],["int(date.timestamp",{"_index":1472,"title":{},"content":{"30":{"position":[[8941,21]]}},"keywords":{}}],["int32",{"_index":3697,"title":{},"content":{"110":{"position":[[477,7],[490,7]]},"113":{"position":[[2039,5]]}},"keywords":{}}],["integ",{"_index":4242,"title":{},"content":{"127":{"position":[[1296,7],[1404,7]]},"193":{"position":[[949,7]]}},"keywords":{}}],["integer.valueof(x",{"_index":4243,"title":{},"content":{"127":{"position":[[1308,19]]}},"keywords":{}}],["integr",{"_index":293,"title":{},"content":{"4":{"position":[[1378,9]]},"101":{"position":[[846,9]]},"188":{"position":[[106,10]]}},"keywords":{}}],["intend",{"_index":1679,"title":{},"content":{"36":{"position":[[85,8]]},"55":{"position":[[133,8]]},"86":{"position":[[646,8]]},"90":{"position":[[87,7],[5134,8]]},"97":{"position":[[2737,7]]},"110":{"position":[[103,8]]},"125":{"position":[[2063,8]]},"160":{"position":[[3645,9]]},"165":{"position":[[124,7]]}},"keywords":{}}],["intent",{"_index":3573,"title":{},"content":{"104":{"position":[[2009,10]]},"132":{"position":[[53,9]]}},"keywords":{}}],["interact",{"_index":3863,"title":{},"content":{"120":{"position":[[891,8]]},"152":{"position":[[225,9]]},"160":{"position":[[134,8],[2113,11]]},"172":{"position":[[746,11],[952,9]]},"173":{"position":[[121,9]]},"188":{"position":[[467,9]]},"190":{"position":[[282,11]]}},"keywords":{}}],["interest",{"_index":499,"title":{"33":{"position":[[0,11]]},"40":{"position":[[12,11]]}},"content":{"10":{"position":[[388,8]]},"24":{"position":[[2904,12]]},"25":{"position":[[2725,11]]},"28":{"position":[[107,10],[427,10],[526,11]]},"30":{"position":[[695,10],[7910,11]]},"32":{"position":[[144,11]]},"33":{"position":[[71,11]]},"40":{"position":[[892,12],[1200,11],[2104,11],[3083,11],[3210,11]]},"41":{"position":[[226,10],[590,11]]},"44":{"position":[[1900,10]]},"45":{"position":[[3286,11]]},"54":{"position":[[38,11],[123,10]]},"57":{"position":[[244,10]]},"58":{"position":[[887,11]]},"59":{"position":[[200,10]]},"69":{"position":[[98,11]]},"72":{"position":[[255,11]]},"74":{"position":[[306,11]]},"89":{"position":[[1005,11]]},"93":{"position":[[948,11]]},"95":{"position":[[275,11]]},"102":{"position":[[422,10]]},"103":{"position":[[2264,11]]},"104":{"position":[[593,11],[1587,11],[2029,11]]},"106":{"position":[[959,11]]},"117":{"position":[[78,10]]},"124":{"position":[[382,11]]},"125":{"position":[[2126,11],[9713,10]]},"129":{"position":[[296,11],[456,11],[1202,11]]},"148":{"position":[[548,10]]},"156":{"position":[[1019,11]]},"159":{"position":[[23,11]]},"163":{"position":[[2163,12],[2343,10]]},"176":{"position":[[238,10]]},"178":{"position":[[237,11]]},"199":{"position":[[468,11]]}},"keywords":{}}],["interestingli",{"_index":3875,"title":{},"content":{"121":{"position":[[168,14]]},"195":{"position":[[99,13]]}},"keywords":{}}],["interfac",{"_index":4146,"title":{},"content":{"125":{"position":[[7297,9]]},"163":{"position":[[1167,9]]},"174":{"position":[[997,11]]}},"keywords":{}}],["interface_id",{"_index":4785,"title":{},"content":{"163":{"position":[[1870,13]]}},"keywords":{}}],["interior",{"_index":5076,"title":{"186":{"position":[[0,8]]}},"content":{"179":{"position":[[797,8]]},"186":{"position":[[132,8],[432,8],[532,8]]}},"keywords":{}}],["intermedi",{"_index":5281,"title":{},"content":{"193":{"position":[[1177,12]]}},"keywords":{}}],["internet",{"_index":2386,"title":{},"content":{"61":{"position":[[2062,10]]},"97":{"position":[[2841,9]]}},"keywords":{}}],["interpol",{"_index":495,"title":{},"content":{"10":{"position":[[320,13]]}},"keywords":{}}],["interpolation)μ\\mu",{"_index":330,"title":{},"content":{"6":{"position":[[419,19]]}},"keywords":{}}],["interpret",{"_index":3127,"title":{},"content":{"91":{"position":[[2548,14]]},"92":{"position":[[360,14]]},"188":{"position":[[671,11]]}},"keywords":{}}],["interrupt",{"_index":4940,"title":{},"content":{"173":{"position":[[155,10],[873,11],[1603,11],[1622,10],[1814,10],[1867,10]]}},"keywords":{}}],["interv",{"_index":3022,"title":{},"content":{"90":{"position":[[3303,8]]}},"keywords":{}}],["interview",{"_index":4501,"title":{},"content":{"150":{"position":[[718,12]]}},"keywords":{}}],["interweb",{"_index":3303,"title":{},"content":{"95":{"position":[[113,10]]}},"keywords":{}}],["intimid",{"_index":3788,"title":{},"content":{"115":{"position":[[2576,13]]}},"keywords":{}}],["intowhil",{"_index":4091,"title":{},"content":{"125":{"position":[[4126,9]]}},"keywords":{}}],["intraday",{"_index":2398,"title":{},"content":{"62":{"position":[[237,8]]}},"keywords":{}}],["intraday']['dataset",{"_index":2420,"title":{},"content":{"62":{"position":[[1005,22]]}},"keywords":{}}],["introduc",{"_index":628,"title":{},"content":{"14":{"position":[[122,9]]},"90":{"position":[[42,9]]},"198":{"position":[[479,9]]}},"keywords":{}}],["introduct",{"_index":3462,"title":{"101":{"position":[[8,12]]}},"content":{},"keywords":{}}],["intuit",{"_index":1127,"title":{},"content":{"24":{"position":[[3142,11]]},"32":{"position":[[1045,9]]},"40":{"position":[[2299,12]]},"83":{"position":[[354,6]]}},"keywords":{}}],["invalid",{"_index":3109,"title":{},"content":{"91":{"position":[[1991,7]]},"93":{"position":[[4404,7]]},"115":{"position":[[560,10],[2947,7]]},"129":{"position":[[2532,7]]}},"keywords":{}}],["invalid_ev",{"_index":3145,"title":{},"content":{"91":{"position":[[3404,14]]}},"keywords":{}}],["invalid_events.append((tick",{"_index":3152,"title":{},"content":{"91":{"position":[[4060,30]]}},"keywords":{}}],["invalid_tick",{"_index":3277,"title":{},"content":{"93":{"position":[[4671,15]]}},"keywords":{}}],["invalid_tickers.append(tick",{"_index":3290,"title":{},"content":{"93":{"position":[[5033,30],[5448,30]]}},"keywords":{}}],["invent",{"_index":2295,"title":{},"content":{"55":{"position":[[27,8]]}},"keywords":{}}],["invers",{"_index":1128,"title":{},"content":{"24":{"position":[[3171,7]]},"136":{"position":[[974,9]]}},"keywords":{}}],["invest",{"_index":1518,"title":{"37":{"position":[[24,10]]}},"content":{"32":{"position":[[382,6],[619,6],[778,10],[1198,9],[1312,6],[2099,6],[2191,6]]},"33":{"position":[[278,6],[690,6],[826,7],[861,10],[1063,6],[1117,6],[1176,10]]},"34":{"position":[[31,10],[103,10],[230,6],[323,6],[494,6],[1800,8],[1918,9],[1994,9],[2167,9],[2195,8],[2206,10],[2394,9],[2470,9],[2675,10],[2927,9],[3081,6],[3168,6],[3290,12],[3452,9],[3516,6],[3681,12],[3843,9]]},"35":{"position":[[18,10],[67,6],[253,9]]},"36":{"position":[[126,10]]},"38":{"position":[[150,7],[231,10],[363,10],[546,8],[590,9],[850,8],[940,8],[990,9],[1067,8]]},"39":{"position":[[1053,8],[1135,9],[1208,9],[1378,9],[1406,8],[1498,9],[1616,9],[1689,9],[1736,9],[1963,9],[2125,9]]},"40":{"position":[[3569,11]]}},"keywords":{}}],["invested.sum",{"_index":1738,"title":{},"content":{"39":{"position":[[1546,14]]}},"keywords":{}}],["investig",{"_index":1516,"title":{},"content":{"32":{"position":[[168,12]]}},"keywords":{}}],["investments[1",{"_index":1649,"title":{},"content":{"34":{"position":[[2842,14]]}},"keywords":{}}],["investor",{"_index":3193,"title":{},"content":{"93":{"position":[[732,9]]}},"keywords":{}}],["invoc",{"_index":4447,"title":{},"content":{"144":{"position":[[60,11]]}},"keywords":{}}],["invok",{"_index":3699,"title":{},"content":{"111":{"position":[[183,6]]},"139":{"position":[[972,6]]},"140":{"position":[[264,8]]},"143":{"position":[[568,6]]},"197":{"position":[[1115,8],[1306,8]]}},"keywords":{}}],["involv",{"_index":2092,"title":{},"content":{"51":{"position":[[859,9]]},"155":{"position":[[836,7]]},"174":{"position":[[1040,9]]},"179":{"position":[[780,8]]},"198":{"position":[[848,9]]}},"keywords":{}}],["involvingcomput",{"_index":3852,"title":{},"content":{"120":{"position":[[478,18]]}},"keywords":{}}],["io/isomorph",{"_index":4074,"title":{},"content":{"125":{"position":[[3085,13]]}},"keywords":{}}],["ipython.display",{"_index":705,"title":{},"content":{"17":{"position":[[58,15]]},"103":{"position":[[447,15]]}},"keywords":{}}],["iresult<&[u8",{"_index":4781,"title":{},"content":{"163":{"position":[[1790,21]]}},"keywords":{}}],["iron",{"_index":3300,"title":{},"content":{"95":{"position":[[20,4]]},"97":{"position":[[792,4],[2269,4],[3200,4],[5906,4]]}},"keywords":{}}],["iron'",{"_index":3426,"title":{},"content":{"97":{"position":[[5570,6]]}},"keywords":{}}],["iron::ironerror>",{"_index":3387,"title":{},"content":{"97":{"position":[[1987,19]]}},"keywords":{}}],["iron::request<'r",{"_index":3385,"title":{},"content":{"97":{"position":[[1913,20]]}},"keywords":{}}],["ironresult<response>",{"_index":3330,"title":{},"content":{"96":{"position":[[697,26],[1116,26],[1646,26],[2192,26]]},"97":{"position":[[1527,26],[3683,26]]}},"keywords":{}}],["irrelevant.it'",{"_index":1577,"title":{},"content":{"33":{"position":[[541,15]]}},"keywords":{}}],["irwin",{"_index":2574,"title":{},"content":{"68":{"position":[[972,5]]}},"keywords":{}}],["is_portfolio",{"_index":830,"title":{},"content":{"20":{"position":[[1784,12],[2053,12]]}},"keywords":{}}],["is_profit",{"_index":1619,"title":{},"content":{"34":{"position":[[1408,13]]}},"keywords":{}}],["is_profitable(close_vals[day",{"_index":1631,"title":{},"content":{"34":{"position":[[1887,30],[2363,30]]},"39":{"position":[[1102,28],[1583,28],[1930,28]]}},"keywords":{}}],["is_profitable(current_pric",{"_index":1725,"title":{},"content":{"39":{"position":[[606,28]]}},"keywords":{}}],["is_profitable(open_vals[day",{"_index":1732,"title":{},"content":{"39":{"position":[[1178,29],[1659,29]]}},"keywords":{}}],["is_profitable(open_vals[day+1",{"_index":1633,"title":{},"content":{"34":{"position":[[1962,31],[2438,31]]}},"keywords":{}}],["isaiah26",{"_index":2227,"title":{},"content":{"53":{"position":[[730,9]]}},"keywords":{}}],["isdead",{"_index":4408,"title":{},"content":{"137":{"position":[[197,7]]}},"keywords":{}}],["isessenti",{"_index":4846,"title":{},"content":{"166":{"position":[[630,13]]}},"keywords":{}}],["ishar",{"_index":3248,"title":{},"content":{"93":{"position":[[3065,8]]}},"keywords":{}}],["isn't",{"_index":229,"title":{},"content":{"4":{"position":[[154,5]]},"24":{"position":[[3419,5]]},"25":{"position":[[2766,5]]},"30":{"position":[[7273,5]]},"43":{"position":[[903,5]]},"96":{"position":[[577,5]]},"97":{"position":[[797,5]]},"112":{"position":[[744,5]]},"125":{"position":[[271,5],[4550,5]]},"148":{"position":[[281,5]]},"153":{"position":[[15,5]]},"163":{"position":[[246,5],[2153,5]]},"170":{"position":[[113,5]]},"184":{"position":[[948,5]]},"193":{"position":[[1036,5]]},"199":{"position":[[603,5]]}},"keywords":{}}],["iso_str",{"_index":3122,"title":{},"content":{"91":{"position":[[2345,7]]}},"keywords":{}}],["isol",{"_index":4949,"title":{},"content":{"173":{"position":[[764,8]]}},"keywords":{}}],["isolcpuskernel",{"_index":4946,"title":{},"content":{"173":{"position":[[618,15]]}},"keywords":{}}],["isomorph",{"_index":4001,"title":{"125":{"position":[[0,10]]}},"content":{},"keywords":{}}],["isomorphic_rust/perci",{"_index":4076,"title":{},"content":{"125":{"position":[[3111,21]]}},"keywords":{}}],["isp",{"_index":5005,"title":{},"content":{"175":{"position":[[342,3]]}},"keywords":{}}],["issu",{"_index":100,"title":{"96":{"position":[[0,5]]},"97":{"position":[[0,5]]}},"content":{"2":{"position":[[375,6]]},"15":{"position":[[294,6]]},"22":{"position":[[2990,5]]},"28":{"position":[[1558,5],[1623,6],[2381,7],[2766,7],[3344,5],[3409,6],[4011,5],[4091,6]]},"30":{"position":[[2512,6]]},"34":{"position":[[164,6]]},"38":{"position":[[442,7],[807,5]]},"40":{"position":[[1325,6]]},"44":{"position":[[1085,6]]},"46":{"position":[[82,5],[232,6]]},"53":{"position":[[1794,6]]},"63":{"position":[[15,5]]},"76":{"position":[[1415,6]]},"88":{"position":[[633,6]]},"90":{"position":[[3453,6]]},"91":{"position":[[3277,6],[3813,7],[3867,6]]},"92":{"position":[[1089,6]]},"93":{"position":[[4048,6]]},"97":{"position":[[2474,6]]},"106":{"position":[[537,5]]},"121":{"position":[[1876,6]]},"122":{"position":[[142,6]]},"123":{"position":[[407,5]]},"125":{"position":[[1391,6],[1867,6],[3508,6],[3654,5],[4563,6],[7197,5],[8406,6],[9227,6],[10033,5]]},"158":{"position":[[497,7]]},"160":{"position":[[2023,5]]},"164":{"position":[[792,7],[1532,6]]},"165":{"position":[[497,7]]},"173":{"position":[[1424,6],[1595,6]]},"174":{"position":[[768,6]]},"188":{"position":[[4059,5]]},"199":{"position":[[759,5]]}},"keywords":{}}],["issue/pr",{"_index":3987,"title":{},"content":{"123":{"position":[[1077,8]]}},"keywords":{}}],["issue:what",{"_index":4381,"title":{},"content":{"135":{"position":[[625,10]]}},"keywords":{}}],["issuei",{"_index":4090,"title":{},"content":{"125":{"position":[[4115,6]]}},"keywords":{}}],["issues/pr",{"_index":3970,"title":{},"content":{"123":{"position":[[149,10],[274,10]]}},"keywords":{}}],["it"",{"_index":926,"title":{},"content":{"22":{"position":[[1184,8]]}},"keywords":{}}],["it'",{"_index":624,"title":{},"content":{"14":{"position":[[51,4]]},"24":{"position":[[511,4]]},"25":{"position":[[236,4]]},"29":{"position":[[302,4]]},"30":{"position":[[425,4],[4062,4]]},"32":{"position":[[413,4]]},"33":{"position":[[92,4],[717,4]]},"39":{"position":[[276,4]]},"41":{"position":[[281,4]]},"51":{"position":[[1494,4]]},"62":{"position":[[65,4]]},"63":{"position":[[42,4]]},"66":{"position":[[402,4],[629,4]]},"74":{"position":[[1164,4]]},"83":{"position":[[224,4]]},"89":{"position":[[454,4]]},"90":{"position":[[5336,4]]},"91":{"position":[[360,4]]},"95":{"position":[[426,4]]},"96":{"position":[[835,4]]},"97":{"position":[[576,4],[601,4],[3351,4]]},"98":{"position":[[742,4],[1177,4],[1194,4]]},"101":{"position":[[255,4],[938,4]]},"102":{"position":[[1445,4]]},"103":{"position":[[761,4]]},"104":{"position":[[943,4],[954,4],[1226,4],[1294,4],[1363,4],[1888,4]]},"106":{"position":[[145,4],[324,4],[983,4]]},"109":{"position":[[35,4]]},"111":{"position":[[5,4]]},"112":{"position":[[275,4]]},"113":{"position":[[90,4],[197,4],[1508,4]]},"120":{"position":[[1120,4]]},"121":{"position":[[242,4],[556,4],[1805,4]]},"122":{"position":[[338,4]]},"125":{"position":[[506,4],[3267,4],[8005,4],[9956,4]]},"127":{"position":[[1209,4]]},"129":{"position":[[5,4],[2673,4],[2773,4]]},"134":{"position":[[174,4]]},"135":{"position":[[80,4],[552,4]]},"139":{"position":[[356,4],[683,4],[842,4]]},"142":{"position":[[212,4]]},"145":{"position":[[336,4]]},"147":{"position":[[1,4]]},"148":{"position":[[102,4],[217,4]]},"150":{"position":[[949,4]]},"155":{"position":[[264,4],[1085,4]]},"156":{"position":[[146,4]]},"157":{"position":[[84,4]]},"158":{"position":[[142,4],[397,4]]},"159":{"position":[[67,4]]},"160":{"position":[[1437,4],[1689,4],[3181,4]]},"163":{"position":[[629,4],[2381,4]]},"164":{"position":[[5,4]]},"166":{"position":[[745,4]]},"172":{"position":[[1874,4]]},"173":{"position":[[399,4],[1587,4]]},"175":{"position":[[399,4]]},"178":{"position":[[172,4],[582,4]]},"179":{"position":[[152,4],[1765,4]]},"181":{"position":[[4,4],[572,4]]},"184":{"position":[[1184,4]]},"188":{"position":[[144,4]]},"189":{"position":[[1840,4]]},"190":{"position":[[19,4]]},"193":{"position":[[730,4]]},"195":{"position":[[947,4]]},"196":{"position":[[600,4]]},"197":{"position":[[1440,4]]},"198":{"position":[[452,4],[550,4],[662,4]]},"199":{"position":[[1595,4]]}},"keywords":{}}],["it'sthi",{"_index":4006,"title":{},"content":{"125":{"position":[[87,8]]}},"keywords":{}}],["item",{"_index":4459,"title":{},"content":{"145":{"position":[[293,5]]}},"keywords":{}}],["itemprop",{"_index":938,"title":{},"content":{"22":{"position":[[1423,12]]}},"keywords":{}}],["iter",{"_index":2400,"title":{"199":{"position":[[0,10]]}},"content":{"62":{"position":[[315,7]]},"75":{"position":[[356,9],[1091,10]]},"76":{"position":[[2368,11]]},"78":{"position":[[881,10]]},"82":{"position":[[256,10],[326,10],[396,10],[466,10],[536,10],[606,10],[676,10],[746,10],[816,10],[886,10]]},"96":{"position":[[1060,10]]},"159":{"position":[[184,8],[658,10]]},"172":{"position":[[1074,10]]},"199":{"position":[[366,9],[625,9],[812,9],[865,7],[923,8],[939,6],[1009,7],[1296,9],[1446,9],[1642,8]]}},"keywords":{}}],["iter(actual_word",{"_index":2103,"title":{},"content":{"51":{"position":[[1292,19]]}},"keywords":{}}],["iter_count",{"_index":2722,"title":{},"content":{"76":{"position":[[1956,10],[2422,10],[2448,10],[2467,10],[2570,11]]}},"keywords":{}}],["iteration.given",{"_index":2667,"title":{},"content":{"75":{"position":[[782,15]]}},"keywords":{}}],["itself",{"_index":1685,"title":{},"content":{"38":{"position":[[13,6]]},"68":{"position":[[943,6]]},"88":{"position":[[3806,6]]},"93":{"position":[[392,6]]},"108":{"position":[[18,6]]},"116":{"position":[[2990,6]]},"117":{"position":[[267,6]]},"136":{"position":[[561,7]]},"160":{"position":[[364,6],[1874,6]]},"161":{"position":[[1556,6]]},"165":{"position":[[789,6]]},"199":{"position":[[932,6]]}},"keywords":{}}],["iwv",{"_index":3245,"title":{},"content":{"93":{"position":[[2968,4]]}},"keywords":{}}],["i}d(0,t)=d(0,t−1)⋅fi−1,i",{"_index":468,"title":{},"content":{"9":{"position":[[455,25]]}},"keywords":{}}],["i}fi−1,i",{"_index":470,"title":{},"content":{"9":{"position":[[502,9]]}},"keywords":{}}],["j",{"_index":2104,"title":{},"content":{"51":{"position":[[1332,1],[1361,1]]},"85":{"position":[[284,1]]}},"keywords":{}}],["jan_92_jan_16",{"_index":2473,"title":{},"content":{"64":{"position":[[962,13],[1055,13],[1668,14]]}},"keywords":{}}],["januari",{"_index":1851,"title":{},"content":{"41":{"position":[[271,7]]},"62":{"position":[[134,7],[1739,7]]},"64":{"position":[[227,7],[400,7],[417,7],[1095,7],[1112,7],[1355,7],[2036,7]]},"65":{"position":[[2165,7]]}},"keywords":{}}],["java",{"_index":3447,"title":{"127":{"position":[[20,7]]}},"content":{"98":{"position":[[593,6]]},"121":{"position":[[48,4]]},"127":{"position":[[75,4],[116,5],[140,5],[320,5],[436,4],[543,4]]},"128":{"position":[[1776,4]]},"129":{"position":[[1050,6]]},"160":{"position":[[1029,6]]},"172":{"position":[[492,4],[506,4],[1089,4],[1591,4],[1809,5],[2203,6]]}},"keywords":{}}],["java'",{"_index":4235,"title":{},"content":{"127":{"position":[[837,6]]}},"keywords":{}}],["java,lambda",{"_index":5325,"title":{},"content":{"196":{"position":[[95,11]]}},"keywords":{}}],["javascript",{"_index":47,"title":{},"content":{"1":{"position":[[540,12]]},"3":{"position":[[112,10]]},"125":{"position":[[15,10],[313,10],[1194,10],[1707,10],[3784,11],[6148,10],[6603,10],[6694,10],[7268,10],[10629,11]]},"196":{"position":[[359,10]]}},"keywords":{}}],["javascript,i",{"_index":4012,"title":{},"content":{"125":{"position":[[295,12]]}},"keywords":{}}],["jemalloc,tcmalloc",{"_index":4916,"title":{},"content":{"172":{"position":[[1233,19]]}},"keywords":{}}],["jerri",{"_index":2266,"title":{},"content":{"53":{"position":[[1353,5]]}},"keywords":{}}],["jit",{"_index":4930,"title":{},"content":{"172":{"position":[[2161,3],[2298,3],[2318,3],[2468,3]]},"189":{"position":[[224,4],[484,4],[3033,3]]}},"keywords":{}}],["jit(nogil=tru",{"_index":5255,"title":{},"content":{"189":{"position":[[2968,16]]}},"keywords":{}}],["jit(nopython=tru",{"_index":5235,"title":{},"content":{"189":{"position":[[1045,19],[1329,19],[3037,19]]}},"keywords":{}}],["jitclass",{"_index":5261,"title":{},"content":{"190":{"position":[[397,9]]}},"keywords":{}}],["jnj",{"_index":313,"title":{},"content":{"6":{"position":[[210,3]]}},"keywords":{}}],["job",{"_index":3563,"title":{},"content":{"104":{"position":[[964,3]]},"121":{"position":[[217,3]]},"125":{"position":[[876,3]]},"150":{"position":[[968,4]]},"193":{"position":[[750,3],[849,4]]},"198":{"position":[[172,4]]}},"keywords":{}}],["join((first",{"_index":2178,"title":{},"content":{"52":{"position":[[399,14]]}},"keywords":{}}],["join((tweet",{"_index":2192,"title":{},"content":{"52":{"position":[[1148,14]]}},"keywords":{}}],["join(results[result",{"_index":2153,"title":{},"content":{"51":{"position":[[3724,22]]}},"keywords":{}}],["joke",{"_index":1680,"title":{},"content":{"36":{"position":[[99,4]]}},"keywords":{}}],["jona",{"_index":2252,"title":{},"content":{"53":{"position":[[1168,5],[2111,5]]}},"keywords":{}}],["jone",{"_index":994,"title":{},"content":{"23":{"position":[[115,5]]}},"keywords":{}}],["joy",{"_index":35,"title":{},"content":{"1":{"position":[[390,4]]}},"keywords":{}}],["js",{"_index":4188,"title":{},"content":{"125":{"position":[[9591,2]]}},"keywords":{}}],["jsx",{"_index":44,"title":{},"content":{"1":{"position":[[518,3]]}},"keywords":{}}],["judg",{"_index":3578,"title":{},"content":{"105":{"position":[[328,6]]}},"keywords":{}}],["judgment",{"_index":1575,"title":{},"content":{"33":{"position":[[456,8]]}},"keywords":{}}],["juli",{"_index":1259,"title":{},"content":{"28":{"position":[[1890,8],[4077,4]]},"30":{"position":[[1407,8],[7480,4]]}},"keywords":{}}],["julia",{"_index":1714,"title":{},"content":{"39":{"position":[[338,5]]}},"keywords":{}}],["july'",{"_index":1280,"title":{},"content":{"28":{"position":[[2389,6]]}},"keywords":{}}],["jump",{"_index":2232,"title":{},"content":{"53":{"position":[[875,4]]}},"keywords":{}}],["justconcurr",{"_index":5265,"title":{},"content":{"190":{"position":[[1005,16]]}},"keywords":{}}],["justif",{"_index":1684,"title":{"38":{"position":[[12,14]]},"84":{"position":[[0,13]]}},"content":{"73":{"position":[[391,14]]}},"keywords":{}}],["jvm",{"_index":4908,"title":{},"content":{"172":{"position":[[525,3]]}},"keywords":{}}],["kaput",{"_index":2531,"title":{},"content":{"65":{"position":[[2391,5],[2438,5]]}},"keywords":{}}],["keep",{"_index":16,"title":{},"content":{"1":{"position":[[155,7]]},"35":{"position":[[470,7]]},"76":{"position":[[2099,4]]},"97":{"position":[[1399,4],[5235,4]]},"115":{"position":[[2621,5]]},"116":{"position":[[2465,5]]},"118":{"position":[[22,4],[341,4]]},"121":{"position":[[1969,4]]},"122":{"position":[[1448,7]]},"123":{"position":[[117,4],[269,4],[793,7],[867,7]]},"125":{"position":[[3906,4],[10263,4]]},"150":{"position":[[662,4]]},"158":{"position":[[301,4]]},"160":{"position":[[633,8],[4026,4]]},"161":{"position":[[1018,5]]},"172":{"position":[[612,4]]},"173":{"position":[[1263,4]]},"188":{"position":[[2829,4]]},"193":{"position":[[980,4]]},"196":{"position":[[1304,5]]}},"keywords":{}}],["kept",{"_index":2838,"title":{},"content":{"88":{"position":[[55,4]]},"125":{"position":[[8046,4]]}},"keywords":{}}],["kernel",{"_index":4938,"title":{"173":{"position":[[0,7]]}},"content":{"173":{"position":[[335,6],[1166,7],[1182,6],[2052,6]]},"174":{"position":[[708,6],[1182,6],[1224,6]]},"195":{"position":[[476,6]]}},"keywords":{}}],["kernelnetwork",{"_index":4994,"title":{},"content":{"174":{"position":[[1090,13]]}},"keywords":{}}],["kernelperf",{"_index":4924,"title":{},"content":{"172":{"position":[[1635,10]]}},"keywords":{}}],["key",{"_index":1054,"title":{},"content":{"24":{"position":[[1142,3]]},"25":{"position":[[862,3]]},"30":{"position":[[8746,3]]},"93":{"position":[[4550,4]]}},"keywords":{}}],["key.to_datetim",{"_index":1052,"title":{},"content":{"24":{"position":[[1106,19]]},"25":{"position":[[826,19]]}},"keywords":{}}],["keyerror",{"_index":3138,"title":{},"content":{"91":{"position":[[3114,9]]},"92":{"position":[[926,9]]}},"keywords":{}}],["keys=list(results.key",{"_index":1780,"title":{},"content":{"39":{"position":[[3309,26]]}},"keywords":{}}],["keyword",{"_index":3421,"title":{},"content":{"97":{"position":[[4775,7]]}},"keywords":{}}],["kick",{"_index":528,"title":{},"content":{"12":{"position":[[319,4]]},"172":{"position":[[2481,6]]}},"keywords":{}}],["kid",{"_index":3979,"title":{},"content":{"123":{"position":[[656,3]]},"165":{"position":[[17,3]]}},"keywords":{}}],["kilobyt",{"_index":5320,"title":{},"content":{"195":{"position":[[251,9],[327,9]]}},"keywords":{}}],["kind",{"_index":126,"title":{},"content":{"2":{"position":[[778,4]]},"51":{"position":[[1892,4]]},"66":{"position":[[14,4]]},"153":{"position":[[377,4]]}},"keywords":{}}],["kinda",{"_index":3848,"title":{},"content":{"120":{"position":[[167,5]]},"125":{"position":[[4075,5]]}},"keywords":{}}],["kindli",{"_index":3975,"title":{},"content":{"123":{"position":[[335,8]]}},"keywords":{}}],["knew",{"_index":2330,"title":{"88":{"position":[[16,5]]}},"content":{"58":{"position":[[277,4]]},"64":{"position":[[1534,5]]},"136":{"position":[[8,4]]},"160":{"position":[[170,4]]}},"keywords":{}}],["knife",{"_index":2234,"title":{},"content":{"53":{"position":[[900,5]]}},"keywords":{}}],["know",{"_index":726,"title":{},"content":{"18":{"position":[[18,4]]},"28":{"position":[[648,5]]},"30":{"position":[[709,4]]},"32":{"position":[[1237,4]]},"33":{"position":[[809,4]]},"34":{"position":[[404,4],[470,4]]},"35":{"position":[[82,4]]},"39":{"position":[[1828,4]]},"40":{"position":[[1080,4]]},"45":{"position":[[1,7],[528,4]]},"53":{"position":[[378,4],[1398,4]]},"54":{"position":[[137,4]]},"61":{"position":[[25,4],[46,4],[170,4],[1001,4],[1157,4]]},"65":{"position":[[29,4],[392,5],[1393,4]]},"66":{"position":[[39,5],[558,4]]},"74":{"position":[[47,5],[983,4]]},"93":{"position":[[543,5],[747,4],[1006,7]]},"96":{"position":[[1881,4],[2025,4]]},"97":{"position":[[4030,5],[5815,4]]},"108":{"position":[[201,4],[789,4]]},"112":{"position":[[1645,4]]},"113":{"position":[[2072,4]]},"117":{"position":[[664,4]]},"122":{"position":[[1353,4]]},"124":{"position":[[302,4],[732,5]]},"125":{"position":[[1503,7],[2157,4],[10332,7],[10771,6]]},"130":{"position":[[561,4]]},"132":{"position":[[150,5]]},"139":{"position":[[158,4]]},"140":{"position":[[68,5]]},"148":{"position":[[570,4]]},"159":{"position":[[234,4]]},"160":{"position":[[2729,4],[4322,4]]},"163":{"position":[[613,4]]},"173":{"position":[[1021,7]]},"174":{"position":[[290,5]]},"175":{"position":[[1562,4]]},"176":{"position":[[618,4]]},"193":{"position":[[1609,5]]}},"keywords":{}}],["knowledg",{"_index":1318,"title":{},"content":{"29":{"position":[[426,10]]},"150":{"position":[[308,9]]},"160":{"position":[[3006,9]]}},"keywords":{}}],["known",{"_index":2629,"title":{},"content":{"73":{"position":[[887,5]]},"115":{"position":[[3115,5]]},"125":{"position":[[10050,5]]}},"keywords":{}}],["kwarg",{"_index":934,"title":{},"content":{"22":{"position":[[1303,10],[1338,9]]},"93":{"position":[[1571,10],[1606,9]]}},"keywords":{}}],["l",{"_index":789,"title":{},"content":{"20":{"position":[[748,3]]},"199":{"position":[[386,1],[405,2]]}},"keywords":{}}],["l(x",{"_index":2647,"title":{},"content":{"74":{"position":[[1119,4]]}},"keywords":{}}],["l(x)={p2x=2p3x=3…p11x=11p12x=12\\begin{align",{"_index":2634,"title":{},"content":{"74":{"position":[[509,45]]}},"keywords":{}}],["l(x)=∏i=1nl(x)\\begin{align",{"_index":2644,"title":{},"content":{"74":{"position":[[1045,28]]}},"keywords":{}}],["l(x)l(x)l(x",{"_index":2652,"title":{},"content":{"74":{"position":[[1390,12]]}},"keywords":{}}],["l__unnamed_1",{"_index":5096,"title":{},"content":{"180":{"position":[[479,15]]},"197":{"position":[[371,12]]}},"keywords":{}}],["l__unnamed_2",{"_index":5344,"title":{},"content":{"197":{"position":[[517,12]]}},"keywords":{}}],["label",{"_index":1908,"title":{},"content":{"44":{"position":[[377,6],[516,6]]}},"keywords":{}}],["label="$\\pm",{"_index":3000,"title":{},"content":{"90":{"position":[[1609,17],[1758,17],[2902,17]]}},"keywords":{}}],["label="gaussian",{"_index":2006,"title":{},"content":{"45":{"position":[[2262,20],[3042,20]]}},"keywords":{}}],["label="invers",{"_index":2013,"title":{},"content":{"45":{"position":[[2394,19],[3174,19]]}},"keywords":{}}],["label="na",{"_index":2010,"title":{},"content":{"45":{"position":[[2327,17],[3107,17]]}},"keywords":{}}],["label='earn",{"_index":2883,"title":{},"content":{"88":{"position":[[1605,15],[1932,15],[3062,15],[3447,15]]},"91":{"position":[[823,15],[1293,15]]}},"keywords":{}}],["label='max",{"_index":3008,"title":{},"content":{"90":{"position":[[1959,10],[3098,10]]}},"keywords":{}}],["label='midpoint",{"_index":3084,"title":{},"content":{"91":{"position":[[700,17],[1164,17]]}},"keywords":{}}],["label=fals",{"_index":441,"title":{},"content":{"7":{"position":[[1283,13]]}},"keywords":{}}],["lack",{"_index":3370,"title":{},"content":{"97":{"position":[[1042,4],[2805,4]]},"100":{"position":[[211,4]]},"160":{"position":[[3020,4]]}},"keywords":{}}],["lackadais",{"_index":4345,"title":{},"content":{"132":{"position":[[317,13]]}},"keywords":{}}],["lambda",{"_index":748,"title":{},"content":{"19":{"position":[[288,6]]},"20":{"position":[[242,6],[1462,6],[1799,6],[1886,6]]},"39":{"position":[[564,6]]},"62":{"position":[[1057,6]]},"90":{"position":[[677,6]]}},"keywords":{}}],["land",{"_index":4127,"title":{},"content":{"125":{"position":[[5707,6],[11116,6]]},"175":{"position":[[108,4]]}},"keywords":{}}],["lang.org/std/sync/struct.once.html#method.call_onc",{"_index":5140,"title":{},"content":{"186":{"position":[[249,51]]}},"keywords":{}}],["lang/rust",{"_index":3745,"title":{},"content":{"113":{"position":[[1209,9]]}},"keywords":{}}],["languag",{"_index":3309,"title":{"122":{"position":[[14,9]]},"172":{"position":[[0,8]]}},"content":{"95":{"position":[[368,8]]},"98":{"position":[[352,9]]},"125":{"position":[[691,8],[730,8]]},"128":{"position":[[147,8]]},"130":{"position":[[240,8]]},"152":{"position":[[361,9]]},"160":{"position":[[355,8],[1019,9]]},"172":{"position":[[714,8],[943,8],[1461,9],[1757,9],[2098,9],[2322,10]]},"176":{"position":[[528,8]]},"188":{"position":[[37,8]]},"189":{"position":[[100,8]]},"193":{"position":[[615,9]]},"196":{"position":[[73,8]]},"198":{"position":[[567,8]]},"199":{"position":[[19,9]]}},"keywords":{}}],["larg",{"_index":525,"title":{},"content":{"12":{"position":[[137,7]]},"40":{"position":[[2331,5]]},"82":{"position":[[34,5]]},"89":{"position":[[788,5]]},"92":{"position":[[1483,5]]},"93":{"position":[[673,5],[1055,7]]},"105":{"position":[[46,5]]},"194":{"position":[[91,5]]}},"keywords":{}}],["large(u64",{"_index":5313,"title":{},"content":{"194":{"position":[[244,10]]}},"keywords":{}}],["largegoogle.com'",{"_index":4699,"title":{},"content":{"160":{"position":[[2913,17]]}},"keywords":{}}],["larger",{"_index":3649,"title":{},"content":{"105":{"position":[[3368,6]]},"111":{"position":[[811,6]]},"150":{"position":[[494,6]]}},"keywords":{}}],["largest",{"_index":765,"title":{},"content":{"20":{"position":[[208,7]]},"194":{"position":[[502,7]]}},"keywords":{}}],["last",{"_index":1372,"title":{},"content":{"30":{"position":[[2435,4]]},"33":{"position":[[529,4]]},"39":{"position":[[204,4]]},"45":{"position":[[2747,4]]},"50":{"position":[[213,4]]},"83":{"position":[[575,5]]},"96":{"position":[[2323,5]]},"97":{"position":[[6288,5]]},"125":{"position":[[4059,4]]},"135":{"position":[[65,4]]},"160":{"position":[[1154,4]]}},"keywords":{}}],["last_coupon",{"_index":678,"title":{},"content":{"15":{"position":[[942,11],[1341,12],[1363,11]]}},"keywords":{}}],["late",{"_index":1833,"title":{},"content":{"40":{"position":[[3171,4]]},"125":{"position":[[140,4]]},"130":{"position":[[319,4]]}},"keywords":{}}],["later",{"_index":58,"title":{},"content":{"1":{"position":[[651,5]]},"8":{"position":[[158,5]]},"30":{"position":[[7977,6]]},"41":{"position":[[252,5]]},"45":{"position":[[1514,6]]},"97":{"position":[[1452,6],[3766,5]]},"110":{"position":[[83,6]]},"113":{"position":[[895,5],[1054,6]]},"184":{"position":[[267,5]]}},"keywords":{}}],["launch",{"_index":4823,"title":{},"content":{"165":{"position":[[102,9]]}},"keywords":{}}],["law",{"_index":4407,"title":{},"content":{"137":{"position":[[193,3]]}},"keywords":{}}],["lay",{"_index":310,"title":{},"content":{"6":{"position":[[142,4]]}},"keywords":{}}],["layout",{"_index":4335,"title":{},"content":{"130":{"position":[[224,7]]},"152":{"position":[[402,7],[1340,7],[1348,7],[1521,7],[1529,7],[1644,8]]},"156":{"position":[[852,7],[1423,7],[1431,7],[1604,7],[1612,7],[1727,8]]},"172":{"position":[[1316,7],[1722,7]]},"193":{"position":[[3094,7]]}},"keywords":{}}],["lbyte_str.u",{"_index":4286,"title":{},"content":{"129":{"position":[[568,13]]}},"keywords":{}}],["lda",{"_index":1956,"title":{"45":{"position":[[33,4]]}},"content":{"45":{"position":[[683,3],[861,3]]}},"keywords":{}}],["lda/qda/svm",{"_index":1984,"title":{},"content":{"45":{"position":[[1496,11]]}},"keywords":{}}],["ldot",{"_index":2638,"title":{},"content":{"74":{"position":[[634,6]]},"85":{"position":[[295,7]]}},"keywords":{}}],["le",{"_index":786,"title":{},"content":{"20":{"position":[[710,3],[744,3]]}},"keywords":{}}],["le_u32",{"_index":4792,"title":{},"content":{"163":{"position":[[1978,7],[1986,7],[1994,7],[2002,7],[2010,7],[2018,7]]}},"keywords":{}}],["lea",{"_index":4284,"title":{},"content":{"129":{"position":[[552,3]]}},"keywords":{}}],["lead",{"_index":2273,"title":{},"content":{"53":{"position":[[1465,5]]},"72":{"position":[[534,5]]},"90":{"position":[[4278,7]]},"102":{"position":[[353,4]]},"106":{"position":[[1102,4]]},"125":{"position":[[7430,5]]},"130":{"position":[[120,5]]},"185":{"position":[[7,5]]},"189":{"position":[[2626,5]]}},"keywords":{}}],["leak",{"_index":3454,"title":{},"content":{"98":{"position":[[1050,7]]}},"keywords":{}}],["leap",{"_index":2454,"title":{},"content":{"64":{"position":[[351,4],[460,4],[687,4],[750,4]]},"65":{"position":[[369,4],[564,4],[615,4],[1420,4],[1637,4]]}},"keywords":{}}],["leap_day",{"_index":2472,"title":{},"content":{"64":{"position":[[948,9],[1044,10]]}},"keywords":{}}],["leap_day_count",{"_index":2467,"title":{},"content":{"64":{"position":[[821,14],[1011,14]]},"65":{"position":[[672,14],[1613,14]]}},"keywords":{}}],["learn",{"_index":217,"title":{"4":{"position":[[0,8]]},"119":{"position":[[7,7]]},"153":{"position":[[20,7]]}},"content":{"4":{"position":[[211,8],[1404,8]]},"73":{"position":[[201,8]]},"98":{"position":[[303,7]]},"102":{"position":[[98,9]]},"103":{"position":[[139,5]]},"125":{"position":[[10242,5]]},"132":{"position":[[785,7]]},"139":{"position":[[830,5]]},"160":{"position":[[799,5]]},"161":{"position":[[531,7],[1257,7]]}},"keywords":{}}],["leav",{"_index":297,"title":{},"content":{"4":{"position":[[1485,5]]},"38":{"position":[[776,5]]},"128":{"position":[[736,5]]},"161":{"position":[[1493,6]]},"198":{"position":[[151,5]]}},"keywords":{}}],["leave"",{"_index":4725,"title":{},"content":{"161":{"position":[[43,11]]}},"keywords":{}}],["led",{"_index":4008,"title":{},"content":{"125":{"position":[[111,3]]}},"keywords":{}}],["left",{"_index":2318,"title":{},"content":{"57":{"position":[[718,5]]},"64":{"position":[[2083,5]]},"65":{"position":[[804,5],[1229,5],[1326,5],[1525,4],[1574,5],[1918,4],[2060,4]]},"66":{"position":[[585,4],[791,5]]},"70":{"position":[[281,7],[455,7]]},"71":{"position":[[381,7],[555,7]]},"74":{"position":[[572,7]]},"90":{"position":[[4989,4]]},"91":{"position":[[3883,4]]},"117":{"position":[[1899,4]]},"134":{"position":[[109,4]]},"150":{"position":[[405,4]]}},"keywords":{}}],["left|\\omega\\right",{"_index":788,"title":{},"content":{"20":{"position":[[724,19]]}},"keywords":{}}],["legal",{"_index":3795,"title":{},"content":{"115":{"position":[[3091,6]]}},"keywords":{}}],["legend=c",{"_index":1277,"title":{},"content":{"28":{"position":[[2274,12],[3947,12]]}},"keywords":{}}],["legend=months_str[x",{"_index":1367,"title":{},"content":{"30":{"position":[[2212,21],[3697,21],[3920,21],[5476,21],[6777,21],[7000,21]]}},"keywords":{}}],["legitim",{"_index":2239,"title":{},"content":{"53":{"position":[[950,12],[1590,10]]},"76":{"position":[[1022,10]]}},"keywords":{}}],["len",{"_index":4773,"title":{},"content":{"163":{"position":[[1441,3],[1525,3]]}},"keywords":{}}],["len(b_class",{"_index":1906,"title":{},"content":{"44":{"position":[[296,12],[686,14]]}},"keywords":{}}],["len(component_byt",{"_index":3588,"title":{},"content":{"105":{"position":[[863,21]]}},"keywords":{}}],["len(compress",{"_index":3595,"title":{},"content":{"105":{"position":[[1122,15]]}},"keywords":{}}],["len(dist",{"_index":2167,"title":{},"content":{"51":{"position":[[4183,9]]}},"keywords":{}}],["len(elem",{"_index":3136,"title":{},"content":{"91":{"position":[[3056,10]]},"92":{"position":[[868,10]]}},"keywords":{}}],["len(elems.dropna()[elem",{"_index":3137,"title":{},"content":{"91":{"position":[[3072,24]]},"92":{"position":[[884,24]]}},"keywords":{}}],["len(first",{"_index":2189,"title":{},"content":{"52":{"position":[[885,10]]}},"keywords":{}}],["len(first_words_alpha",{"_index":2090,"title":{},"content":{"51":{"position":[[672,22]]}},"keywords":{}}],["len(fram",{"_index":1030,"title":{},"content":{"24":{"position":[[578,12]]},"25":{"position":[[303,12]]}},"keywords":{}}],["len(hashtag",{"_index":2124,"title":{},"content":{"51":{"position":[[2319,13]]},"52":{"position":[[898,13],[982,13]]}},"keywords":{}}],["len(hashtag_dist",{"_index":2131,"title":{},"content":{"51":{"position":[[2530,17]]}},"keywords":{}}],["len(list(filter(lambda",{"_index":1248,"title":{},"content":{"28":{"position":[[1483,22],[3274,22]]},"30":{"position":[[1844,22],[3193,22],[5108,22],[6262,22]]}},"keywords":{}}],["len(matches_dict[index][futur",{"_index":1084,"title":{},"content":{"24":{"position":[[2155,32]]},"25":{"position":[[1879,32]]}},"keywords":{}}],["len(month",{"_index":1365,"title":{},"content":{"30":{"position":[[2161,13],[3647,13],[3866,13],[5420,13],[6720,13],[6945,13]]}},"keywords":{}}],["len(recon.tobyt",{"_index":3607,"title":{},"content":{"105":{"position":[[1576,20]]}},"keywords":{}}],["len(sign",{"_index":3524,"title":{},"content":{"103":{"position":[[1009,11]]}},"keywords":{}}],["len(signal_byt",{"_index":3587,"title":{},"content":{"105":{"position":[[842,18]]}},"keywords":{}}],["len(tick",{"_index":835,"title":{},"content":{"20":{"position":[[1974,12]]}},"keywords":{}}],["len(tweet",{"_index":2190,"title":{},"content":{"52":{"position":[[969,10]]}},"keywords":{}}],["len(x.column",{"_index":1876,"title":{},"content":{"43":{"position":[[650,14]]}},"keywords":{}}],["len(x[0",{"_index":1768,"title":{},"content":{"39":{"position":[[2837,10],[2943,11]]}},"keywords":{}}],["len(x[c].uniqu",{"_index":1904,"title":{},"content":{"44":{"position":[[253,18]]}},"keywords":{}}],["length",{"_index":4771,"title":{},"content":{"163":{"position":[[1088,6]]},"166":{"position":[[392,6],[508,6]]}},"keywords":{}}],["length(investments))"",{"_index":1653,"title":{},"content":{"34":{"position":[[2937,29]]}},"keywords":{}}],["length(motion[1",{"_index":407,"title":{},"content":{"7":{"position":[[615,19]]}},"keywords":{}}],["length(motion[:,1",{"_index":408,"title":{},"content":{"7":{"position":[[639,19]]}},"keywords":{}}],["length(s0",{"_index":391,"title":{},"content":{"7":{"position":[[330,10]]}},"keywords":{}}],["length(term",{"_index":475,"title":{},"content":{"9":{"position":[[732,12]]}},"keywords":{}}],["length(year_pric",{"_index":568,"title":{},"content":{"13":{"position":[[736,19]]},"14":{"position":[[1593,19]]},"15":{"position":[[980,19]]}},"keywords":{}}],["less",{"_index":1409,"title":{},"content":{"30":{"position":[[5611,4]]},"45":{"position":[[975,4]]},"66":{"position":[[865,4]]},"76":{"position":[[1175,4]]},"165":{"position":[[1451,4]]},"173":{"position":[[1403,4]]},"189":{"position":[[1888,4]]}},"keywords":{}}],["lesson",{"_index":231,"title":{},"content":{"4":{"position":[[203,7]]},"161":{"position":[[564,8],[1275,7]]}},"keywords":{}}],["let",{"_index":2397,"title":{},"content":{"62":{"position":[[223,4]]},"93":{"position":[[368,7]]},"117":{"position":[[628,4]]},"160":{"position":[[3456,4]]}},"keywords":{}}],["let'",{"_index":307,"title":{},"content":{"6":{"position":[[86,5]]},"8":{"position":[[1,5]]},"9":{"position":[[45,5]]},"10":{"position":[[40,5]]},"11":{"position":[[95,5]]},"13":{"position":[[51,5]]},"14":{"position":[[1,5]]},"15":{"position":[[553,5]]},"23":{"position":[[163,5]]},"24":{"position":[[195,5]]},"25":{"position":[[123,5]]},"28":{"position":[[2802,5]]},"34":{"position":[[987,5],[1362,5],[3016,5],[3605,5]]},"38":{"position":[[395,5]]},"39":{"position":[[102,5]]},"40":{"position":[[1,5],[82,5],[558,5],[2573,5]]},"44":{"position":[[384,5]]},"45":{"position":[[1021,5],[2733,5]]},"51":{"position":[[77,5],[327,5],[1532,5],[1994,5],[2207,5],[3265,5]]},"52":{"position":[[87,5],[504,5]]},"57":{"position":[[628,5]]},"62":{"position":[[1771,5]]},"65":{"position":[[1332,5]]},"68":{"position":[[212,5]]},"69":{"position":[[76,5]]},"77":{"position":[[1,5]]},"88":{"position":[[2134,5],[2400,5]]},"91":{"position":[[4942,5]]},"96":{"position":[[229,5],[594,5],[1040,5],[1581,5]]},"97":{"position":[[3178,5],[4814,5]]},"103":{"position":[[368,5],[1542,5],[1906,5]]},"105":{"position":[[2652,5],[2838,5]]},"113":{"position":[[1558,5],[1751,5]]},"116":{"position":[[2347,5]]},"121":{"position":[[2748,5]]},"125":{"position":[[10906,5]]},"128":{"position":[[112,5],[1045,5]]},"129":{"position":[[363,5]]},"160":{"position":[[793,5],[3337,5]]},"184":{"position":[[7,5]]},"188":{"position":[[1464,5]]},"189":{"position":[[895,5]]}},"keywords":{}}],["level",{"_index":156,"title":{"128":{"position":[[4,5]]}},"content":{"3":{"position":[[456,6]]},"14":{"position":[[669,5]]},"20":{"position":[[895,6],[919,6]]},"34":{"position":[[542,5]]},"110":{"position":[[218,5]]},"121":{"position":[[1951,6]]},"127":{"position":[[1598,5]]},"128":{"position":[[374,5],[927,5]]},"176":{"position":[[1626,6]]}},"keywords":{}}],["level=1).hist",{"_index":1791,"title":{},"content":{"40":{"position":[[260,15],[1794,15],[2737,15]]}},"keywords":{}}],["level=1).plot",{"_index":1797,"title":{},"content":{"40":{"position":[[429,15],[1965,15],[2909,15]]}},"keywords":{}}],["leverag",{"_index":796,"title":{},"content":{"20":{"position":[[930,8],[1097,8],[1851,8]]},"34":{"position":[[2742,9],[2875,9],[3419,9],[3810,9],[3929,9]]},"38":{"position":[[110,8],[528,8],[832,8],[909,8],[964,10],[1179,9]]},"40":{"position":[[3350,9]]}},"keywords":{}}],["levien",{"_index":4643,"title":{},"content":{"159":{"position":[[1259,6]]}},"keywords":{}}],["lexic",{"_index":3743,"title":{},"content":{"113":{"position":[[1163,7]]}},"keywords":{}}],["lib.r",{"_index":4367,"title":{},"content":{"133":{"position":[[232,6]]}},"keywords":{}}],["liber",{"_index":3921,"title":{},"content":{"121":{"position":[[2369,10]]}},"keywords":{}}],["librari",{"_index":2068,"title":{},"content":{"51":{"position":[[24,7]]},"53":{"position":[[485,7]]},"95":{"position":[[25,7]]},"108":{"position":[[144,10]]},"109":{"position":[[555,7]]},"112":{"position":[[1250,7]]},"120":{"position":[[88,7],[129,7]]},"121":{"position":[[445,7]]},"122":{"position":[[366,8],[511,7],[570,7],[988,7],[1176,7]]},"124":{"position":[[154,7]]},"125":{"position":[[11146,9]]},"132":{"position":[[122,8]]},"155":{"position":[[596,7]]},"156":{"position":[[1776,7]]},"157":{"position":[[350,7]]},"159":{"position":[[1156,7]]},"163":{"position":[[431,7]]},"188":{"position":[[197,10]]}},"keywords":{}}],["library"",{"_index":3937,"title":{},"content":{"122":{"position":[[216,13],[1067,13]]}},"keywords":{}}],["libui",{"_index":4042,"title":{},"content":{"125":{"position":[[1315,6]]}},"keywords":{}}],["life",{"_index":2336,"title":{},"content":{"58":{"position":[[562,4],[582,4],[702,4]]},"63":{"position":[[124,5]]},"66":{"position":[[279,5]]},"123":{"position":[[762,5]]},"127":{"position":[[67,4]]},"150":{"position":[[169,4]]},"160":{"position":[[1198,4]]},"182":{"position":[[141,4]]}},"keywords":{}}],["lifetim",{"_index":2316,"title":{},"content":{"57":{"position":[[660,8]]},"58":{"position":[[782,8]]},"98":{"position":[[715,8]]},"113":{"position":[[1171,10]]},"117":{"position":[[1542,10]]},"152":{"position":[[60,8]]},"182":{"position":[[213,10]]}},"keywords":{}}],["lifetimeand",{"_index":3394,"title":{},"content":{"97":{"position":[[2543,11]]}},"keywords":{}}],["lift",{"_index":2070,"title":{},"content":{"51":{"position":[[61,8]]}},"keywords":{}}],["light",{"_index":2904,"title":{},"content":{"88":{"position":[[2388,6]]}},"keywords":{}}],["lighter",{"_index":4734,"title":{},"content":{"161":{"position":[[502,7]]}},"keywords":{}}],["lightli",{"_index":4253,"title":{},"content":{"128":{"position":[[425,7],[1250,7]]}},"keywords":{}}],["likebranch",{"_index":4977,"title":{},"content":{"174":{"position":[[155,10]]}},"keywords":{}}],["likecompil",{"_index":4711,"title":{},"content":{"160":{"position":[[3875,11]]}},"keywords":{}}],["likecriterion",{"_index":5050,"title":{},"content":{"176":{"position":[[1194,13]]}},"keywords":{}}],["likejailhous",{"_index":4991,"title":{},"content":{"174":{"position":[[870,13]]}},"keywords":{}}],["likejava",{"_index":5370,"title":{},"content":{"199":{"position":[[29,11]]}},"keywords":{}}],["likelihood",{"_index":2630,"title":{"74":{"position":[[13,10]]}},"content":{"73":{"position":[[900,10]]},"74":{"position":[[15,10],[992,10]]},"75":{"position":[[36,10]]},"86":{"position":[[814,10]]}},"keywords":{}}],["liketelecom",{"_index":4998,"title":{},"content":{"174":{"position":[[1317,11]]}},"keywords":{}}],["likethi",{"_index":4775,"title":{},"content":{"163":{"position":[[1667,9]]}},"keywords":{}}],["liketim",{"_index":3861,"title":{},"content":{"120":{"position":[[755,9]]}},"keywords":{}}],["likewis",{"_index":4343,"title":{},"content":{"132":{"position":[[234,8]]}},"keywords":{}}],["limit",{"_index":1985,"title":{},"content":{"45":{"position":[[1705,5]]},"93":{"position":[[4611,6]]},"97":{"position":[[982,7]]},"160":{"position":[[1830,7],[2563,7]]},"173":{"position":[[513,5]]}},"keywords":{}}],["line",{"_index":680,"title":{},"content":{"15":{"position":[[1313,5]]},"30":{"position":[[7355,4]]},"33":{"position":[[400,5]]},"44":{"position":[[1148,4]]},"90":{"position":[[4754,4],[4977,4]]},"91":{"position":[[1999,5]]},"93":{"position":[[4412,5]]},"97":{"position":[[6388,4]]},"121":{"position":[[1558,4],[2206,5],[2324,5]]},"129":{"position":[[2498,4]]},"152":{"position":[[678,4]]},"155":{"position":[[1377,4],[1439,4],[1501,4],[1564,4]]},"156":{"position":[[661,4]]},"173":{"position":[[642,4]]},"175":{"position":[[133,4]]},"179":{"position":[[994,4],[1099,4]]},"181":{"position":[[154,4],[276,5]]},"188":{"position":[[3864,4],[3929,4],[4008,4]]},"192":{"position":[[155,4],[529,4]]},"193":{"position":[[2330,4],[3512,5]]}},"keywords":{}}],["linear",{"_index":329,"title":{},"content":{"6":{"position":[[412,6]]},"10":{"position":[[313,6]]},"86":{"position":[[111,6],[186,6],[564,6]]}},"keywords":{}}],["link",{"_index":4071,"title":{},"content":{"125":{"position":[[2870,4],[6135,4],[6577,4],[7123,7],[7799,6]]},"129":{"position":[[1383,4]]},"155":{"position":[[277,6]]}},"keywords":{}}],["linker",{"_index":4648,"title":{},"content":{"160":{"position":[[182,6]]}},"keywords":{}}],["linking/packag",{"_index":5263,"title":{},"content":{"190":{"position":[[597,17]]}},"keywords":{}}],["links"""",{"_index":886,"title":{},"content":{"22":{"position":[[258,23]]}},"keywords":{}}],["linux",{"_index":3665,"title":{},"content":{"108":{"position":[[342,5]]},"124":{"position":[[203,5]]},"134":{"position":[[74,6]]},"173":{"position":[[241,5]]},"176":{"position":[[363,5]]},"195":{"position":[[525,6]]}},"keywords":{}}],["liquid",{"_index":3192,"title":{},"content":{"93":{"position":[[688,9]]}},"keywords":{}}],["list",{"_index":2052,"title":{},"content":{"49":{"position":[[16,4]]},"91":{"position":[[2151,4]]},"93":{"position":[[2982,4]]},"121":{"position":[[2409,4]]}},"keywords":{}}],["list(earnings_data.key",{"_index":3275,"title":{},"content":{"93":{"position":[[4628,26]]}},"keywords":{}}],["list(filter(lambda",{"_index":897,"title":{},"content":{"22":{"position":[[517,18],[1477,18]]}},"keywords":{}}],["list(map(lambda",{"_index":1245,"title":{},"content":{"28":{"position":[[1386,15],[3181,15]]},"30":{"position":[[1752,15],[3101,15],[5020,15],[6169,15]]},"93":{"position":[[2886,15]]}},"keywords":{}}],["list(set([x",{"_index":2126,"title":{},"content":{"51":{"position":[[2351,11]]}},"keywords":{}}],["list(set(global_articl",{"_index":982,"title":{},"content":{"22":{"position":[[2881,26]]}},"keywords":{}}],["list_1.iterrow",{"_index":1056,"title":{},"content":{"24":{"position":[[1188,18]]},"25":{"position":[[908,18]]}},"keywords":{}}],["list_2",{"_index":1047,"title":{},"content":{"24":{"position":[[955,8],[1322,7]]},"25":{"position":[[675,8],[1042,7]]}},"keywords":{}}],["list_2.key",{"_index":1055,"title":{},"content":{"24":{"position":[[1149,14]]},"25":{"position":[[869,14]]}},"keywords":{}}],["list_2[index_dt",{"_index":1066,"title":{},"content":{"24":{"position":[[1344,16]]},"25":{"position":[[1064,16]]}},"keywords":{}}],["list_2[key",{"_index":1053,"title":{},"content":{"24":{"position":[[1126,11]]},"25":{"position":[[846,11]]}},"keywords":{}}],["liter",{"_index":3348,"title":{},"content":{"96":{"position":[[1798,7]]},"132":{"position":[[900,9]]}},"keywords":{}}],["littl",{"_index":279,"title":{},"content":{"4":{"position":[[1091,6]]},"30":{"position":[[9485,6]]},"98":{"position":[[627,6]]},"116":{"position":[[2358,6]]},"122":{"position":[[1369,6]]},"161":{"position":[[421,6]]}},"keywords":{}}],["live",{"_index":1314,"title":{},"content":{"29":{"position":[[244,4]]},"66":{"position":[[201,4]]},"112":{"position":[[479,5]]},"174":{"position":[[467,4]]}},"keywords":{}}],["llvm",{"_index":4508,"title":{},"content":{"152":{"position":[[35,4],[160,4],[309,4],[835,4]]},"153":{"position":[[35,4],[84,4],[414,4]]},"172":{"position":[[2229,4]]}},"keywords":{}}],["lmt",{"_index":1656,"title":{},"content":{"34":{"position":[[3103,4]]}},"keywords":{}}],["load",{"_index":110,"title":{},"content":{"2":{"position":[[551,4]]},"30":{"position":[[319,7]]},"43":{"position":[[22,4]]},"68":{"position":[[389,6]]},"69":{"position":[[337,6]]},"71":{"position":[[17,6],[40,6],[115,6]]},"72":{"position":[[322,6]]},"73":{"position":[[106,7]]},"77":{"position":[[94,6]]},"103":{"position":[[84,7],[387,4]]},"125":{"position":[[3996,4],[4469,4]]},"134":{"position":[[319,4]]},"178":{"position":[[334,6]]},"180":{"position":[[52,6]]},"182":{"position":[[507,6]]}},"keywords":{}}],["loader",{"_index":171,"title":{},"content":{"3":{"position":[[754,8]]}},"keywords":{}}],["loav",{"_index":4743,"title":{},"content":{"161":{"position":[[927,6]]}},"keywords":{}}],["loc",{"_index":1484,"title":{},"content":{"30":{"position":[[9665,3]]}},"keywords":{}}],["local",{"_index":2346,"title":{},"content":{"60":{"position":[[185,5]]},"85":{"position":[[530,5]]},"86":{"position":[[267,5]]},"134":{"position":[[244,5]]},"172":{"position":[[1398,8]]},"196":{"position":[[173,5],[214,5]]}},"keywords":{}}],["locat",{"_index":979,"title":{},"content":{"22":{"position":[[2811,9]]},"113":{"position":[[529,8]]},"127":{"position":[[1473,6]]},"128":{"position":[[583,8],[823,8],[1331,8]]},"129":{"position":[[1003,8]]},"155":{"position":[[991,8]]},"181":{"position":[[983,9]]},"182":{"position":[[454,9]]},"183":{"position":[[767,8]]},"192":{"position":[[274,8]]},"193":{"position":[[437,7]]}},"keywords":{}}],["lock",{"_index":5197,"title":{},"content":{"188":{"position":[[2934,6],[3341,6]]},"189":{"position":[[831,5],[857,6],[1289,6],[2003,6],[2606,6]]}},"keywords":{}}],["log(\\mathcal{l",{"_index":2659,"title":{},"content":{"74":{"position":[[1681,17]]}},"keywords":{}}],["log(l",{"_index":2660,"title":{},"content":{"74":{"position":[[1719,7]]}},"keywords":{}}],["logic",{"_index":3028,"title":{},"content":{"90":{"position":[[3639,5]]},"121":{"position":[[789,6],[1890,6]]}},"keywords":{}}],["loglevel",{"_index":3506,"title":{},"content":{"103":{"position":[[260,8]]}},"keywords":{}}],["log⁡(d)\\log(d)log(d",{"_index":1694,"title":{},"content":{"38":{"position":[[643,21]]}},"keywords":{}}],["log⁡(l)=∑i=1nlog⁡(l)\\begin{align",{"_index":2658,"title":{},"content":{"74":{"position":[[1646,34]]}},"keywords":{}}],["log⁡(l)\\log(\\mathcal{l})log(l",{"_index":2649,"title":{},"content":{"74":{"position":[[1208,30]]},"75":{"position":[[570,30]]}},"keywords":{}}],["london",{"_index":1214,"title":{},"content":{"28":{"position":[[495,6]]}},"keywords":{}}],["long",{"_index":1466,"title":{},"content":{"30":{"position":[[8772,5],[8921,5],[9018,5]]},"32":{"position":[[228,4]]},"33":{"position":[[583,4]]},"43":{"position":[[370,4]]},"44":{"position":[[1252,4]]},"45":{"position":[[1344,4],[1399,5]]},"61":{"position":[[377,5]]},"83":{"position":[[570,4]]},"89":{"position":[[839,5]]},"93":{"position":[[300,4]]},"96":{"position":[[2318,4]]},"97":{"position":[[92,4],[6167,4],[6283,4]]},"98":{"position":[[14,4]]},"112":{"position":[[526,4]]},"113":{"position":[[228,4]]},"121":{"position":[[762,4]]},"125":{"position":[[9886,4]]},"127":{"position":[[230,4]]},"160":{"position":[[1136,4]]},"164":{"position":[[112,4],[1575,4]]},"168":{"position":[[48,4]]},"169":{"position":[[48,4]]},"173":{"position":[[1033,4]]},"188":{"position":[[984,4],[1008,4],[1060,4],[1175,4],[1309,4],[1479,4]]},"189":{"position":[[1582,4],[1700,4],[2066,4]]},"199":{"position":[[153,4],[317,4],[380,5]]}},"keywords":{}}],["long/short",{"_index":800,"title":{},"content":{"20":{"position":[[979,10]]}},"keywords":{}}],["longer",{"_index":2499,"title":{"65":{"position":[[20,8]]}},"content":{"66":{"position":[[206,7]]},"82":{"position":[[1075,6]]},"97":{"position":[[5518,6]]},"98":{"position":[[1227,6]]},"113":{"position":[[1258,6]]},"121":{"position":[[1797,7],[2306,6]]},"146":{"position":[[476,6]]},"156":{"position":[[154,6]]},"183":{"position":[[850,6]]},"194":{"position":[[162,7]]}},"keywords":{}}],["look",{"_index":190,"title":{},"content":{"3":{"position":[[1095,6]]},"4":{"position":[[1289,7]]},"28":{"position":[[2350,5],[2842,7]]},"30":{"position":[[7416,6]]},"32":{"position":[[921,4],[1422,5]]},"38":{"position":[[1033,4]]},"39":{"position":[[152,7]]},"40":{"position":[[13,7],[101,5],[826,7],[3720,5]]},"44":{"position":[[916,5]]},"51":{"position":[[1857,5]]},"53":{"position":[[1964,7]]},"57":{"position":[[614,4]]},"64":{"position":[[488,7]]},"68":{"position":[[262,5]]},"72":{"position":[[638,7]]},"88":{"position":[[161,4],[2140,4]]},"91":{"position":[[5327,7],[5718,4]]},"92":{"position":[[93,7]]},"93":{"position":[[61,7],[469,4],[608,4]]},"96":{"position":[[806,4],[950,4],[1562,5]]},"97":{"position":[[731,5],[3336,4],[3538,5],[6039,4]]},"106":{"position":[[1133,4]]},"111":{"position":[[719,4]]},"112":{"position":[[354,5],[775,4],[930,4],[967,5]]},"115":{"position":[[87,4]]},"116":{"position":[[181,5]]},"121":{"position":[[808,7]]},"122":{"position":[[1000,4]]},"124":{"position":[[822,7]]},"125":{"position":[[7737,5]]},"128":{"position":[[1058,4],[1292,4]]},"155":{"position":[[547,4],[799,4],[1262,7]]},"159":{"position":[[193,5]]},"160":{"position":[[446,4],[2798,4]]},"161":{"position":[[868,4],[1645,7]]},"163":{"position":[[1661,5]]},"172":{"position":[[1200,4]]},"176":{"position":[[687,4]]},"182":{"position":[[407,4]]},"188":{"position":[[51,5]]},"193":{"position":[[2176,4]]},"196":{"position":[[1022,5]]}},"keywords":{}}],["lookback",{"_index":717,"title":{},"content":{"17":{"position":[[222,8],[303,10]]},"19":{"position":[[80,8]]},"20":{"position":[[62,8]]},"90":{"position":[[820,11],[887,8],[1089,8],[1355,8],[2048,8],[2093,8],[2205,11],[2272,8],[2474,8],[2710,8],[3150,8]]}},"keywords":{}}],["lookback+1",{"_index":3012,"title":{},"content":{"90":{"position":[[2060,12],[2105,12],[3162,12]]}},"keywords":{}}],["lookforward",{"_index":2984,"title":{},"content":{"90":{"position":[[1050,11],[1376,11],[1542,13],[1574,13],[1691,13],[1723,13],[2435,11],[2731,11],[2835,13],[2867,13]]}},"keywords":{}}],["lookforward+1",{"_index":3004,"title":{},"content":{"90":{"position":[[1815,15],[1848,15],[1917,16],[2959,15],[2992,15],[3056,16]]}},"keywords":{}}],["lookforward_data",{"_index":2987,"title":{},"content":{"90":{"position":[[1133,16],[2518,16]]}},"keywords":{}}],["lookforward_data.max(axis=0",{"_index":2992,"title":{},"content":{"90":{"position":[[1245,28],[2630,28]]}},"keywords":{}}],["lookforward_data.min(axis=0",{"_index":2993,"title":{},"content":{"90":{"position":[[1281,28],[2666,28]]}},"keywords":{}}],["lookforward_data.std(axis=0",{"_index":2991,"title":{},"content":{"90":{"position":[[1206,30],[2591,30]]}},"keywords":{}}],["lookimposs",{"_index":4540,"title":{},"content":{"153":{"position":[[244,14]]}},"keywords":{}}],["lookup",{"_index":5091,"title":{},"content":{"180":{"position":[[249,6]]}},"keywords":{}}],["loop",{"_index":1026,"title":{},"content":{"24":{"position":[[499,5]]},"25":{"position":[[224,5]]},"30":{"position":[[9523,5]]},"199":{"position":[[182,4],[354,4]]}},"keywords":{}}],["loos",{"_index":3448,"title":{},"content":{"98":{"position":[[643,5]]}},"keywords":{}}],["lose",{"_index":1580,"title":{},"content":{"33":{"position":[[962,4]]},"102":{"position":[[1353,6]]}},"keywords":{}}],["lossi",{"_index":3475,"title":{},"content":{"101":{"position":[[544,5],[805,5]]},"102":{"position":[[208,5]]},"175":{"position":[[760,6]]}},"keywords":{}}],["lossless",{"_index":3470,"title":{},"content":{"101":{"position":[[337,8]]},"105":{"position":[[916,8]]}},"keywords":{}}],["lost",{"_index":3867,"title":{"121":{"position":[[0,4]]}},"content":{},"keywords":{}}],["lot",{"_index":1333,"title":{},"content":{"30":{"position":[[387,3]]},"33":{"position":[[699,3]]},"40":{"position":[[637,3],[674,3],[3076,3]]},"41":{"position":[[67,3]]},"51":{"position":[[44,3],[3204,3]]},"53":{"position":[[1650,3]]},"55":{"position":[[91,3]]},"68":{"position":[[58,3]]},"74":{"position":[[205,3]]},"90":{"position":[[108,3]]},"98":{"position":[[1223,3]]},"102":{"position":[[320,3]]},"104":{"position":[[1751,3],[1813,3]]},"106":{"position":[[296,3]]},"120":{"position":[[195,3]]},"121":{"position":[[2228,3]]},"122":{"position":[[807,3]]},"124":{"position":[[432,3]]},"125":{"position":[[3491,3],[7382,3],[9910,3],[10393,3],[10735,3]]},"130":{"position":[[261,3]]},"148":{"position":[[17,3]]},"153":{"position":[[168,3]]},"159":{"position":[[16,3]]},"161":{"position":[[1610,3]]},"174":{"position":[[298,3]]},"176":{"position":[[196,3]]},"188":{"position":[[59,3]]},"199":{"position":[[1112,3]]}},"keywords":{}}],["love",{"_index":2269,"title":{"153":{"position":[[31,4]]}},"content":{"53":{"position":[[1384,4]]},"124":{"position":[[139,4]]},"129":{"position":[[1408,4]]}},"keywords":{}}],["loveyoual",{"_index":2231,"title":{},"content":{"53":{"position":[[841,11]]}},"keywords":{}}],["low",{"_index":337,"title":{"128":{"position":[[0,3]]}},"content":{"6":{"position":[[513,3]]},"70":{"position":[[37,4],[1232,4]]},"71":{"position":[[24,4],[127,3]]},"78":{"position":[[51,4]]},"104":{"position":[[1256,3],[1512,3]]},"105":{"position":[[167,3]]},"127":{"position":[[1594,3]]},"128":{"position":[[923,3]]},"163":{"position":[[1353,5]]}},"keywords":{}}],["lower",{"_index":1371,"title":{},"content":{"30":{"position":[[2417,5],[4395,5]]}},"keywords":{}}],["lowest/highest",{"_index":4763,"title":{},"content":{"163":{"position":[[206,14]]}},"keywords":{}}],["lt",{"_index":822,"title":{},"content":{"20":{"position":[[1564,4]]},"24":{"position":[[1422,4],[1445,4]]},"25":{"position":[[1142,4],[1165,4]]},"76":{"position":[[2402,4],[2433,4],[3104,4]]},"91":{"position":[[3097,5]]},"93":{"position":[[2851,4]]},"96":{"position":[[179,4]]},"188":{"position":[[1028,5],[3567,5]]},"189":{"position":[[1117,5],[1387,5],[3111,5]]},"199":{"position":[[205,4]]}},"keywords":{}}],["lt;bspeice@kcg.com>"",{"_index":3689,"title":{},"content":{"109":{"position":[[346,30]]}},"keywords":{}}],["lt;matplotlib.axes._subplots.axessubplot",{"_index":2114,"title":{},"content":{"51":{"position":[[1785,41]]}},"keywords":{}}],["lt;t",{"_index":4288,"title":{},"content":{"129":{"position":[[624,5]]}},"keywords":{}}],["lt;url>",{"_index":3323,"title":{},"content":{"96":{"position":[[378,12]]}},"keywords":{}}],["luajit",{"_index":4926,"title":{},"content":{"172":{"position":[[1796,8]]}},"keywords":{}}],["luck",{"_index":4500,"title":{},"content":{"150":{"position":[[702,5]]}},"keywords":{}}],["lume",{"_index":207,"title":{},"content":{"3":{"position":[[1338,5]]}},"keywords":{}}],["lunch",{"_index":4494,"title":{},"content":{"150":{"position":[[414,6]]}},"keywords":{}}],["luxuri",{"_index":4498,"title":{},"content":{"150":{"position":[[570,6]]}},"keywords":{}}],["m",{"_index":370,"title":{},"content":{"6":{"position":[[1034,1]]},"7":{"position":[[326,1],[635,1],[675,2]]},"12":{"position":[[251,2],[566,2]]},"13":{"position":[[1347,2]]},"14":{"position":[[2419,2]]},"15":{"position":[[2091,2]]},"30":{"position":[[2039,1],[3445,1],[3533,1],[5289,1],[6519,1],[6607,1]]},"39":{"position":[[577,2],[592,2]]},"62":{"position":[[563,2],[1109,2]]},"64":{"position":[[567,2]]},"65":{"position":[[463,2]]},"88":{"position":[[759,2]]},"93":{"position":[[4174,2]]},"129":{"position":[[1976,1]]}},"keywords":{}}],["m)[0",{"_index":1361,"title":{},"content":{"30":{"position":[[2013,5],[3419,5],[5263,5],[6493,5]]}},"keywords":{}}],["m)[1",{"_index":1388,"title":{},"content":{"30":{"position":[[3507,5],[6581,5]]}},"keywords":{}}],["m.my_funct",{"_index":4307,"title":{},"content":{"129":{"position":[[1990,15]]}},"keywords":{}}],["m4a",{"_index":3479,"title":{},"content":{"101":{"position":[[595,6]]}},"keywords":{}}],["mac",{"_index":4372,"title":{},"content":{"134":{"position":[[50,4]]}},"keywords":{}}],["machin",{"_index":2622,"title":{},"content":{"73":{"position":[[193,7]]},"102":{"position":[[90,7]]},"189":{"position":[[162,7],[290,7],[367,7]]}},"keywords":{}}],["macro",{"_index":3346,"title":{"144":{"position":[[19,6]]},"145":{"position":[[16,6]]}},"content":{"96":{"position":[[1551,5],[1861,5]]},"121":{"position":[[1997,6],[2068,5],[2299,6],[2650,6]]},"147":{"position":[[596,5]]}},"keywords":{}}],["made",{"_index":49,"title":{},"content":{"1":{"position":[[562,4]]},"26":{"position":[[325,4]]},"34":{"position":[[1852,4],[3274,4]]},"36":{"position":[[12,4]]},"66":{"position":[[341,4]]},"71":{"position":[[1463,4]]},"76":{"position":[[1441,4]]},"172":{"position":[[1171,4]]}},"keywords":{}}],["magic",{"_index":5040,"title":{},"content":{"176":{"position":[[59,8]]}},"keywords":{}}],["magical."",{"_index":71,"title":{},"content":{"1":{"position":[[789,14]]}},"keywords":{}}],["magnitud",{"_index":4419,"title":{},"content":{"139":{"position":[[451,9]]}},"keywords":{}}],["main",{"_index":84,"title":{},"content":{"2":{"position":[[145,4]]},"76":{"position":[[1814,4]]},"111":{"position":[[327,6]]},"113":{"position":[[729,6]]},"115":{"position":[[112,6]]},"116":{"position":[[212,6]]},"117":{"position":[[1004,6]]},"127":{"position":[[587,4],[1237,4]]},"128":{"position":[[263,6],[441,5],[1135,6]]},"129":{"position":[[421,6],[1533,6]]},"135":{"position":[[373,4]]},"136":{"position":[[225,4]]},"144":{"position":[[283,6]]},"145":{"position":[[141,6]]},"146":{"position":[[169,6]]},"147":{"position":[[317,6]]},"152":{"position":[[1057,5],[1109,6]]},"153":{"position":[[750,6]]},"156":{"position":[[919,6],[1154,4]]},"160":{"position":[[261,7]]},"164":{"position":[[1216,4]]},"179":{"position":[[568,6],[976,6],[1284,6]]},"180":{"position":[[237,4]]},"184":{"position":[[314,6],[654,6]]},"186":{"position":[[337,6]]},"195":{"position":[[638,6]]}},"keywords":{}}],["main(str",{"_index":4231,"title":{},"content":{"127":{"position":[[613,13],[1263,13]]}},"keywords":{}}],["main.java:5",{"_index":4233,"title":{},"content":{"127":{"position":[[730,12]]}},"keywords":{}}],["main.r",{"_index":4368,"title":{},"content":{"133":{"position":[[242,8]]}},"keywords":{}}],["maintain",{"_index":809,"title":{},"content":{"20":{"position":[[1149,8]]},"122":{"position":[[1338,8]]},"123":{"position":[[168,10]]},"125":{"position":[[10278,8]]},"164":{"position":[[163,11]]}},"keywords":{}}],["maintained.chrono",{"_index":3953,"title":{},"content":{"122":{"position":[[1132,17]]}},"keywords":{}}],["mainten",{"_index":3965,"title":{"123":{"position":[[6,11]]}},"content":{},"keywords":{}}],["make",{"_index":216,"title":{"113":{"position":[[8,6]]},"161":{"position":[[0,6]]}},"content":{"3":{"position":[[1532,4]]},"7":{"position":[[4,4]]},"9":{"position":[[57,6]]},"23":{"position":[[199,4]]},"25":{"position":[[2791,4]]},"26":{"position":[[143,5]]},"32":{"position":[[323,4],[742,4],[962,4],[1029,4],[1345,4],[2167,4],[2344,4]]},"33":{"position":[[111,4],[451,4],[569,4],[740,4],[887,4]]},"34":{"position":[[95,4],[883,4],[961,4],[3576,4]]},"35":{"position":[[171,4]]},"36":{"position":[[68,6]]},"38":{"position":[[66,6],[343,4],[1041,6]]},"39":{"position":[[306,4],[1784,4]]},"43":{"position":[[157,4],[1044,4],[1185,4]]},"53":{"position":[[549,4],[2033,4],[2129,4]]},"61":{"position":[[495,4],[1257,4]]},"63":{"position":[[91,4]]},"66":{"position":[[187,6]]},"68":{"position":[[84,4],[681,5],[717,4],[782,4]]},"69":{"position":[[240,4]]},"75":{"position":[[1145,4]]},"76":{"position":[[899,4],[1367,4]]},"81":{"position":[[42,4]]},"85":{"position":[[493,5]]},"90":{"position":[[484,4]]},"91":{"position":[[2185,4],[3215,4]]},"92":{"position":[[1027,4]]},"96":{"position":[[83,4]]},"97":{"position":[[325,5],[709,6],[5975,6]]},"101":{"position":[[628,4]]},"104":{"position":[[583,5],[1009,4],[1413,4]]},"106":{"position":[[910,4]]},"108":{"position":[[223,4],[701,4]]},"110":{"position":[[115,4]]},"111":{"position":[[55,4]]},"113":{"position":[[1245,4],[2309,4]]},"116":{"position":[[2768,6],[2868,4],[3107,4]]},"120":{"position":[[222,6],[684,4],[779,5],[1042,4]]},"121":{"position":[[577,4],[1252,4],[1897,4]]},"122":{"position":[[72,4]]},"123":{"position":[[231,4]]},"125":{"position":[[6207,4],[10370,4],[11185,4]]},"128":{"position":[[564,6]]},"129":{"position":[[2051,4]]},"132":{"position":[[393,6],[1021,4]]},"133":{"position":[[168,4]]},"135":{"position":[[4,4]]},"150":{"position":[[442,4]]},"153":{"position":[[223,4]]},"155":{"position":[[189,4]]},"156":{"position":[[1816,4]]},"158":{"position":[[410,4],[448,4]]},"160":{"position":[[1246,4]]},"161":{"position":[[635,5],[1726,6]]},"163":{"position":[[341,4]]},"164":{"position":[[1470,4]]},"165":{"position":[[1464,4]]},"166":{"position":[[299,4]]},"167":{"position":[[266,4]]},"170":{"position":[[61,6]]},"172":{"position":[[1614,5],[2525,4]]},"173":{"position":[[1825,4],[1973,6]]},"175":{"position":[[464,6],[706,4],[941,4]]},"176":{"position":[[403,4]]},"188":{"position":[[2886,5]]},"190":{"position":[[492,4]]},"192":{"position":[[335,5]]},"194":{"position":[[81,4]]},"196":{"position":[[1693,4]]}},"keywords":{}}],["make_lin",{"_index":5267,"title":{},"content":{"192":{"position":[[191,11]]}},"keywords":{}}],["maker",{"_index":1507,"title":{"31":{"position":[[17,5]]}},"content":{},"keywords":{}}],["malloc",{"_index":3364,"title":{},"content":{"97":{"position":[[269,8]]},"160":{"position":[[3504,8]]}},"keywords":{}}],["man",{"_index":2549,"title":{},"content":{"66":{"position":[[604,3]]},"121":{"position":[[2380,4]]}},"keywords":{}}],["manag",{"_index":1534,"title":{},"content":{"32":{"position":[[952,6]]},"97":{"position":[[200,10]]},"108":{"position":[[405,7]]},"121":{"position":[[919,7]]},"125":{"position":[[1962,6],[7039,6],[8138,7],[8298,7],[10085,7]]},"134":{"position":[[63,7]]},"148":{"position":[[64,8]]},"155":{"position":[[442,8],[640,6]]},"156":{"position":[[762,7]]},"160":{"position":[[729,11],[1004,7],[1960,6]]},"188":{"position":[[293,8],[4343,6]]},"190":{"position":[[937,6]]},"199":{"position":[[4,7]]}},"keywords":{}}],["managerexplicitli",{"_index":5155,"title":{},"content":{"188":{"position":[[530,17]]}},"keywords":{}}],["mani",{"_index":188,"title":{"64":{"position":[[4,4]]},"65":{"position":[[4,4]]}},"content":{"3":{"position":[[1058,4]]},"4":{"position":[[756,4]]},"30":{"position":[[1060,4],[2814,4],[4203,4],[4569,4]]},"44":{"position":[[1095,4]]},"51":{"position":[[1548,4],[2177,4]]},"58":{"position":[[294,4]]},"64":{"position":[[36,4],[282,4],[1253,4]]},"65":{"position":[[38,4],[81,4],[281,4],[1368,4],[1548,4],[2240,4]]},"66":{"position":[[346,4]]},"68":{"position":[[704,4]]},"74":{"position":[[1341,4]]},"89":{"position":[[278,4]]},"97":{"position":[[349,4],[2196,4],[2464,4]]},"102":{"position":[[1033,4]]},"156":{"position":[[293,4]]},"164":{"position":[[1527,4]]},"172":{"position":[[2093,4]]},"173":{"position":[[90,4]]},"175":{"position":[[1083,4]]}},"keywords":{}}],["manipul",{"_index":5269,"title":{},"content":{"192":{"position":[[651,12]]}},"keywords":{}}],["manner",{"_index":2095,"title":{},"content":{"51":{"position":[[984,6]]},"116":{"position":[[2943,7]]}},"keywords":{}}],["mannerth",{"_index":5153,"title":{},"content":{"188":{"position":[[502,9]]}},"keywords":{}}],["manual",{"_index":3362,"title":{},"content":{"97":{"position":[[186,6]]},"121":{"position":[[685,6]]},"125":{"position":[[9387,8]]}},"keywords":{}}],["map",{"_index":808,"title":{},"content":{"20":{"position":[[1122,3]]},"113":{"position":[[2130,3]]}},"keywords":{}}],["map(lambda",{"_index":3240,"title":{},"content":{"93":{"position":[[2765,10]]}},"keywords":{}}],["march",{"_index":2394,"title":{},"content":{"62":{"position":[[158,5],[1759,5]]}},"keywords":{}}],["margin",{"_index":1842,"title":{},"content":{"40":{"position":[[3630,7]]}},"keywords":{}}],["mark",{"_index":4441,"title":{},"content":{"143":{"position":[[97,6]]},"152":{"position":[[785,4],[882,6]]},"159":{"position":[[879,6]]},"184":{"position":[[875,6]]}},"keywords":{}}],["marker",{"_index":5114,"title":{"185":{"position":[[9,7]]}},"content":{"182":{"position":[[614,6]]},"185":{"position":[[82,7]]},"198":{"position":[[669,6]]}},"keywords":{}}],["market",{"_index":723,"title":{"88":{"position":[[4,6]]}},"content":{"17":{"position":[[335,6]]},"19":{"position":[[107,6]]},"24":{"position":[[408,7],[3003,6],[3186,7],[3324,6]]},"25":{"position":[[72,6],[2674,6]]},"26":{"position":[[355,6],[488,6],[697,6],[787,6]]},"32":{"position":[[217,7]]},"38":{"position":[[1124,6]]},"40":{"position":[[1280,7],[1582,7],[2545,8]]},"88":{"position":[[2095,6],[2229,6],[2308,6],[3583,6],[3789,6]]},"89":{"position":[[163,6],[416,6],[848,7]]},"91":{"position":[[1707,6],[4703,6],[4884,6],[5105,6],[5469,6]]},"93":{"position":[[83,7],[380,6],[488,7],[525,6],[638,6],[818,6]]},"163":{"position":[[75,6],[396,6],[2207,6],[2421,6]]}},"keywords":{}}],["market.pct_chang",{"_index":747,"title":{},"content":{"19":{"position":[[259,19]]}},"keywords":{}}],["market_return",{"_index":746,"title":{},"content":{"19":{"position":[[242,14]]}},"keywords":{}}],["market_returns[d_col].mean",{"_index":751,"title":{},"content":{"19":{"position":[[314,29]]}},"keywords":{}}],["market_tick",{"_index":715,"title":{},"content":{"17":{"position":[[190,13]]}},"keywords":{}}],["markov",{"_index":2298,"title":{},"content":{"55":{"position":[[105,6]]}},"keywords":{}}],["marri",{"_index":2277,"title":{},"content":{"53":{"position":[[1528,7]]}},"keywords":{}}],["martingal",{"_index":1508,"title":{"32":{"position":[[13,10]]}},"content":{"34":{"position":[[811,10]]}},"keywords":{}}],["marvel",{"_index":3842,"title":{},"content":{"118":{"position":[[147,6]]}},"keywords":{}}],["match",{"_index":282,"title":{},"content":{"4":{"position":[[1117,5]]},"7":{"position":[[181,5]]},"9":{"position":[[337,5]]},"24":{"position":[[1017,5],[1084,5],[1164,7],[1497,7],[1518,7],[1588,7]]},"25":{"position":[[737,5],[804,5],[884,7],[1217,7],[1238,7],[1308,7]]},"72":{"position":[[334,7]]},"75":{"position":[[329,7]]},"93":{"position":[[1764,5],[1806,6]]},"113":{"position":[[2324,5]]},"125":{"position":[[4303,5],[7995,6]]}},"keywords":{}}],["matches_dict",{"_index":1069,"title":{},"content":{"24":{"position":[[1617,12]]},"25":{"position":[[1316,12]]}},"keywords":{}}],["matches_dict[index",{"_index":1080,"title":{},"content":{"24":{"position":[[2011,19]]},"25":{"position":[[1735,19]]}},"keywords":{}}],["materi",{"_index":4735,"title":{},"content":{"161":{"position":[[510,9]]},"178":{"position":[[653,12]]}},"keywords":{}}],["math",{"_index":1519,"title":{},"content":{"32":{"position":[[431,5]]},"193":{"position":[[1403,4]]}},"keywords":{}}],["mathbb{e}[d_1",{"_index":2587,"title":{},"content":{"70":{"position":[[620,15],[684,14]]},"71":{"position":[[720,15],[784,14]]}},"keywords":{}}],["mathbb{e}[d_2",{"_index":2588,"title":{},"content":{"70":{"position":[[648,15]]},"71":{"position":[[748,15]]}},"keywords":{}}],["mathbb{e}[d_{fair",{"_index":2590,"title":{},"content":{"70":{"position":[[712,19]]},"71":{"position":[[812,19]]}},"keywords":{}}],["mathcal{l(\\mathbf{x",{"_index":2645,"title":{},"content":{"74":{"position":[[1074,23]]}},"keywords":{}}],["mathcal{l(x",{"_index":2635,"title":{},"content":{"74":{"position":[[555,14]]}},"keywords":{}}],["mathematician",{"_index":2816,"title":{},"content":{"83":{"position":[[585,14]]}},"keywords":{}}],["matplotlib",{"_index":1720,"title":{},"content":{"39":{"position":[[516,11]]},"43":{"position":[[338,11]]},"51":{"position":[[1657,11]]},"68":{"position":[[473,11]]},"88":{"position":[[544,11]]}},"keywords":{}}],["matplotlib.d",{"_index":2843,"title":{},"content":{"88":{"position":[[319,16],[405,16]]}},"keywords":{}}],["matplotlib.fin",{"_index":2845,"title":{},"content":{"88":{"position":[[357,18]]}},"keywords":{}}],["matplotlib.pyplot",{"_index":1717,"title":{},"content":{"39":{"position":[[460,17]]},"43":{"position":[[313,17]]},"51":{"position":[[1632,17]]},"68":{"position":[[448,17]]},"88":{"position":[[289,17]]}},"keywords":{}}],["matrix",{"_index":405,"title":{},"content":{"7":{"position":[[575,6]]},"43":{"position":[[1059,6]]},"106":{"position":[[237,6],[615,6],[722,7],[806,7],[842,6],[881,7]]}},"keywords":{}}],["matter",{"_index":2030,"title":{},"content":{"46":{"position":[[258,6]]},"74":{"position":[[1503,6]]},"139":{"position":[[592,7]]},"175":{"position":[[542,8],[1686,6]]},"176":{"position":[[1445,6]]},"194":{"position":[[583,6]]}},"keywords":{}}],["matters;data",{"_index":4918,"title":{},"content":{"172":{"position":[[1360,12]]}},"keywords":{}}],["matur",{"_index":573,"title":{},"content":{"13":{"position":[[913,9]]},"14":{"position":[[1325,9],[1931,9]]},"15":{"position":[[1599,9]]}},"keywords":{}}],["max",{"_index":701,"title":{},"content":{"17":{"position":[[7,3]]},"20":{"position":[[533,3],[583,4],[2678,3],[3004,3]]},"30":{"position":[[7137,3]]},"34":{"position":[[3415,3],[3806,3]]},"44":{"position":[[897,3]]},"90":{"position":[[1237,5],[1800,5],[2622,5],[2944,5]]}},"keywords":{}}],["max(close_vals[day",{"_index":1642,"title":{},"content":{"34":{"position":[[2584,20]]}},"keywords":{}}],["max(ev",{"_index":3033,"title":{},"content":{"90":{"position":[[3761,11]]}},"keywords":{}}],["max(events)+td",{"_index":3288,"title":{},"content":{"93":{"position":[[4988,15],[5403,15]]}},"keywords":{}}],["max(x[0",{"_index":1766,"title":{},"content":{"39":{"position":[[2772,10],[2932,10]]}},"keywords":{}}],["max_d1",{"_index":2730,"title":{},"content":{"76":{"position":[[2184,6],[2726,6],[3326,7]]},"78":{"position":[[253,7]]}},"keywords":{}}],["max_d2",{"_index":2731,"title":{},"content":{"76":{"position":[[2200,6],[2742,6],[3334,7]]},"78":{"position":[[261,7],[710,8]]}},"keywords":{}}],["max_err",{"_index":3003,"title":{},"content":{"90":{"position":[[1790,7],[1949,9],[2934,7],[3088,9]]}},"keywords":{}}],["max_it",{"_index":2734,"title":{},"content":{"76":{"position":[[2438,9],[2480,9]]}},"keywords":{}}],["max_iter=1e4",{"_index":2720,"title":{},"content":{"76":{"position":[[1921,14]]}},"keywords":{}}],["max_leverag",{"_index":1647,"title":{},"content":{"34":{"position":[[2806,12]]}},"keywords":{}}],["max_leverage)"",{"_index":1651,"title":{},"content":{"34":{"position":[[2885,22]]}},"keywords":{}}],["max_profit",{"_index":1641,"title":{},"content":{"34":{"position":[[2571,10],[2641,10]]}},"keywords":{}}],["max_scor",{"_index":2729,"title":{},"content":{"76":{"position":[[2162,9],[2693,10],[2704,9]]}},"keywords":{}}],["max_value=r3000_equities.index.max",{"_index":3267,"title":{},"content":{"93":{"position":[[3546,37]]}},"keywords":{}}],["maxim",{"_index":792,"title":{},"content":{"20":{"position":[[811,8]]}},"keywords":{}}],["maximum",{"_index":702,"title":{},"content":{"17":{"position":[[24,7]]},"20":{"position":[[32,7],[162,7]]},"30":{"position":[[7223,7]]},"76":{"position":[[2350,7]]},"86":{"position":[[273,8]]},"90":{"position":[[5256,7]]}},"keywords":{}}],["maximum(leverag",{"_index":1648,"title":{},"content":{"34":{"position":[[2821,18]]}},"keywords":{}}],["mayb",{"_index":209,"title":{},"content":{"3":{"position":[[1391,6]]},"29":{"position":[[179,5]]},"30":{"position":[[7936,5]]},"43":{"position":[[884,5]]},"97":{"position":[[4239,5],[4362,5]]},"124":{"position":[[530,5]]},"142":{"position":[[51,6]]},"161":{"position":[[295,5]]}},"keywords":{}}],["mb",{"_index":4402,"title":{},"content":{"136":{"position":[[961,2]]}},"keywords":{}}],["mean",{"_index":605,"title":{"149":{"position":[[28,5]]}},"content":{"13":{"position":[[1921,4],[1977,4],[2033,4],[2089,4],[2145,4],[2201,4]]},"14":{"position":[[2993,4],[3049,4],[3105,4],[3161,4],[3217,4],[3273,4]]},"15":{"position":[[2664,4],[2720,4],[2776,4],[2832,4],[2888,4],[2944,4]]},"26":{"position":[[295,5]]},"38":{"position":[[1137,5]]},"40":{"position":[[655,5]]},"44":{"position":[[818,4]]},"51":{"position":[[2634,5]]},"54":{"position":[[236,6]]},"75":{"position":[[5,5]]},"76":{"position":[[1149,5]]},"90":{"position":[[1098,5],[1433,6],[1485,6],[1535,6],[1567,6],[1684,6],[1716,6],[1808,6],[1841,6],[1910,6],[2483,5],[2783,6],[2828,6],[2860,6],[2952,6],[2985,6],[3049,6],[3423,5],[4774,4],[5082,4]]},"96":{"position":[[2073,6]]},"104":{"position":[[736,5],[830,5]]},"105":{"position":[[587,7],[720,5]]},"108":{"position":[[187,6]]},"121":{"position":[[730,5]]},"122":{"position":[[38,5],[727,5]]},"124":{"position":[[807,4]]},"161":{"position":[[857,5],[1699,4]]},"172":{"position":[[1099,8]]},"175":{"position":[[173,5],[1619,5]]},"198":{"position":[[595,5]]}},"keywords":{}}],["mean(mean_payoff",{"_index":594,"title":{},"content":{"13":{"position":[[1671,18]]},"14":{"position":[[2754,18]]},"15":{"position":[[2428,18]]}},"keywords":{}}],["mean(mean_payoffs))"",{"_index":597,"title":{},"content":{"13":{"position":[[1744,28]]},"14":{"position":[[2827,28]]},"15":{"position":[[2501,28]]}},"keywords":{}}],["mean(payoff",{"_index":585,"title":{},"content":{"13":{"position":[[1425,13]]},"14":{"position":[[2497,13]]},"15":{"position":[[2169,13]]}},"keywords":{}}],["mean_payoff",{"_index":586,"title":{},"content":{"13":{"position":[[1443,12]]},"14":{"position":[[2515,12]]},"15":{"position":[[2187,12]]}},"keywords":{}}],["mean_payoffs[i",{"_index":589,"title":{},"content":{"13":{"position":[[1511,15],[1631,16]]},"14":{"position":[[2583,15],[2714,16]]},"15":{"position":[[2255,15],[2388,16]]}},"keywords":{}}],["meant",{"_index":2837,"title":{},"content":{"86":{"position":[[1147,5]]},"91":{"position":[[188,5]]}},"keywords":{}}],["meanwhile,chrono",{"_index":3958,"title":{},"content":{"122":{"position":[[1244,16]]}},"keywords":{}}],["measur",{"_index":4618,"title":{},"content":{"158":{"position":[[68,9]]},"168":{"position":[[11,9]]},"169":{"position":[[11,9]]},"176":{"position":[[1025,10],[1572,7]]}},"keywords":{}}],["meati",{"_index":4801,"title":{},"content":{"164":{"position":[[31,5]]}},"keywords":{}}],["median",{"_index":4856,"title":{},"content":{"168":{"position":[[160,6]]},"169":{"position":[[274,6]]},"170":{"position":[[233,6]]}},"keywords":{}}],["medic",{"_index":2339,"title":{},"content":{"58":{"position":[[855,7]]},"66":{"position":[[112,7]]}},"keywords":{}}],["meet",{"_index":1596,"title":{},"content":{"34":{"position":[[580,4]]}},"keywords":{}}],["meets_dd",{"_index":841,"title":{},"content":{"20":{"position":[[2184,8]]}},"keywords":{}}],["meets_dd(x",{"_index":821,"title":{},"content":{"20":{"position":[[1514,12]]}},"keywords":{}}],["meets_sharp",{"_index":818,"title":{},"content":{"20":{"position":[[1447,12],[2143,12]]}},"keywords":{}}],["megabyt",{"_index":3466,"title":{},"content":{"101":{"position":[[77,9]]},"105":{"position":[[825,9]]},"195":{"position":[[402,9],[768,9]]}},"keywords":{}}],["melodi",{"_index":3557,"title":{},"content":{"104":{"position":[[547,9]]}},"keywords":{}}],["memori",{"_index":623,"title":{"14":{"position":[[16,6]]},"15":{"position":[[13,6]]},"154":{"position":[[29,6]]},"177":{"position":[[28,6]]},"183":{"position":[[0,6]]},"191":{"position":[[27,6]]}},"content":{"14":{"position":[[43,7],[2959,6],[3350,6]]},"15":{"position":[[18,6],[687,6],[1293,6],[2630,6],[3018,6]]},"22":{"position":[[2804,6]]},"97":{"position":[[193,6]]},"98":{"position":[[795,6],[1058,7]]},"127":{"position":[[1084,7]]},"128":{"position":[[221,7],[936,7],[1407,6],[1764,7]]},"130":{"position":[[217,6]]},"132":{"position":[[193,6],[343,6],[750,6],[1038,6]]},"135":{"position":[[22,6],[255,6]]},"136":{"position":[[738,6],[967,6]]},"137":{"position":[[77,7]]},"140":{"position":[[130,6]]},"153":{"position":[[63,6]]},"155":{"position":[[976,6],[1114,6],[1252,6]]},"156":{"position":[[27,6],[99,6],[134,6],[451,7]]},"159":{"position":[[378,6],[1219,7]]},"160":{"position":[[478,6],[722,6],[817,6],[983,6],[1012,6],[1429,7],[1730,7],[1838,7],[2234,6],[2780,6],[2863,6],[3050,6],[3149,6],[4521,6]]},"164":{"position":[[370,6]]},"172":{"position":[[780,7],[864,6],[1063,6],[1353,6],[1566,6],[1715,6]]},"173":{"position":[[2096,6],[2184,6]]},"174":{"position":[[432,6],[586,6],[632,6],[911,6]]},"178":{"position":[[573,6]]},"180":{"position":[[64,6],[242,6]]},"183":{"position":[[760,6]]},"192":{"position":[[83,6],[252,6],[365,6],[512,6],[644,6]]},"193":{"position":[[275,6],[456,6],[1677,6],[2043,7],[3147,6]]},"194":{"position":[[565,6]]},"195":{"position":[[690,6],[787,6],[916,6],[1016,6]]},"196":{"position":[[878,6],[1339,6]]},"198":{"position":[[184,6]]},"199":{"position":[[12,6],[907,7],[1663,6]]}},"keywords":{}}],["memory"",{"_index":4683,"title":{},"content":{"160":{"position":[[1985,12]]}},"keywords":{}}],["memory."th",{"_index":5063,"title":{},"content":{"179":{"position":[[52,16]]}},"keywords":{}}],["memory.al",{"_index":5112,"title":{},"content":{"182":{"position":[[563,10]]}},"keywords":{}}],["memory.collect",{"_index":4639,"title":{},"content":{"159":{"position":[[1033,18]]}},"keywords":{}}],["memory.lik",{"_index":5111,"title":{},"content":{"182":{"position":[[467,11]]}},"keywords":{}}],["memory.som",{"_index":4641,"title":{},"content":{"159":{"position":[[1113,11]]}},"keywords":{}}],["memory?"",{"_index":4349,"title":{},"content":{"132":{"position":[[493,13]]}},"keywords":{}}],["memory_coupon",{"_index":681,"title":{},"content":{"15":{"position":[[1319,14],[1441,14]]}},"keywords":{}}],["memoryand",{"_index":4676,"title":{},"content":{"160":{"position":[[1357,9]]}},"keywords":{}}],["mention",{"_index":1221,"title":{},"content":{"28":{"position":[[744,10]]},"51":{"position":[[213,10]]},"97":{"position":[[3219,8]]},"104":{"position":[[1045,9]]},"125":{"position":[[483,10],[1996,7],[9580,10]]},"163":{"position":[[2392,10]]},"166":{"position":[[565,9]]},"180":{"position":[[19,7]]}},"keywords":{}}],["messag",{"_index":3375,"title":{},"content":{"97":{"position":[[1616,10],[3586,8],[3838,8],[4656,8]]},"112":{"position":[[1187,7],[1419,8]]},"113":{"position":[[139,9],[779,7],[863,7],[1313,7],[1435,7],[1539,7],[1992,7]]},"115":{"position":[[194,7]]},"116":{"position":[[294,7],[2644,8],[3253,7]]},"117":{"position":[[419,8],[701,7],[1086,7],[1513,7],[2107,9]]},"163":{"position":[[111,7]]},"164":{"position":[[290,9],[401,7],[506,8],[757,8],[820,7],[945,9],[986,7],[1065,7],[1161,7]]},"165":{"position":[[212,10],[413,8],[630,7],[763,8],[781,7],[874,7],[1160,8],[1254,7],[1328,7]]},"166":{"position":[[358,7],[454,8]]},"168":{"position":[[29,7],[83,7]]},"169":{"position":[[29,7],[96,7]]},"170":{"position":[[403,7]]}},"keywords":{}}],["message;phantomdata",{"_index":3825,"title":{},"content":{"117":{"position":[[793,19]]}},"keywords":{}}],["messages:[messag",{"_index":4829,"title":{},"content":{"165":{"position":[[679,19]]}},"keywords":{}}],["met",{"_index":4489,"title":{},"content":{"150":{"position":[[138,3]]}},"keywords":{}}],["method",{"_index":2826,"title":{},"content":{"86":{"position":[[131,8],[1197,6]]},"97":{"position":[[3329,6],[3494,6],[3991,6],[4114,6],[6520,7]]},"106":{"position":[[488,6]]},"112":{"position":[[1552,8],[1625,8],[1682,7]]},"127":{"position":[[493,8],[965,7]]},"129":{"position":[[2100,10],[2739,7]]},"144":{"position":[[13,7]]},"179":{"position":[[501,6]]}},"keywords":{}}],["method='nearest",{"_index":2435,"title":{},"content":{"62":{"position":[[1461,17]]}},"keywords":{}}],["methodolog",{"_index":3102,"title":{},"content":{"91":{"position":[[1598,11]]}},"keywords":{}}],["metobserv",{"_index":557,"title":{},"content":{"13":{"position":[[499,11]]},"14":{"position":[[552,11]]}},"keywords":{}}],["metric",{"_index":1379,"title":{},"content":{"30":{"position":[[2777,6]]},"40":{"position":[[1069,7]]},"91":{"position":[[258,7]]}},"keywords":{}}],["metropoli",{"_index":2626,"title":{},"content":{"73":{"position":[[554,10]]}},"keywords":{}}],["mi",{"_index":4978,"title":{},"content":{"174":{"position":[[193,3]]}},"keywords":{}}],["micro",{"_index":4421,"title":{},"content":{"139":{"position":[[569,5]]}},"keywords":{}}],["microsecond",{"_index":4623,"title":{},"content":{"158":{"position":[[204,11]]}},"keywords":{}}],["microsoft",{"_index":4409,"title":{},"content":{"137":{"position":[[252,9]]}},"keywords":{}}],["microwav",{"_index":4739,"title":{},"content":{"161":{"position":[[780,9]]}},"keywords":{}}],["mid",{"_index":1834,"title":{},"content":{"40":{"position":[[3188,3]]}},"keywords":{}}],["middl",{"_index":5292,"title":{},"content":{"193":{"position":[[1802,6],[2757,6]]}},"keywords":{}}],["midnight",{"_index":1476,"title":{},"content":{"30":{"position":[[9172,8],[9282,9]]},"93":{"position":[[1923,8]]}},"keywords":{}}],["midpoint",{"_index":2333,"title":{},"content":{"58":{"position":[[428,8]]},"91":{"position":[[270,8],[597,8],[690,9],[893,8],[1053,8],[1154,9],[1369,8],[2863,9],[3018,9]]},"92":{"position":[[675,9],[830,9]]}},"keywords":{}}],["midpoints.shift(1",{"_index":3135,"title":{},"content":{"91":{"position":[[3030,18]]},"92":{"position":[[842,18]]}},"keywords":{}}],["midrang",{"_index":3549,"title":{},"content":{"103":{"position":[[2383,8]]}},"keywords":{}}],["might'v",{"_index":3940,"title":{},"content":{"122":{"position":[[383,8]]}},"keywords":{}}],["migrat",{"_index":5044,"title":{},"content":{"176":{"position":[[426,8]]}},"keywords":{}}],["million",{"_index":2477,"title":{},"content":{"64":{"position":[[1149,7]]},"65":{"position":[[1306,7]]}},"keywords":{}}],["mime",{"_index":4094,"title":{},"content":{"125":{"position":[[4330,4],[4498,4],[4592,4],[4714,4]]}},"keywords":{}}],["mimick",{"_index":3876,"title":{},"content":{"121":{"position":[[224,9]]}},"keywords":{}}],["min",{"_index":1925,"title":{},"content":{"44":{"position":[[845,3]]},"90":{"position":[[1274,4],[1866,4],[1976,5],[2659,4],[3010,4],[3115,5]]}},"keywords":{}}],["min(ev",{"_index":3032,"title":{},"content":{"90":{"position":[[3728,11]]},"93":{"position":[[4972,11],[5387,11]]}},"keywords":{}}],["min/max",{"_index":3166,"title":{},"content":{"91":{"position":[[4826,7]]},"92":{"position":[[1489,7]]}},"keywords":{}}],["min_err",{"_index":3005,"title":{},"content":{"90":{"position":[[1831,7],[2975,7]]}},"keywords":{}}],["mind",{"_index":17,"title":{},"content":{"1":{"position":[[171,5]]},"95":{"position":[[421,4]]},"97":{"position":[[5248,5]]},"123":{"position":[[788,4]]},"125":{"position":[[11613,4]]},"129":{"position":[[1747,4]]},"160":{"position":[[2103,5]]},"188":{"position":[[2837,4]]}},"keywords":{}}],["mindblown",{"_index":2243,"title":{},"content":{"53":{"position":[[1022,10]]}},"keywords":{}}],["mindshar",{"_index":3440,"title":{},"content":{"98":{"position":[[402,9]]}},"keywords":{}}],["minim",{"_index":804,"title":{},"content":{"20":{"position":[[1048,8],[1360,10],[1936,10],[2462,10]]},"125":{"position":[[9288,7]]}},"keywords":{}}],["minimize(object",{"_index":842,"title":{},"content":{"20":{"position":[[2207,19]]}},"keywords":{}}],["minimum",{"_index":2824,"title":{},"content":{"85":{"position":[[536,8]]},"90":{"position":[[5244,7]]},"172":{"position":[[649,7]]},"173":{"position":[[1278,7]]}},"keywords":{}}],["minor",{"_index":2543,"title":{},"content":{"66":{"position":[[351,5]]},"130":{"position":[[90,5]]}},"keywords":{}}],["minu",{"_index":740,"title":{},"content":{"19":{"position":[[97,5]]}},"keywords":{}}],["minut",{"_index":292,"title":{},"content":{"4":{"position":[[1356,8]]},"62":{"position":[[1267,7]]},"64":{"position":[[1280,7],[1323,7]]},"65":{"position":[[2206,6],[2245,7]]},"93":{"position":[[5088,7]]},"101":{"position":[[91,6]]},"121":{"position":[[2098,7]]}},"keywords":{}}],["minute_mean",{"_index":2483,"title":{},"content":{"64":{"position":[[1472,11],[1606,11]]},"65":{"position":[[2379,11]]}},"keywords":{}}],["minutes_left",{"_index":2530,"title":{},"content":{"65":{"position":[[2346,12]]}},"keywords":{}}],["mirror",{"_index":4340,"title":{},"content":{"132":{"position":[[70,6]]}},"keywords":{}}],["miss",{"_index":96,"title":{},"content":{"2":{"position":[[339,8]]},"28":{"position":[[2441,7],[4054,7]]},"30":{"position":[[2721,7]]},"62":{"position":[[1280,7]]},"91":{"position":[[3955,7]]},"97":{"position":[[4266,8]]},"121":{"position":[[2404,4]]},"125":{"position":[[6462,7]]}},"keywords":{}}],["mistak",{"_index":75,"title":{},"content":{"2":{"position":[[21,8]]},"3":{"position":[[22,8]]},"66":{"position":[[357,9]]},"98":{"position":[[835,7]]},"127":{"position":[[413,8]]},"136":{"position":[[211,8]]},"158":{"position":[[415,9]]}},"keywords":{}}],["mitig",{"_index":5055,"title":{},"content":{"176":{"position":[[1584,8]]}},"keywords":{}}],["mix",{"_index":281,"title":{},"content":{"4":{"position":[[1109,3]]},"66":{"position":[[415,3]]},"121":{"position":[[1019,5]]},"125":{"position":[[10685,6]]},"147":{"position":[[88,6]]}},"keywords":{}}],["mkdir",{"_index":3680,"title":{},"content":{"109":{"position":[[128,5]]},"110":{"position":[[348,5]]}},"keywords":{}}],["mle",{"_index":2120,"title":{},"content":{"51":{"position":[[2087,3],[2109,3]]}},"keywords":{}}],["mod",{"_index":3732,"title":{},"content":{"113":{"position":[[444,3]]}},"keywords":{}}],["mode",{"_index":4444,"title":{},"content":{"143":{"position":[[437,4]]},"160":{"position":[[3663,4]]},"189":{"position":[[531,4],[802,4],[1234,4]]}},"keywords":{}}],["mode=develop",{"_index":4118,"title":{},"content":{"125":{"position":[[5403,16],[5528,16]]}},"keywords":{}}],["mode=product",{"_index":4129,"title":{},"content":{"125":{"position":[[5990,15]]}},"keywords":{}}],["model",{"_index":458,"title":{},"content":{"9":{"position":[[104,6]]},"43":{"position":[[112,5]]},"45":{"position":[[687,5],[865,5],[1253,5],[1295,5],[1508,5],[1674,6],[1865,5]]},"46":{"position":[[270,5]]},"53":{"position":[[1853,7]]},"73":{"position":[[447,5]]},"82":{"position":[[1298,5]]},"86":{"position":[[801,8]]},"160":{"position":[[4528,6]]}},"keywords":{}}],["modern",{"_index":267,"title":{},"content":{"4":{"position":[[885,6]]},"174":{"position":[[54,6],[1135,6]]},"176":{"position":[[356,6]]}},"keywords":{}}],["modif",{"_index":2694,"title":{},"content":{"76":{"position":[[911,14]]}},"keywords":{}}],["modifi",{"_index":2664,"title":{},"content":{"75":{"position":[[486,6]]},"125":{"position":[[2318,8]]},"179":{"position":[[268,6],[521,6]]},"186":{"position":[[553,8]]}},"keywords":{}}],["modify.valu",{"_index":5060,"title":{},"content":{"178":{"position":[[601,13]]}},"keywords":{}}],["modul",{"_index":210,"title":{},"content":{"3":{"position":[[1409,6]]},"4":{"position":[[798,7],[1233,8]]},"113":{"position":[[369,6]]},"125":{"position":[[8513,6],[8981,6],[11237,6]]}},"keywords":{}}],["modules"",{"_index":4165,"title":{},"content":{"125":{"position":[[8432,13]]}},"keywords":{}}],["moistur",{"_index":4751,"title":{},"content":{"161":{"position":[[1194,8]]}},"keywords":{}}],["moment",{"_index":1316,"title":{},"content":{"29":{"position":[[294,7]]},"51":{"position":[[1052,7]]},"64":{"position":[[2016,6]]},"97":{"position":[[1008,7]]},"125":{"position":[[3590,7],[7362,7],[10717,7],[10863,7]]},"150":{"position":[[901,8]]},"175":{"position":[[329,6]]}},"keywords":{}}],["monday",{"_index":2850,"title":{},"content":{"88":{"position":[[473,6],[1189,7]]},"90":{"position":[[3623,6]]}},"keywords":{}}],["money",{"_index":1165,"title":{"31":{"position":[[11,5]]}},"content":{"25":{"position":[[2796,5]]},"26":{"position":[[313,5],[684,5]]},"32":{"position":[[328,5],[602,5],[751,6],[1034,6],[1188,5],[1302,5],[1350,6],[1400,5],[2181,5],[2349,6]]},"33":{"position":[[116,5],[264,5],[574,5],[892,5],[1070,5]]},"34":{"position":[[888,6],[966,5]]},"35":{"position":[[176,6],[247,5]]},"36":{"position":[[75,5]]},"38":{"position":[[348,5]]}},"keywords":{}}],["money"",{"_index":1513,"title":{},"content":{"32":{"position":[[82,11]]}},"keywords":{}}],["money.it'",{"_index":1581,"title":{},"content":{"33":{"position":[[967,10]]}},"keywords":{}}],["monkey'",{"_index":3473,"title":{},"content":{"101":{"position":[[389,8]]}},"keywords":{}}],["monomorph",{"_index":5337,"title":{},"content":{"197":{"position":[[57,18],[706,17]]}},"keywords":{}}],["monorepo",{"_index":146,"title":{},"content":{"3":{"position":[[286,8]]}},"keywords":{}}],["mont",{"_index":2300,"title":{},"content":{"55":{"position":[[118,5]]}},"keywords":{}}],["month",{"_index":415,"title":{},"content":{"7":{"position":[[755,6]]},"28":{"position":[[1235,7],[1289,6],[1323,5],[1808,7],[1856,6],[1879,6],[1976,6],[1995,7],[2459,6],[2567,6],[2735,6],[3035,7],[3089,6],[3123,5],[3560,7],[3604,6],[3631,6],[3650,7],[4205,6]]},"30":{"position":[[556,6],[1372,6],[1601,7],[1655,6],[1689,5],[2044,7],[2950,7],[3004,6],[3038,5],[3450,7],[3538,7],[4554,6],[4588,5],[4874,7],[4928,6],[4962,5],[5294,7],[5597,5],[5654,6],[5720,6],[6018,7],[6072,6],[6106,5],[6524,7],[6612,7],[7322,7],[7470,6]]},"57":{"position":[[571,7]]},"58":{"position":[[728,6]]},"63":{"position":[[73,6]]},"64":{"position":[[289,5]]},"66":{"position":[[242,7]]},"123":{"position":[[463,6]]},"124":{"position":[[671,5]]},"125":{"position":[[2241,7],[10835,6]]}},"keywords":{}}],["month_averag",{"_index":1268,"title":{},"content":{"28":{"position":[[2003,14],[3658,14]]}},"keywords":{}}],["month_averages[c",{"_index":1276,"title":{},"content":{"28":{"position":[[2251,22],[3924,22]]}},"keywords":{}}],["month_id",{"_index":1267,"title":{},"content":{"28":{"position":[[1983,8],[2045,9],[3638,8],[3700,9]]}},"keywords":{}}],["monthli",{"_index":1370,"title":{},"content":{"30":{"position":[[2313,7],[2905,7]]}},"keywords":{}}],["monthly_avg_cloudcover(c",{"_index":1239,"title":{},"content":{"28":{"position":[[1200,28],[1823,29]]}},"keywords":{}}],["monthly_avg_cloudcover(i",{"_index":1360,"title":{},"content":{"30":{"position":[[1985,27]]}},"keywords":{}}],["monthly_avg_cloudcover(year",{"_index":1357,"title":{},"content":{"30":{"position":[[1572,28]]}},"keywords":{}}],["monthly_avg_precip(c",{"_index":1298,"title":{},"content":{"28":{"position":[[3004,24],[3575,25]]}},"keywords":{}}],["monthly_avg_precip(i",{"_index":1407,"title":{},"content":{"30":{"position":[[5239,23]]}},"keywords":{}}],["monthly_avg_precip(year",{"_index":1404,"title":{},"content":{"30":{"position":[[4849,24]]}},"keywords":{}}],["monthly_avg_precip_v",{"_index":1406,"title":{},"content":{"30":{"position":[[5213,23]]}},"keywords":{}}],["monthly_avg_precip_vals[x",{"_index":1408,"title":{},"content":{"30":{"position":[[5448,27]]}},"keywords":{}}],["monthly_cloudy_days(i",{"_index":1386,"title":{},"content":{"30":{"position":[[3394,24],[3482,24]]}},"keywords":{}}],["monthly_cloudy_days(year",{"_index":1382,"title":{},"content":{"30":{"position":[[2924,25]]}},"keywords":{}}],["monthly_cover_sampl",{"_index":1387,"title":{},"content":{"30":{"position":[[3458,21]]}},"keywords":{}}],["monthly_cover_samples[x",{"_index":1391,"title":{},"content":{"30":{"position":[[3894,25]]}},"keywords":{}}],["monthly_cover_v",{"_index":1359,"title":{},"content":{"30":{"position":[[1964,18]]}},"keywords":{}}],["monthly_cover_vals[x",{"_index":1366,"title":{},"content":{"30":{"position":[[2189,22]]}},"keywords":{}}],["monthly_days_v",{"_index":1385,"title":{},"content":{"30":{"position":[[3374,17]]}},"keywords":{}}],["monthly_days_vals[x",{"_index":1389,"title":{},"content":{"30":{"position":[[3675,21]]}},"keywords":{}}],["monthly_precip_days_v",{"_index":1423,"title":{},"content":{"30":{"position":[[6442,24]]}},"keywords":{}}],["monthly_precip_days_vals[x",{"_index":1426,"title":{},"content":{"30":{"position":[[6748,28]]}},"keywords":{}}],["monthly_precip_sampl",{"_index":1425,"title":{},"content":{"30":{"position":[[6532,22]]}},"keywords":{}}],["monthly_precip_samples[x",{"_index":1427,"title":{},"content":{"30":{"position":[[6973,26]]}},"keywords":{}}],["monthly_rainy_days(i",{"_index":1424,"title":{},"content":{"30":{"position":[[6469,23],[6557,23]]}},"keywords":{}}],["monthly_rainy_days(year",{"_index":1417,"title":{},"content":{"30":{"position":[[5993,24]]}},"keywords":{}}],["months_str",{"_index":1356,"title":{},"content":{"30":{"position":[[1394,10]]}},"keywords":{}}],["moore'",{"_index":4406,"title":{},"content":{"137":{"position":[[185,7]]}},"keywords":{}}],["morbid",{"_index":2315,"title":{},"content":{"57":{"position":[[413,8]]}},"keywords":{}}],["more",{"_index":239,"title":{"105":{"position":[[2,4]]},"149":{"position":[[0,4]]}},"content":{"4":{"position":[[411,4],[600,4]]},"9":{"position":[[77,4]]},"12":{"position":[[175,4]]},"24":{"position":[[331,4]]},"26":{"position":[[81,4],[913,4]]},"28":{"position":[[2624,4]]},"29":{"position":[[220,4]]},"30":{"position":[[576,4],[2772,4],[4085,4],[5603,4],[5734,4],[7581,4],[7734,5],[9195,4]]},"33":{"position":[[6,4]]},"34":{"position":[[330,4]]},"35":{"position":[[299,4]]},"40":{"position":[[887,4],[932,4],[2099,4],[3498,4]]},"43":{"position":[[828,4]]},"44":{"position":[[1975,4]]},"45":{"position":[[1477,4]]},"46":{"position":[[568,4]]},"51":{"position":[[854,4],[969,4]]},"53":{"position":[[321,4],[1654,4]]},"55":{"position":[[203,4]]},"57":{"position":[[389,4]]},"61":{"position":[[1593,4]]},"68":{"position":[[181,4]]},"70":{"position":[[1380,5]]},"71":{"position":[[1492,4]]},"72":{"position":[[431,4]]},"73":{"position":[[136,4]]},"74":{"position":[[244,4]]},"86":{"position":[[538,4]]},"91":{"position":[[5122,4]]},"93":{"position":[[888,4],[943,4],[1143,4]]},"95":{"position":[[303,4]]},"97":{"position":[[1210,4],[2469,4],[4065,4]]},"98":{"position":[[1163,5]]},"101":{"position":[[610,4],[686,4]]},"104":{"position":[[32,4],[1303,4]]},"105":{"position":[[2871,4]]},"106":{"position":[[1149,4]]},"108":{"position":[[557,4]]},"121":{"position":[[803,4],[2758,4]]},"122":{"position":[[102,4]]},"124":{"position":[[850,5]]},"125":{"position":[[415,4],[2096,4],[3621,4],[6960,4]]},"129":{"position":[[765,4]]},"139":{"position":[[461,4]]},"141":{"position":[[303,4]]},"145":{"position":[[25,4]]},"148":{"position":[[21,4],[426,4]]},"155":{"position":[[668,4],[885,4]]},"156":{"position":[[94,4]]},"161":{"position":[[86,4],[1614,4]]},"163":{"position":[[2176,4]]},"170":{"position":[[442,4]]},"172":{"position":[[553,4]]},"174":{"position":[[627,4],[949,4],[1014,4],[1150,4]]},"182":{"position":[[314,4]]},"185":{"position":[[338,4]]},"188":{"position":[[266,5],[4314,4]]},"190":{"position":[[109,4]]},"195":{"position":[[513,5]]},"199":{"position":[[1433,4]]}},"keywords":{}}],["morn",{"_index":2198,"title":{},"content":{"53":{"position":[[206,8]]}},"keywords":{}}],["mostli",{"_index":1373,"title":{},"content":{"30":{"position":[[2467,6],[7345,6]]},"41":{"position":[[164,6]]},"57":{"position":[[223,6]]},"91":{"position":[[3192,6]]},"92":{"position":[[1004,6]]},"97":{"position":[[2644,8]]},"124":{"position":[[592,6]]},"125":{"position":[[2849,6],[3272,6]]},"155":{"position":[[552,6]]}},"keywords":{}}],["moststruct",{"_index":5134,"title":{},"content":{"185":{"position":[[203,10]]}},"keywords":{}}],["motion",{"_index":392,"title":{},"content":{"7":{"position":[[351,6],[519,6],[604,6]]},"8":{"position":[[164,6]]},"9":{"position":[[30,6]]},"12":{"position":[[48,6]]},"13":{"position":[[1312,6]]},"14":{"position":[[2384,6]]},"15":{"position":[[2056,6]]}},"keywords":{}}],["motion[:,1",{"_index":394,"title":{},"content":{"7":{"position":[[372,11]]}},"keywords":{}}],["motion[:,i",{"_index":397,"title":{},"content":{"7":{"position":[[442,11]]}},"keywords":{}}],["motion[:,i+1",{"_index":396,"title":{},"content":{"7":{"position":[[426,13]]}},"keywords":{}}],["mov",{"_index":4257,"title":{},"content":{"128":{"position":[[456,3],[519,3],[627,3],[654,3],[725,3],[768,3],[866,3],[980,3],[1414,3],[1584,3]]},"129":{"position":[[539,3],[582,3],[676,3]]},"181":{"position":[[169,4],[296,4],[428,3]]},"193":{"position":[[3490,5]]}},"keywords":{}}],["move",{"_index":108,"title":{"54":{"position":[[0,6]]},"115":{"position":[[11,4]]}},"content":{"2":{"position":[[474,6]]},"3":{"position":[[212,6]]},"14":{"position":[[7,4]]},"24":{"position":[[3166,4]]},"28":{"position":[[2812,4]]},"33":{"position":[[999,4]]},"63":{"position":[[163,4]]},"65":{"position":[[1241,4]]},"90":{"position":[[5367,5]]},"91":{"position":[[4606,4],[5455,5],[5813,4]]},"97":{"position":[[1556,4],[4768,6],[4870,4],[4999,4],[5121,4]]},"115":{"position":[[53,4],[537,4]]},"116":{"position":[[668,4]]},"117":{"position":[[978,4],[1942,6]]},"123":{"position":[[129,6],[314,7],[882,6]]},"125":{"position":[[2484,6]]},"152":{"position":[[170,4]]},"173":{"position":[[2059,5]]},"175":{"position":[[1285,4]]},"192":{"position":[[438,4]]},"193":{"position":[[3027,6],[3213,6]]},"195":{"position":[[994,4]]},"196":{"position":[[1124,4]]},"198":{"position":[[15,4],[363,5],[880,4]]}},"keywords":{}}],["mozilla/5.0",{"_index":3222,"title":{},"content":{"93":{"position":[[2357,12]]}},"keywords":{}}],["mp3",{"_index":3476,"title":{},"content":{"101":{"position":[[577,4]]},"102":{"position":[[712,4]]},"104":{"position":[[1719,4]]}},"keywords":{}}],["mpsc",{"_index":3837,"title":{},"content":{"117":{"position":[[2017,4]]}},"keywords":{}}],["ms",{"_index":5173,"title":{},"content":{"188":{"position":[[1594,3],[1620,2],[1638,2],[1692,3],[1718,2],[1736,2],[2261,3],[2275,3],[2290,2],[2308,2],[2578,3],[2606,2],[2624,2],[3116,3],[3142,2],[3160,2]]},"189":{"position":[[1782,3],[1810,2],[1828,2],[2237,3],[2251,3],[2266,2],[2284,2],[2520,3],[2534,3],[2549,2],[2567,2],[2809,3],[2835,2],[2853,2]]}},"keywords":{}}],["mu",{"_index":779,"title":{},"content":{"20":{"position":[[596,3]]}},"keywords":{}}],["much",{"_index":382,"title":{},"content":{"7":{"position":[[124,4]]},"18":{"position":[[27,4]]},"32":{"position":[[366,4],[931,5],[1395,4]]},"33":{"position":[[818,4]]},"34":{"position":[[222,4],[797,4],[937,4]]},"35":{"position":[[59,4]]},"40":{"position":[[2178,4]]},"43":{"position":[[1204,4]]},"44":{"position":[[977,4]]},"57":{"position":[[698,4]]},"66":{"position":[[567,4],[860,4]]},"74":{"position":[[1179,4]]},"82":{"position":[[1070,4]]},"83":{"position":[[401,4]]},"86":{"position":[[1064,4]]},"88":{"position":[[958,4],[3813,4]]},"90":{"position":[[18,4],[5331,4]]},"93":{"position":[[1138,4]]},"95":{"position":[[298,4],[540,4]]},"97":{"position":[[2321,4]]},"101":{"position":[[277,4]]},"105":{"position":[[404,4]]},"111":{"position":[[806,4],[909,4]]},"120":{"position":[[1098,4]]},"125":{"position":[[252,4],[818,4],[5738,4],[7241,4],[10608,4]]},"127":{"position":[[56,4]]},"132":{"position":[[261,4]]},"135":{"position":[[161,4],[250,4]]},"153":{"position":[[24,4]]},"160":{"position":[[2720,4],[3144,4],[3392,4]]},"182":{"position":[[309,4]]},"188":{"position":[[2718,5]]},"194":{"position":[[560,4]]}},"keywords":{}}],["mul",{"_index":5117,"title":{},"content":{"183":{"position":[[382,4],[528,4]]}},"keywords":{}}],["multi",{"_index":1716,"title":{},"content":{"39":{"position":[[376,5]]},"173":{"position":[[1980,5]]}},"keywords":{}}],["multicast",{"_index":5022,"title":{},"content":{"175":{"position":[[926,10]]}},"keywords":{}}],["multimessag",{"_index":4828,"title":{},"content":{"165":{"position":[[664,12],[723,12],[930,13]]}},"keywords":{}}],["multinom_sim(1",{"_index":2161,"title":{},"content":{"51":{"position":[[4015,15],[4200,15]]}},"keywords":{}}],["multinom_sim(n",{"_index":2149,"title":{},"content":{"51":{"position":[[3610,15],[3870,15]]}},"keywords":{}}],["multinomi",{"_index":2142,"title":{},"content":{"51":{"position":[[3170,11]]}},"keywords":{}}],["multipl",{"_index":1839,"title":{},"content":{"40":{"position":[[3518,8]]},"43":{"position":[[866,8]]},"86":{"position":[[301,8]]},"121":{"position":[[1532,8]]},"193":{"position":[[606,8]]}},"keywords":{}}],["multipli",{"_index":851,"title":{},"content":{"20":{"position":[[2416,8]]},"64":{"position":[[1292,8]]},"74":{"position":[[1329,8]]},"183":{"position":[[694,11]]}},"keywords":{}}],["multiply(valu",{"_index":5095,"title":{},"content":{"180":{"position":[[425,15]]},"181":{"position":[[105,15]]},"183":{"position":[[330,15]]}},"keywords":{}}],["multiply_twic",{"_index":5102,"title":{},"content":{"181":{"position":[[478,14]]}},"keywords":{}}],["multiply_twice(valu",{"_index":5099,"title":{},"content":{"181":{"position":[[221,21]]},"183":{"position":[[470,21]]}},"keywords":{}}],["music",{"_index":2263,"title":{},"content":{"53":{"position":[[1285,5],[2000,5]]},"100":{"position":[[189,6]]},"104":{"position":[[1672,5]]}},"keywords":{}}],["mustcontext",{"_index":4960,"title":{},"content":{"173":{"position":[[1140,11]]}},"keywords":{}}],["mut",{"_index":3384,"title":{},"content":{"97":{"position":[[1909,3]]},"112":{"position":[[1362,3],[1375,3],[1398,3]]},"113":{"position":[[944,3],[1348,3],[1594,3]]},"152":{"position":[[1362,4],[1512,4]]},"156":{"position":[[1445,4],[1595,4]]},"179":{"position":[[117,3]]},"186":{"position":[[23,3]]},"199":{"position":[[1276,3],[1419,3],[1577,3]]}},"keywords":{}}],["mut.refcel",{"_index":5067,"title":{},"content":{"179":{"position":[[303,11]]}},"keywords":{}}],["mutabl",{"_index":3740,"title":{"186":{"position":[[9,11]]}},"content":{"113":{"position":[[1019,7],[1119,7]]},"136":{"position":[[540,7]]},"179":{"position":[[254,10],[806,10]]},"182":{"position":[[636,10]]},"186":{"position":[[141,10]]}},"keywords":{}}],["mutat",{"_index":5137,"title":{},"content":{"186":{"position":[[50,8],[421,6]]}},"keywords":{}}],["mutex",{"_index":4638,"title":{},"content":{"159":{"position":[[988,6]]}},"keywords":{}}],["my_appl",{"_index":4374,"title":{},"content":{"134":{"position":[[157,14]]}},"keywords":{}}],["my_arc",{"_index":4584,"title":{},"content":{"155":{"position":[[1470,8]]}},"keywords":{}}],["my_box",{"_index":4578,"title":{},"content":{"155":{"position":[[1346,8]]}},"keywords":{}}],["my_cow",{"_index":4587,"title":{},"content":{"155":{"position":[[1533,8]]}},"keywords":{}}],["my_func",{"_index":5332,"title":{},"content":{"196":{"position":[[940,9],[1162,12],[1175,12],[1559,10],[1578,10],[1761,10],[1780,10]]}},"keywords":{}}],["my_funct",{"_index":4263,"title":{},"content":{"128":{"position":[[594,13],[674,13],[713,11],[746,12],[1344,13],[1432,13]]},"140":{"position":[[4,13]]},"141":{"position":[[4,13]]}},"keywords":{}}],["my_function(int",{"_index":4249,"title":{},"content":{"128":{"position":[[235,15]]}},"keywords":{}}],["my_function(self",{"_index":4305,"title":{},"content":{"129":{"position":[[1943,18]]}},"keywords":{}}],["my_function(v",{"_index":4439,"title":{},"content":{"142":{"position":[[4,14]]}},"keywords":{}}],["my_function(x",{"_index":4251,"title":{},"content":{"128":{"position":[[283,15],[1109,14],[1155,14]]}},"keywords":{}}],["my_lock",{"_index":5131,"title":{},"content":{"184":{"position":[[1117,8]]}},"keywords":{}}],["my_mutator(&cel",{"_index":5075,"title":{},"content":{"179":{"position":[[663,22],[1066,22]]}},"keywords":{}}],["my_mutator(cel",{"_index":5069,"title":{},"content":{"179":{"position":[[390,16],[910,16]]}},"keywords":{}}],["my_rc",{"_index":4581,"title":{},"content":{"155":{"position":[[1409,7]]}},"keywords":{}}],["my_struct",{"_index":5122,"title":{},"content":{"184":{"position":[[182,10],[367,11],[612,10],[716,11]]},"185":{"position":[[798,10]]}},"keywords":{}}],["my_val",{"_index":4299,"title":{},"content":{"129":{"position":[[1546,6]]},"184":{"position":[[276,6],[293,7]]}},"keywords":{}}],["my_val.to_str",{"_index":4300,"title":{},"content":{"129":{"position":[[1593,19]]}},"keywords":{}}],["my_vec",{"_index":4598,"title":{},"content":{"156":{"position":[[630,8]]}},"keywords":{}}],["myclass",{"_index":4304,"title":{},"content":{"129":{"position":[[1921,10],[1980,9]]}},"keywords":{}}],["myclass.my_function(m",{"_index":4308,"title":{},"content":{"129":{"position":[[2006,22]]}},"keywords":{}}],["myenum",{"_index":5311,"title":{},"content":{"194":{"position":[[224,6],[278,7],[289,7]]}},"keywords":{}}],["myenum::large(0",{"_index":5316,"title":{},"content":{"194":{"position":[[357,17]]}},"keywords":{}}],["myenum::small(0",{"_index":5315,"title":{},"content":{"194":{"position":[[331,17]]}},"keywords":{}}],["myself",{"_index":232,"title":{},"content":{"4":{"position":[[225,7]]},"35":{"position":[[485,8]]},"45":{"position":[[1813,8]]},"121":{"position":[[936,6]]},"125":{"position":[[192,6],[8163,6]]}},"keywords":{}}],["mystruct",{"_index":5121,"title":{},"content":{"184":{"position":[[155,8],[193,8],[204,8],[345,9],[514,8],[539,8],[571,8],[582,8],[623,8],[694,9]]},"185":{"position":[[477,8],[660,8],[809,8],[820,8]]},"194":{"position":[[264,8],[383,8]]}},"keywords":{}}],["mystruct::new",{"_index":5125,"title":{},"content":{"184":{"position":[[634,16]]}},"keywords":{}}],["myval",{"_index":4296,"title":{},"content":{"129":{"position":[[1434,5],[1456,5],[1555,5]]}},"keywords":{}}],["myval::to_string(&my_v",{"_index":4301,"title":{},"content":{"129":{"position":[[1613,30]]}},"keywords":{}}],["n",{"_index":367,"title":{"91":{"position":[[42,1]]},"92":{"position":[[30,1]]}},"content":{"6":{"position":[[1003,1]]},"7":{"position":[[299,2],[349,1],[369,2],[611,1],[940,1]]},"11":{"position":[[497,2]]},"12":{"position":[[248,2],[456,2],[563,2]]},"13":{"position":[[1344,2]]},"14":{"position":[[2416,2]]},"15":{"position":[[2088,2]]},"64":{"position":[[549,1],[564,2]]},"65":{"position":[[443,1],[458,2]]},"70":{"position":[[957,3],[998,2]]},"78":{"position":[[189,2],[222,2]]},"89":{"position":[[598,1]]},"91":{"position":[[351,1]]},"105":{"position":[[1731,2],[1742,2]]},"188":{"position":[[1013,2],[1026,1],[1044,1],[1114,3],[1180,3],[1314,3],[3552,2],[3565,1]]},"189":{"position":[[1115,1],[1133,1],[1176,3],[1385,1],[1403,1],[1446,3],[3109,1]]}},"keywords":{}}],["n*i",{"_index":581,"title":{},"content":{"13":{"position":[[1296,4]]},"14":{"position":[[2368,4]]},"15":{"position":[[2040,4]]}},"keywords":{}}],["n=10000",{"_index":2749,"title":{},"content":{"78":{"position":[[149,9]]}},"keywords":{}}],["n=250",{"_index":2789,"title":{},"content":{"82":{"position":[[246,6]]}},"keywords":{}}],["n_compon",{"_index":3521,"title":{},"content":{"103":{"position":[[896,13],[1597,12]]},"105":{"position":[[1360,13],[1439,13]]}},"keywords":{}}],["n_hash",{"_index":2186,"title":{},"content":{"52":{"position":[[791,6]]}},"keywords":{}}],["n_hashtag",{"_index":2123,"title":{},"content":{"51":{"position":[[2306,10],[2491,10]]}},"keywords":{}}],["naiv",{"_index":1947,"title":{},"content":{"44":{"position":[[1624,5],[1697,5]]},"45":{"position":[[18,5],[173,5],[998,5],[1241,5],[1662,5],[1887,5],[2414,5],[2600,5],[3194,5]]}},"keywords":{}}],["naive_guess",{"_index":1940,"title":{},"content":{"44":{"position":[[1456,11]]},"45":{"position":[[2381,12],[3161,12]]}},"keywords":{}}],["name",{"_index":664,"title":{},"content":{"15":{"position":[[78,4]]},"93":{"position":[[4769,4],[5184,4]]},"109":{"position":[[250,4]]},"112":{"position":[[689,4]]},"120":{"position":[[750,4]]},"121":{"position":[[508,6]]},"127":{"position":[[26,4],[164,4]]},"134":{"position":[[267,4]]},"183":{"position":[[754,5]]},"196":{"position":[[525,5]]}},"keywords":{}}],["nan",{"_index":1250,"title":{},"content":{"28":{"position":[[1588,3],[3374,3]]}},"keywords":{}}],["nanmean",{"_index":1249,"title":{},"content":{"28":{"position":[[1569,7],[3355,7]]}},"keywords":{}}],["nano",{"_index":4422,"title":{},"content":{"139":{"position":[[579,4]]}},"keywords":{}}],["nasdaq",{"_index":997,"title":{},"content":{"23":{"position":[[151,6],[566,6]]},"24":{"position":[[2506,6],[2585,6],[2658,6],[2797,6],[2946,6],[3454,6]]},"25":{"position":[[2229,6],[2308,6],[2381,6],[2520,6],[2688,6],[2706,6]]},"26":{"position":[[515,6]]},"93":{"position":[[3228,9]]}},"keywords":{}}],["nasdaq_close_ret",{"_index":1146,"title":{},"content":{"25":{"position":[[602,16],[1505,17]]}},"keywords":{}}],["nasdaq_open_ret",{"_index":1044,"title":{},"content":{"24":{"position":[[883,15],[1782,16]]}},"keywords":{}}],["nasti",{"_index":1206,"title":{},"content":{"28":{"position":[[268,5]]},"112":{"position":[[980,6]]},"125":{"position":[[7721,5]]}},"keywords":{}}],["nativ",{"_index":4041,"title":{},"content":{"125":{"position":[[1298,6]]},"172":{"position":[[2067,6]]}},"keywords":{}}],["natur",{"_index":4715,"title":{},"content":{"160":{"position":[[3957,6]]}},"keywords":{}}],["navig",{"_index":3934,"title":{},"content":{"122":{"position":[[149,10]]}},"keywords":{}}],["nb",{"_index":2007,"title":{},"content":{"45":{"position":[[2283,2],[3063,2]]}},"keywords":{}}],["ncseattl",{"_index":1210,"title":{},"content":{"28":{"position":[[388,10]]}},"keywords":{}}],["near",{"_index":1884,"title":{},"content":{"43":{"position":[[940,4]]}},"keywords":{}}],["nearli",{"_index":2314,"title":{},"content":{"57":{"position":[[403,6]]},"92":{"position":[[1368,6]]},"104":{"position":[[1858,6]]},"105":{"position":[[2584,6]]},"124":{"position":[[97,6]]},"175":{"position":[[791,6]]}},"keywords":{}}],["neat",{"_index":1852,"title":{},"content":{"41":{"position":[[348,4]]}},"keywords":{}}],["necessari",{"_index":3498,"title":{},"content":{"102":{"position":[[1070,11]]},"113":{"position":[[1265,9]]},"123":{"position":[[912,9]]},"125":{"position":[[3738,9],[11074,9]]},"152":{"position":[[133,10]]},"156":{"position":[[161,10]]},"157":{"position":[[598,9]]},"174":{"position":[[730,9]]},"189":{"position":[[756,9]]},"196":{"position":[[1940,10]]}},"keywords":{}}],["necessarili",{"_index":5054,"title":{},"content":{"176":{"position":[[1471,11]]}},"keywords":{}}],["need",{"_index":23,"title":{},"content":{"1":{"position":[[250,4]]},"6":{"position":[[46,4]]},"9":{"position":[[289,4]]},"22":{"position":[[822,4]]},"30":{"position":[[2546,4],[4130,4]]},"34":{"position":[[53,4],[174,4],[315,4],[3508,4]]},"35":{"position":[[202,5]]},"39":{"position":[[1902,4]]},"43":{"position":[[14,4],[149,4],[1436,4]]},"44":{"position":[[468,4]]},"49":{"position":[[158,4],[408,4]]},"51":{"position":[[706,4],[2750,4],[3504,4]]},"52":{"position":[[35,4]]},"54":{"position":[[252,5]]},"55":{"position":[[220,7]]},"61":{"position":[[303,4],[349,4],[398,4],[823,4],[990,7],[1438,4],[1588,4],[2278,4]]},"62":{"position":[[1300,4]]},"64":{"position":[[1176,4]]},"74":{"position":[[237,4],[850,4]]},"76":{"position":[[558,4],[837,4]]},"86":{"position":[[974,6],[1115,6]]},"89":{"position":[[211,4]]},"91":{"position":[[156,4],[1976,4],[2270,4]]},"93":{"position":[[3764,6],[4389,4]]},"95":{"position":[[86,4]]},"96":{"position":[[891,4],[2083,4]]},"97":{"position":[[3008,4],[3419,4],[6008,4]]},"98":{"position":[[174,4]]},"101":{"position":[[200,5]]},"102":{"position":[[1047,6]]},"103":{"position":[[190,4]]},"104":{"position":[[274,4],[423,4],[571,5]]},"105":{"position":[[418,4]]},"106":{"position":[[244,6]]},"108":{"position":[[28,6],[215,4],[666,4]]},"109":{"position":[[626,4]]},"112":{"position":[[378,4]]},"113":{"position":[[179,4],[1012,4]]},"121":{"position":[[2358,4]]},"122":{"position":[[270,4]]},"123":{"position":[[160,7],[285,7],[932,5],[1048,4]]},"124":{"position":[[724,4]]},"125":{"position":[[6970,5],[7287,6],[9451,4],[10975,4],[11050,5],[11177,4],[11265,4]]},"128":{"position":[[10,4]]},"137":{"position":[[23,4]]},"141":{"position":[[321,6]]},"145":{"position":[[20,4]]},"152":{"position":[[777,4]]},"156":{"position":[[111,7]]},"157":{"position":[[217,4],[544,4],[709,5]]},"159":{"position":[[226,4],[1209,4]]},"160":{"position":[[1561,4],[3169,5]]},"163":{"position":[[300,4]]},"164":{"position":[[958,4]]},"166":{"position":[[680,4]]},"170":{"position":[[182,6],[426,4]]},"175":{"position":[[995,6],[1275,6]]},"178":{"position":[[489,4]]},"180":{"position":[[611,5]]},"183":{"position":[[808,5]]},"190":{"position":[[193,4],[433,5]]},"193":{"position":[[408,6],[1151,6]]},"194":{"position":[[681,4]]},"196":{"position":[[885,6],[1320,5]]},"199":{"position":[[672,4],[954,4],[1327,4]]}},"keywords":{}}],["needless",{"_index":4755,"title":{},"content":{"161":{"position":[[1365,8]]}},"keywords":{}}],["neg",{"_index":334,"title":{},"content":{"6":{"position":[[479,8]]},"19":{"position":[[215,8]]},"76":{"position":[[1619,9]]}},"keywords":{}}],["nervous",{"_index":4156,"title":{},"content":{"125":{"position":[[8178,11]]}},"keywords":{}}],["nest",{"_index":3907,"title":{},"content":{"121":{"position":[[1655,6]]},"165":{"position":[[557,6]]}},"keywords":{}}],["netflix",{"_index":1804,"title":{},"content":{"40":{"position":[[1027,7],[1115,8],[2449,8]]}},"keywords":{}}],["network",{"_index":4992,"title":{"175":{"position":[[0,9]]}},"content":{"174":{"position":[[989,7]]},"175":{"position":[[571,7],[731,10],[1666,7]]}},"keywords":{}}],["never",{"_index":41,"title":{},"content":{"1":{"position":[[487,5]]},"45":{"position":[[1745,5]]},"55":{"position":[[158,5]]},"76":{"position":[[1646,5]]},"97":{"position":[[247,5]]},"98":{"position":[[935,5]]},"127":{"position":[[445,5]]},"132":{"position":[[807,5]]},"153":{"position":[[891,5]]},"158":{"position":[[169,5]]},"160":{"position":[[1555,5],[1617,5]]},"161":{"position":[[1283,5]]},"176":{"position":[[420,5]]},"178":{"position":[[204,5]]},"179":{"position":[[1441,5]]},"180":{"position":[[605,5]]},"181":{"position":[[534,5]]},"183":{"position":[[873,5]]},"185":{"position":[[445,5]]},"193":{"position":[[2026,5]]},"197":{"position":[[1300,5]]},"199":{"position":[[1040,5]]}},"keywords":{}}],["new",{"_index":21,"title":{"100":{"position":[[10,3]]}},"content":{"1":{"position":[[222,3]]},"2":{"position":[[712,3]]},"3":{"position":[[241,3],[315,3],[750,3]]},"4":{"position":[[488,3],[1413,3]]},"30":{"position":[[7251,3]]},"51":{"position":[[2709,4]]},"53":{"position":[[853,3]]},"75":{"position":[[395,3],[525,3],[742,3],[802,3],[880,3],[1003,3]]},"76":{"position":[[2796,3],[3150,3]]},"93":{"position":[[3262,4]]},"96":{"position":[[2090,3]]},"97":{"position":[[354,3],[1790,3],[3436,3]]},"98":{"position":[[348,3]]},"100":{"position":[[429,3]]},"115":{"position":[[488,3]]},"116":{"position":[[694,3]]},"117":{"position":[[22,3],[1975,3]]},"121":{"position":[[643,3],[2269,3]]},"122":{"position":[[27,4]]},"125":{"position":[[1775,3]]},"156":{"position":[[468,3]]},"164":{"position":[[286,3],[478,3],[1045,3]]},"165":{"position":[[13,3]]},"183":{"position":[[719,3]]},"184":{"position":[[559,5]]},"198":{"position":[[900,3]]}},"keywords":{}}],["new_d1",{"_index":2708,"title":{},"content":{"76":{"position":[[1466,6],[1779,7],[2594,7],[2659,7],[2735,6],[2889,6],[3198,6]]}},"keywords":{}}],["new_d1[d1_index1",{"_index":2712,"title":{},"content":{"76":{"position":[[1660,17]]}},"keywords":{}}],["new_d1[d1_index2",{"_index":2713,"title":{},"content":{"76":{"position":[[1688,17]]}},"keywords":{}}],["new_d2",{"_index":2710,"title":{},"content":{"76":{"position":[[1507,6],[1787,6],[2602,6],[2667,7],[2751,6],[2905,6],[3214,6]]}},"keywords":{}}],["new_d2[d2_index1",{"_index":2714,"title":{},"content":{"76":{"position":[[1716,17]]}},"keywords":{}}],["new_d2[d2_index2",{"_index":2715,"title":{},"content":{"76":{"position":[[1744,17]]}},"keywords":{}}],["new_scor",{"_index":2738,"title":{},"content":{"76":{"position":[[2635,9],[2678,9],[2716,9],[2761,9],[2870,9],[3179,9]]}},"keywords":{}}],["newbi",{"_index":3395,"title":{},"content":{"97":{"position":[[2568,6]]}},"keywords":{}}],["newer",{"_index":4023,"title":{},"content":{"125":{"position":[[669,5]]}},"keywords":{}}],["newparser::default",{"_index":4396,"title":{},"content":{"136":{"position":[[588,18]]}},"keywords":{}}],["next",{"_index":109,"title":{"25":{"position":[[4,4]]},"41":{"position":[[26,4]]}},"content":{"2":{"position":[[490,4]]},"35":{"position":[[271,4]]},"41":{"position":[[408,4]]},"51":{"position":[[697,5],[795,4]]},"61":{"position":[[65,5]]},"66":{"position":[[881,4]]},"75":{"position":[[777,4],[1086,4]]},"91":{"position":[[5157,4]]},"93":{"position":[[1171,4]]},"103":{"position":[[705,5]]},"113":{"position":[[2505,4]]},"116":{"position":[[168,4]]},"175":{"position":[[1234,4],[1463,4]]},"180":{"position":[[5,4]]},"184":{"position":[[1,5]]},"185":{"position":[[25,4]]},"192":{"position":[[348,4],[495,4]]}},"keywords":{}}],["next.j",{"_index":189,"title":{},"content":{"3":{"position":[[1087,7]]},"4":{"position":[[1148,7]]}},"keywords":{}}],["nice",{"_index":1846,"title":{},"content":{"40":{"position":[[3726,4]]},"70":{"position":[[1362,6]]},"96":{"position":[[1575,5]]},"97":{"position":[[4198,4]]},"106":{"position":[[452,4]]},"116":{"position":[[2751,4]]},"120":{"position":[[647,4]]},"121":{"position":[[844,4],[1122,4]]},"124":{"position":[[745,4]]},"125":{"position":[[775,4]]},"150":{"position":[[631,6]]},"165":{"position":[[375,5]]}},"keywords":{}}],["nicer",{"_index":4013,"title":{},"content":{"125":{"position":[[405,5]]}},"keywords":{}}],["nick",{"_index":2251,"title":{},"content":{"53":{"position":[[1163,4],[2106,4]]}},"keywords":{}}],["nigh",{"_index":4835,"title":{},"content":{"165":{"position":[[1361,4]]}},"keywords":{}}],["night",{"_index":2204,"title":{},"content":{"53":{"position":[[326,5]]},"125":{"position":[[145,6]]}},"keywords":{}}],["night,"",{"_index":3981,"title":{},"content":{"123":{"position":[[701,12]]}},"keywords":{}}],["nighter",{"_index":2179,"title":{},"content":{"52":{"position":[[471,7]]}},"keywords":{}}],["nightli",{"_index":4113,"title":{},"content":{"125":{"position":[[5210,8],[5758,8]]}},"keywords":{}}],["nightly.becaus",{"_index":4714,"title":{},"content":{"160":{"position":[[3934,15]]}},"keywords":{}}],["nltk",{"_index":2067,"title":{},"content":{"51":{"position":[[19,4]]}},"keywords":{}}],["nltk.token",{"_index":2080,"title":{},"content":{"51":{"position":[[418,13]]}},"keywords":{}}],["nnn",{"_index":1538,"title":{},"content":{"32":{"position":[[1225,4]]},"75":{"position":[[1163,3]]}},"keywords":{}}],["no_alloc",{"_index":4450,"title":{},"content":{"144":{"position":[[162,11]]},"147":{"position":[[177,11]]}},"keywords":{}}],["nobodi",{"_index":3488,"title":{},"content":{"101":{"position":[[1069,6]]},"130":{"position":[[409,6]]}},"keywords":{}}],["nobody'",{"_index":3973,"title":{},"content":{"123":{"position":[[241,8]]},"124":{"position":[[611,8]]}},"keywords":{}}],["node",{"_index":4970,"title":{},"content":{"173":{"position":[[2082,6],[2157,5]]},"175":{"position":[[1307,5],[1468,5]]}},"keywords":{}}],["nogil",{"_index":5157,"title":{},"content":{"188":{"position":[[626,5],[865,7],[925,6],[1016,6],[1244,6],[3555,6],[3590,6],[4083,5],[4130,5],[4386,5],[4484,5]]},"189":{"position":[[702,5]]}},"keywords":{}}],["nogil=fals",{"_index":5234,"title":{},"content":{"189":{"position":[[867,11],[1303,13]]}},"keywords":{}}],["nogil=tru",{"_index":5231,"title":{},"content":{"189":{"position":[[612,10],[1065,11],[3057,11]]}},"keywords":{}}],["nogilcontext",{"_index":5154,"title":{},"content":{"188":{"position":[[517,12]]}},"keywords":{}}],["nogilfunct",{"_index":5151,"title":{},"content":{"188":{"position":[[348,13]]}},"keywords":{}}],["nois",{"_index":3561,"title":{},"content":{"104":{"position":[[792,5],[1835,5]]}},"keywords":{}}],["noisi",{"_index":3562,"title":{},"content":{"104":{"position":[[919,5]]}},"keywords":{}}],["nom",{"_index":4761,"title":{"163":{"position":[[30,4]]}},"content":{"163":{"position":[[446,4],[624,4],[1652,3],[2273,3]]}},"keywords":{}}],["nomin",{"_index":352,"title":{},"content":{"6":{"position":[[777,7]]},"9":{"position":[[683,7]]},"13":{"position":[[587,7],[820,8],[1007,7],[1909,8]]},"14":{"position":[[1417,7],[1677,8],[2025,7]]},"15":{"position":[[786,7],[1067,8],[1693,7]]}},"keywords":{}}],["nominal*(1",{"_index":577,"title":{},"content":{"13":{"position":[[1070,10]]},"14":{"position":[[2104,10]]},"15":{"position":[[1772,10]]}},"keywords":{}}],["non",{"_index":2825,"title":{},"content":{"86":{"position":[[107,3],[182,3],[560,3]]},"97":{"position":[[1050,3],[2813,3]]},"112":{"position":[[1371,3]]},"113":{"position":[[1159,3]]},"146":{"position":[[213,3]]},"163":{"position":[[553,3]]},"172":{"position":[[2314,3]]},"173":{"position":[[538,3]]},"181":{"position":[[794,3]]},"185":{"position":[[585,3]]},"190":{"position":[[198,3]]},"196":{"position":[[220,3]]}},"keywords":{}}],["none",{"_index":834,"title":{},"content":{"20":{"position":[[1956,7],[1964,7]]},"30":{"position":[[8863,5],[9946,4]]},"51":{"position":[[1236,4]]},"62":{"position":[[904,4]]},"88":{"position":[[1065,5]]},"93":{"position":[[1529,4],[2751,5]]},"123":{"position":[[1110,4]]},"136":{"position":[[409,5],[415,5],[435,5]]}},"keywords":{}}],["nonetheless",{"_index":3492,"title":{},"content":{"102":{"position":[[443,12]]}},"keywords":{}}],["nonsens",{"_index":2280,"title":{},"content":{"53":{"position":[[1659,11]]}},"keywords":{}}],["noon",{"_index":1475,"title":{},"content":{"30":{"position":[[9142,5]]}},"keywords":{}}],["nop",{"_index":4267,"title":{},"content":{"128":{"position":[[893,3]]}},"keywords":{}}],["nopython",{"_index":5230,"title":{},"content":{"189":{"position":[[522,8],[793,8],[1223,10]]}},"keywords":{}}],["nopython=tru",{"_index":5229,"title":{},"content":{"189":{"position":[[445,13]]}},"keywords":{}}],["nopythonar",{"_index":5233,"title":{},"content":{"189":{"position":[[712,11]]}},"keywords":{}}],["norm_factor",{"_index":2980,"title":{},"content":{"90":{"position":[[928,11],[1034,11],[2313,11],[2419,11]]}},"keywords":{}}],["normal",{"_index":4553,"title":{},"content":{"153":{"position":[[762,8]]},"161":{"position":[[957,8]]},"173":{"position":[[345,8]]},"196":{"position":[[311,9]]}},"keywords":{}}],["north",{"_index":1196,"title":{},"content":{"28":{"position":[[54,5]]},"30":{"position":[[78,5],[347,5],[523,5],[1011,5],[7801,5],[8035,5]]}},"keywords":{}}],["notabl",{"_index":1832,"title":{},"content":{"40":{"position":[[3149,7]]}},"keywords":{}}],["notat",{"_index":5119,"title":{},"content":{"184":{"position":[[120,9]]}},"keywords":{}}],["notcopy",{"_index":5369,"title":{},"content":{"198":{"position":[[1130,11]]}},"keywords":{}}],["note",{"_index":333,"title":{"36":{"position":[[5,4]]}},"content":{"6":{"position":[[453,5]]},"13":{"position":[[90,5],[1867,5],[2269,5]]},"14":{"position":[[752,4],[1089,4],[2966,5],[3357,5]]},"15":{"position":[[289,4],[2637,5],[3025,5]]},"30":{"position":[[8202,4]]},"33":{"position":[[19,4]]},"40":{"position":[[1212,4]]},"43":{"position":[[1107,5]]},"45":{"position":[[3301,4]]},"68":{"position":[[834,5]]},"74":{"position":[[347,4]]},"91":{"position":[[2563,5]]},"92":{"position":[[375,5],[1339,6]]},"97":{"position":[[342,5],[595,5]]},"113":{"position":[[290,4]]},"115":{"position":[[2489,5]]},"121":{"position":[[1070,5]]},"123":{"position":[[953,4]]},"125":{"position":[[2510,4]]},"155":{"position":[[20,4]]},"186":{"position":[[349,4]]},"188":{"position":[[2916,4]]},"189":{"position":[[692,4]]},"192":{"position":[[585,4]]},"193":{"position":[[2247,4]]},"195":{"position":[[960,4]]},"196":{"position":[[987,4]]},"197":{"position":[[1169,4]]},"198":{"position":[[700,4]]}},"keywords":{}}],["notebook",{"_index":1864,"title":{},"content":{"43":{"position":[[395,8]]}},"keywords":{}}],["noth",{"_index":637,"title":{},"content":{"14":{"position":[[1017,8]]},"30":{"position":[[7902,7]]},"45":{"position":[[3271,8]]},"53":{"position":[[569,7]]},"93":{"position":[[549,7]]},"109":{"position":[[82,7]]},"123":{"position":[[442,7]]},"127":{"position":[[1053,7]]},"128":{"position":[[997,7]]},"143":{"position":[[201,7]]},"199":{"position":[[451,7]]}},"keywords":{}}],["notic",{"_index":1436,"title":{},"content":{"30":{"position":[[7720,8]]},"68":{"position":[[848,6]]},"103":{"position":[[2314,6]]},"104":{"position":[[1926,9]]},"153":{"position":[[877,7]]},"160":{"position":[[4434,6]]}},"keywords":{}}],["notifi",{"_index":4966,"title":{},"content":{"173":{"position":[[1676,6]]}},"keywords":{}}],["notion",{"_index":603,"title":{},"content":{"13":{"position":[[1881,9],[2283,9]]}},"keywords":{}}],["notstr",{"_index":4595,"title":{},"content":{"156":{"position":[[387,9]]}},"keywords":{}}],["novemb",{"_index":1265,"title":{},"content":{"28":{"position":[[1953,12],[2589,9],[4236,8]]},"30":{"position":[[1042,9],[1450,11],[7120,8],[7487,8]]}},"keywords":{}}],["now",{"_index":73,"title":{"40":{"position":[[4,3]]}},"content":{"2":{"position":[[1,3]]},"3":{"position":[[1,3]]},"8":{"position":[[125,4]]},"9":{"position":[[1,3]]},"10":{"position":[[1,3]]},"11":{"position":[[1,3]]},"12":{"position":[[7,3]]},"13":{"position":[[1,3]]},"23":{"position":[[1,3]]},"28":{"position":[[552,3],[2808,3]]},"30":{"position":[[2708,3]]},"32":{"position":[[409,3]]},"34":{"position":[[4,3],[698,3],[982,4],[3011,4],[3601,3]]},"38":{"position":[[767,3]]},"40":{"position":[[1370,5]]},"43":{"position":[[973,3],[1027,4]]},"44":{"position":[[1207,3],[1264,4],[1963,4]]},"45":{"position":[[361,4],[1522,3]]},"51":{"position":[[302,3],[1450,3],[2160,3],[2725,3],[3493,3]]},"52":{"position":[[6,3]]},"53":{"position":[[5,3],[353,3]]},"61":{"position":[[877,3],[1833,4]]},"62":{"position":[[1,3],[1681,3]]},"64":{"position":[[325,3],[1169,4]]},"65":{"position":[[1,3],[730,4]]},"66":{"position":[[393,4]]},"74":{"position":[[961,4]]},"76":{"position":[[510,3],[1796,3],[3363,3]]},"79":{"position":[[12,3]]},"80":{"position":[[17,3]]},"81":{"position":[[7,3]]},"82":{"position":[[84,3]]},"88":{"position":[[89,3]]},"89":{"position":[[986,3]]},"92":{"position":[[7,3]]},"97":{"position":[[618,3],[4154,4],[5152,4],[6218,3]]},"98":{"position":[[34,3]]},"100":{"position":[[276,3]]},"103":{"position":[[1501,3]]},"109":{"position":[[590,3]]},"110":{"position":[[373,4],[521,3]]},"111":{"position":[[1,3],[933,4]]},"112":{"position":[[945,4],[1638,3]]},"113":{"position":[[85,4],[1284,3],[1513,3],[2272,3],[2431,3]]},"116":{"position":[[596,3]]},"117":{"position":[[1443,3],[1561,3],[2064,3]]},"118":{"position":[[100,4]]},"120":{"position":[[1116,3]]},"122":{"position":[[1,4]]},"124":{"position":[[12,3]]},"125":{"position":[[1278,3],[10847,4]]},"127":{"position":[[86,4]]},"129":{"position":[[1,3],[737,4]]},"130":{"position":[[508,3]]},"135":{"position":[[531,3]]},"136":{"position":[[843,3]]},"160":{"position":[[3333,3]]},"161":{"position":[[941,4]]},"164":{"position":[[1,3]]},"193":{"position":[[1695,3]]}},"keywords":{}}],["nowher",{"_index":1883,"title":{},"content":{"43":{"position":[[932,7]]}},"keywords":{}}],["np",{"_index":802,"title":{},"content":{"20":{"position":[[1018,2]]},"30":{"position":[[233,2]]},"39":{"position":[[430,2]]},"43":{"position":[[303,2]]},"51":{"position":[[3603,2]]},"68":{"position":[[418,2]]},"76":{"position":[[143,2]]},"90":{"position":[[192,2]]},"103":{"position":[[870,2]]}},"keywords":{}}],["np.append(invest",{"_index":1736,"title":{},"content":{"39":{"position":[[1417,19]]}},"keywords":{}}],["np.arange(1",{"_index":2002,"title":{},"content":{"45":{"position":[[2183,12],[2963,12]]}},"keywords":{}}],["np.arange(2",{"_index":2761,"title":{},"content":{"78":{"position":[[431,12]]}},"keywords":{}}],["np.array([init",{"_index":1730,"title":{},"content":{"39":{"position":[[1064,16]]}},"keywords":{}}],["np.array(event_data",{"_index":3040,"title":{},"content":{"90":{"position":[[3967,20]]}},"keywords":{}}],["np.array(list(map(lambda",{"_index":813,"title":{},"content":{"20":{"position":[[1222,24],[1291,24],[1383,24]]}},"keywords":{}}],["np.count_nonzero(cloudy_day",{"_index":1384,"title":{},"content":{"30":{"position":[[3323,30]]}},"keywords":{}}],["np.count_nonzero(precip_day",{"_index":1422,"title":{},"content":{"30":{"position":[[6391,30]]}},"keywords":{}}],["np.exp(new_scor",{"_index":2741,"title":{},"content":{"76":{"position":[[3032,16]]}},"keywords":{}}],["np.float64(first_word_dist.valu",{"_index":2160,"title":{},"content":{"51":{"position":[[3973,34]]}},"keywords":{}}],["np.float64(np.copy(d1_dens",{"_index":2709,"title":{},"content":{"76":{"position":[[1475,31]]}},"keywords":{}}],["np.float64(np.copy(d2_dens",{"_index":2711,"title":{},"content":{"76":{"position":[[1516,31]]}},"keywords":{}}],["np.hstack((0",{"_index":2691,"title":{},"content":{"76":{"position":[[766,13]]}},"keywords":{}}],["np.hstack([0",{"_index":2990,"title":{},"content":{"90":{"position":[[1192,13],[2577,13]]}},"keywords":{}}],["np.lib.pad(sign",{"_index":3527,"title":{},"content":{"103":{"position":[[1081,18]]}},"keywords":{}}],["np.log(coefs[x]).sum",{"_index":2692,"title":{},"content":{"76":{"position":[[798,22]]}},"keywords":{}}],["np.mean(i",{"_index":1941,"title":{},"content":{"44":{"position":[[1470,9]]}},"keywords":{}}],["np.mean(matches_dict[index][futur",{"_index":1086,"title":{},"content":{"24":{"position":[[2245,36]]},"25":{"position":[[1969,36]]}},"keywords":{}}],["np.mean(x_bin[:,i",{"_index":1915,"title":{},"content":{"44":{"position":[[642,19]]}},"keywords":{}}],["np.mod(sampl",{"_index":3526,"title":{},"content":{"103":{"position":[[1044,15]]}},"keywords":{}}],["np.nan",{"_index":950,"title":{},"content":{"22":{"position":[[1718,6]]},"28":{"position":[[1189,6],[1518,7],[2993,6],[3309,7]]},"30":{"position":[[1561,6],[1879,7],[3228,7],[4838,6],[5143,7],[6297,7]]}},"keywords":{}}],["np.nanmean(cloud_cover_v",{"_index":1254,"title":{},"content":{"28":{"position":[[1708,29]]},"30":{"position":[[1914,29]]}},"keywords":{}}],["np.nanmean(precip_v",{"_index":1302,"title":{},"content":{"28":{"position":[[3494,24]]},"30":{"position":[[5173,24]]}},"keywords":{}}],["np.ones(len(dist",{"_index":2166,"title":{},"content":{"51":{"position":[[4162,18]]}},"keywords":{}}],["np.random.multinomial(1",{"_index":2594,"title":{},"content":{"70":{"position":[[965,24]]}},"keywords":{}}],["np.random.multinomial(n",{"_index":2152,"title":{},"content":{"51":{"position":[[3654,24]]}},"keywords":{}}],["np.random.poisson(hashtag_freq",{"_index":2155,"title":{},"content":{"51":{"position":[[3796,31]]}},"keywords":{}}],["np.random.rand",{"_index":2743,"title":{},"content":{"76":{"position":[[3074,16]]}},"keywords":{}}],["np.random.randint(0",{"_index":2703,"title":{},"content":{"76":{"position":[[1283,20],[1333,20]]}},"keywords":{}}],["np.random.randint(1",{"_index":2561,"title":{},"content":{"68":{"position":[[501,20],[541,20]]}},"keywords":{}}],["np.repeat(1/6",{"_index":2724,"title":{},"content":{"76":{"position":[[2012,14],[2039,14]]},"81":{"position":[[135,14]]}},"keywords":{}}],["np.repeat(array[:,lookback].reshap",{"_index":2981,"title":{},"content":{"90":{"position":[[942,36],[2327,36]]}},"keywords":{}}],["np.vstack([five_day_ev",{"_index":3149,"title":{},"content":{"91":{"position":[[3675,27]]}},"keywords":{}}],["np.zeros((1",{"_index":3143,"title":{},"content":{"91":{"position":[[3375,12]]}},"keywords":{}}],["np.zeros(len(i",{"_index":1942,"title":{},"content":{"44":{"position":[[1483,17]]}},"keywords":{}}],["np.zeros(len(tick",{"_index":836,"title":{},"content":{"20":{"position":[[1991,22]]}},"keywords":{}}],["ns",{"_index":5174,"title":{},"content":{"188":{"position":[[1605,3],[1703,3],[3127,3]]},"189":{"position":[[2820,3]]}},"keywords":{}}],["nt",{"_index":3224,"title":{},"content":{"93":{"position":[[2379,2]]}},"keywords":{}}],["nuanc",{"_index":4539,"title":{},"content":{"153":{"position":[[175,6]]}},"keywords":{}}],["null",{"_index":4228,"title":{},"content":{"127":{"position":[[454,5]]},"188":{"position":[[3685,4]]}},"keywords":{}}],["num",{"_index":4250,"title":{},"content":{"128":{"position":[[251,4]]}},"keywords":{}}],["num_dealloc",{"_index":4898,"title":{},"content":{"172":{"position":[[233,11]]}},"keywords":{}}],["num_quart",{"_index":2471,"title":{},"content":{"64":{"position":[[930,12],[996,12],[1028,13]]}},"keywords":{}}],["num_simul",{"_index":372,"title":{},"content":{"6":{"position":[[1053,15]]},"13":{"position":[[1714,16]]},"14":{"position":[[2797,16]]},"15":{"position":[[2471,16]]}},"keywords":{}}],["num_tick",{"_index":419,"title":{},"content":{"7":{"position":[[830,9],[876,9],[944,9]]}},"keywords":{}}],["numa",{"_index":4968,"title":{},"content":{"173":{"position":[[1945,5],[1957,4]]}},"keywords":{}}],["numba",{"_index":5225,"title":{"189":{"position":[[0,6]]}},"content":{"189":{"position":[[14,5],[119,5],[421,5],[945,5],[1038,6],[1871,5],[2881,5],[3020,5]]},"190":{"position":[[380,5],[671,5],[905,5]]}},"keywords":{}}],["numba_gil(n",{"_index":5238,"title":{},"content":{"189":{"position":[[1353,12],[1623,13],[1747,12]]}},"keywords":{}}],["numba_nogil(n",{"_index":5236,"title":{},"content":{"189":{"position":[[1081,14],[1608,14]]}},"keywords":{}}],["numba_recurse(2",{"_index":5258,"title":{},"content":{"189":{"position":[[3157,17]]}},"keywords":{}}],["numba_recurse(n",{"_index":5257,"title":{},"content":{"189":{"position":[[3073,16],[3136,15]]}},"keywords":{}}],["number",{"_index":346,"title":{},"content":{"6":{"position":[[659,6],[693,6],[727,6]]},"30":{"position":[[3986,6],[4169,6],[4247,6],[7073,6]]},"32":{"position":[[1117,6]]},"40":{"position":[[2258,6]]},"43":{"position":[[1455,6]]},"45":{"position":[[797,6],[1195,6]]},"49":{"position":[[609,6]]},"51":{"position":[[1931,6],[2902,6]]},"57":{"position":[[35,6],[101,6],[456,6]]},"58":{"position":[[185,6],[483,7],[535,6],[611,6],[675,6],[827,6]]},"64":{"position":[[178,7],[475,6],[618,6],[663,6],[700,6],[740,6],[1313,6]]},"65":{"position":[[577,6],[605,6],[768,6]]},"66":{"position":[[79,6],[421,6]]},"74":{"position":[[1352,7]]},"76":{"position":[[2358,6]]},"91":{"position":[[3778,6]]},"92":{"position":[[154,6]]},"98":{"position":[[450,6],[507,6]]},"102":{"position":[[502,6],[1175,6],[1323,6]]},"103":{"position":[[1937,6]]},"104":{"position":[[877,7],[1446,6]]},"105":{"position":[[52,6],[136,6]]},"188":{"position":[[1537,7]]}},"keywords":{}}],["numer",{"_index":5150,"title":{},"content":{"188":{"position":[[235,9]]}},"keywords":{}}],["numpi",{"_index":801,"title":{},"content":{"20":{"position":[[1009,5]]},"30":{"position":[[224,5]]},"39":{"position":[[421,5]]},"43":{"position":[[294,5]]},"51":{"position":[[3594,5]]},"68":{"position":[[409,5]]},"76":{"position":[[134,5],[151,5]]},"90":{"position":[[183,5]]},"103":{"position":[[861,5]]}},"keywords":{}}],["ny",{"_index":1203,"title":{},"content":{"28":{"position":[[203,2],[416,2]]}},"keywords":{}}],["nyc",{"_index":1232,"title":{},"content":{"28":{"position":[[1013,6]]},"30":{"position":[[8641,6],[10273,3]]}},"keywords":{}}],["nyc_loc",{"_index":1453,"title":{},"content":{"30":{"position":[[8503,7],[8648,8]]}},"keywords":{}}],["nycari",{"_index":1209,"title":{},"content":{"28":{"position":[[380,7]]}},"keywords":{}}],["o",{"_index":4123,"title":{},"content":{"125":{"position":[[5581,1],[6042,1]]}},"keywords":{}}],["o_n",{"_index":1553,"title":{},"content":{"32":{"position":[[1861,4]]}},"keywords":{}}],["o_n}{o_n",{"_index":1549,"title":{},"content":{"32":{"position":[[1765,10]]}},"keywords":{}}],["oauth",{"_index":2343,"title":{"61":{"position":[[9,5]]}},"content":{"59":{"position":[[144,6]]},"60":{"position":[[153,5]]},"61":{"position":[[35,5],[92,5]]}},"keywords":{}}],["oauth2sess",{"_index":2402,"title":{},"content":{"62":{"position":[[394,13]]}},"keywords":{}}],["oauth2session(token",{"_index":2404,"title":{},"content":{"62":{"position":[[468,21]]}},"keywords":{}}],["object",{"_index":833,"title":{"49":{"position":[[4,10]]}},"content":{"20":{"position":[[1874,9]]},"29":{"position":[[208,11]]},"34":{"position":[[590,10]]},"90":{"position":[[514,6]]},"98":{"position":[[708,6]]},"110":{"position":[[546,6]]},"117":{"position":[[144,6],[161,6],[332,7],[882,6],[1718,6]]},"125":{"position":[[4243,7]]},"127":{"position":[[1428,8]]},"152":{"position":[[75,6]]},"155":{"position":[[409,7],[652,8]]},"156":{"position":[[298,7],[426,7]]},"157":{"position":[[133,7]]},"159":{"position":[[263,6]]},"160":{"position":[[1141,7],[1209,6]]},"164":{"position":[[339,7]]},"172":{"position":[[130,7],[1550,6]]},"190":{"position":[[306,7]]},"192":{"position":[[61,8]]},"196":{"position":[[132,7]]},"197":{"position":[[116,8],[191,7],[275,7],[1523,7]]},"198":{"position":[[389,7]]},"199":{"position":[[508,6],[655,7],[781,7],[854,7]]}},"keywords":{}}],["objectand",{"_index":4236,"title":{},"content":{"127":{"position":[[844,9]]}},"keywords":{}}],["observ",{"_index":548,"title":{},"content":{"13":{"position":[[289,11],[444,12]]},"14":{"position":[[497,12]]},"15":{"position":[[192,11]]},"68":{"position":[[745,8]]}},"keywords":{}}],["observationacceler",{"_index":545,"title":{},"content":{"13":{"position":[[207,22]]}},"keywords":{}}],["observationcoupon",{"_index":631,"title":{},"content":{"14":{"position":[[362,17]]}},"keywords":{}}],["observationprincipl",{"_index":632,"title":{},"content":{"14":{"position":[[432,20]]}},"keywords":{}}],["obsess",{"_index":234,"title":{},"content":{"4":{"position":[[238,8]]}},"keywords":{}}],["obsolet",{"_index":4060,"title":{},"content":{"125":{"position":[[2221,8]]}},"keywords":{}}],["obviou",{"_index":2556,"title":{},"content":{"68":{"position":[[92,7]]},"98":{"position":[[469,7]]},"172":{"position":[[1008,8]]}},"keywords":{}}],["obvious",{"_index":4246,"title":{},"content":{"127":{"position":[[1522,9]]}},"keywords":{}}],["occas",{"_index":3933,"title":{},"content":{"122":{"position":[[116,8]]}},"keywords":{}}],["occur",{"_index":2616,"title":{},"content":{"72":{"position":[[278,5]]},"136":{"position":[[138,8]]},"143":{"position":[[82,6]]},"156":{"position":[[1139,5]]},"161":{"position":[[204,8]]},"193":{"position":[[2431,6]]},"195":{"position":[[934,8]]},"198":{"position":[[927,5]]}},"keywords":{}}],["occurr",{"_index":2151,"title":{},"content":{"51":{"position":[[3640,11],[3696,11]]}},"keywords":{}}],["ocd",{"_index":1843,"title":{},"content":{"40":{"position":[[3658,3]]}},"keywords":{}}],["octob",{"_index":1263,"title":{},"content":{"28":{"position":[[1936,11],[2577,7],[4223,8]]},"30":{"position":[[1439,10]]},"40":{"position":[[3192,8]]}},"keywords":{}}],["of"resourc",{"_index":4559,"title":{},"content":{"155":{"position":[[312,16]]}},"keywords":{}}],["offer",{"_index":3411,"title":{},"content":{"97":{"position":[[4215,6]]}},"keywords":{}}],["offici",{"_index":4822,"title":{},"content":{"165":{"position":[[72,8]]}},"keywords":{}}],["offset",{"_index":5276,"title":{},"content":{"193":{"position":[[463,7]]}},"keywords":{}}],["offsetsto",{"_index":4842,"title":{},"content":{"166":{"position":[[366,9]]}},"keywords":{}}],["ofperform",{"_index":4665,"title":{},"content":{"160":{"position":[[864,14]]}},"keywords":{}}],["ogg",{"_index":3477,"title":{},"content":{"101":{"position":[[582,4]]}},"keywords":{}}],["oh",{"_index":4045,"title":{},"content":{"125":{"position":[[1334,2]]}},"keywords":{}}],["ohlc_dataframe(aapl",{"_index":2877,"title":{},"content":{"88":{"position":[[1489,20],[2779,20]]}},"keywords":{}}],["ohlc_dataframe(aapl[datetime(2016",{"_index":3089,"title":{},"content":{"91":{"position":[[930,34]]}},"keywords":{}}],["ohlc_dataframe(data",{"_index":2860,"title":{},"content":{"88":{"position":[[925,20]]}},"keywords":{}}],["ohlc_dataframe(fb",{"_index":2891,"title":{},"content":{"88":{"position":[[1818,18],[3182,18]]}},"keywords":{}}],["ohlc_dataframe(fb[datetime(2016",{"_index":3077,"title":{},"content":{"91":{"position":[[482,32]]}},"keywords":{}}],["oio_ioi",{"_index":1521,"title":{},"content":{"32":{"position":[[475,8]]}},"keywords":{}}],["oj",{"_index":2249,"title":{},"content":{"53":{"position":[[1146,2],[2090,3]]}},"keywords":{}}],["ok",{"_index":2354,"title":{},"content":{"61":{"position":[[328,3],[461,3],[664,3]]},"96":{"position":[[1333,3]]},"97":{"position":[[239,2]]},"103":{"position":[[1850,3]]},"120":{"position":[[1,3]]},"121":{"position":[[901,2],[1458,2]]},"160":{"position":[[1811,3]]}},"keywords":{}}],["ok((remain",{"_index":4795,"title":{},"content":{"163":{"position":[[2101,14]]}},"keywords":{}}],["ok((res.0",{"_index":4393,"title":{},"content":{"136":{"position":[[473,10]]}},"keywords":{}}],["ok(12).and_then(|",{"_index":4477,"title":{},"content":{"147":{"position":[[265,19]]}},"keywords":{}}],["ok(response::with((status::ok",{"_index":3331,"title":{},"content":{"96":{"position":[[726,30],[1145,30],[1675,30],[2221,30]]},"97":{"position":[[1585,30],[3712,30],[5060,30],[6056,30]]}},"keywords":{}}],["ok(vec::with_capacity(",{"_index":4478,"title":{},"content":{"147":{"position":[[285,26]]}},"keywords":{}}],["okay",{"_index":1878,"title":{},"content":{"43":{"position":[[674,5]]},"118":{"position":[[313,5]]}},"keywords":{}}],["ol",{"_index":4039,"title":{},"content":{"125":{"position":[[1263,3]]}},"keywords":{}}],["old",{"_index":2739,"title":{},"content":{"76":{"position":[[2822,3]]},"88":{"position":[[234,3]]},"161":{"position":[[343,3]]}},"keywords":{}}],["older",{"_index":4024,"title":{},"content":{"125":{"position":[[703,5]]}},"keywords":{}}],["oldschool",{"_index":2181,"title":{},"content":{"52":{"position":[[490,11]]}},"keywords":{}}],["omega",{"_index":780,"title":{},"content":{"20":{"position":[[606,8],[637,6],[664,6],[701,6]]}},"keywords":{}}],["on",{"_index":20,"title":{},"content":{"1":{"position":[[210,3]]},"7":{"position":[[1040,3]]},"20":{"position":[[6,3]]},"22":{"position":[[50,3],[96,3]]},"30":{"position":[[2768,3]]},"38":{"position":[[383,3]]},"39":{"position":[[1922,4]]},"45":{"position":[[907,4],[2567,4],[2743,3]]},"49":{"position":[[512,4]]},"51":{"position":[[841,3],[3260,4]]},"53":{"position":[[989,3],[1713,5]]},"61":{"position":[[1603,3]]},"62":{"position":[[251,3]]},"66":{"position":[[834,4]]},"70":{"position":[[19,3],[46,3]]},"71":{"position":[[6,3],[33,3]]},"73":{"position":[[794,3]]},"76":{"position":[[950,3],[1072,3],[1125,3],[2826,4]]},"80":{"position":[[25,3],[61,3]]},"89":{"position":[[90,3]]},"90":{"position":[[5039,3]]},"91":{"position":[[2922,3]]},"92":{"position":[[734,3]]},"96":{"position":[[1596,4]]},"97":{"position":[[2074,4],[2903,3],[5271,3]]},"102":{"position":[[670,5]]},"111":{"position":[[925,3]]},"118":{"position":[[324,4]]},"122":{"position":[[112,3]]},"125":{"position":[[4268,4]]},"135":{"position":[[582,3]]},"139":{"position":[[73,4]]},"155":{"position":[[750,3]]},"160":{"position":[[2050,3]]},"166":{"position":[[44,3]]},"174":{"position":[[891,3],[1024,3]]},"180":{"position":[[568,3]]},"188":{"position":[[1952,3]]},"197":{"position":[[741,3],[848,3]]}},"keywords":{}}],["onc",{"_index":1511,"title":{},"content":{"32":{"position":[[37,4]]},"34":{"position":[[1841,4],[3263,4]]},"57":{"position":[[78,4]]},"91":{"position":[[4556,4]]},"125":{"position":[[5697,4]]},"129":{"position":[[401,4]]},"155":{"position":[[1047,4]]},"164":{"position":[[247,4]]},"176":{"position":[[1597,4]]},"179":{"position":[[1217,5],[1261,4],[1308,6],[1411,6]]},"186":{"position":[[314,4]]},"189":{"position":[[1502,4]]},"193":{"position":[[73,4],[565,4]]},"199":{"position":[[711,4]]}},"keywords":{}}],["once::new",{"_index":5080,"title":{},"content":{"179":{"position":[[1268,12]]},"186":{"position":[[321,12]]}},"keywords":{}}],["ones(5",{"_index":445,"title":{},"content":{"8":{"position":[[89,7]]},"11":{"position":[[350,7]]}},"keywords":{}}],["ones(m",{"_index":530,"title":{},"content":{"12":{"position":[[351,7]]}},"keywords":{}}],["ones(n)*i",{"_index":435,"title":{},"content":{"7":{"position":[[1194,10]]}},"keywords":{}}],["onev",{"_index":51,"title":{},"content":{"1":{"position":[[581,7]]}},"keywords":{}}],["onlin",{"_index":39,"title":{},"content":{"1":{"position":[[447,6]]},"4":{"position":[[450,6],[520,6]]},"96":{"position":[[644,7]]},"97":{"position":[[2933,7]]}},"keywords":{}}],["onward",{"_index":3354,"title":{},"content":{"96":{"position":[[2339,8]]},"124":{"position":[[856,8]]},"148":{"position":[[267,7]]}},"keywords":{}}],["oookay",{"_index":3389,"title":{},"content":{"97":{"position":[[2057,10]]}},"keywords":{}}],["opaqu",{"_index":4509,"title":{},"content":{"152":{"position":[[270,7]]}},"keywords":{}}],["open",{"_index":1018,"title":{},"content":{"24":{"position":[[115,7],[259,7],[416,5],[1059,7]]},"25":{"position":[[779,7]]},"26":{"position":[[127,9],[495,4]]},"32":{"position":[[509,7]]},"33":{"position":[[185,7],[657,7]]},"39":{"position":[[1868,4]]},"90":{"position":[[3298,4]]},"91":{"position":[[298,7]]},"93":{"position":[[2126,5]]},"161":{"position":[[170,4]]}},"keywords":{}}],["open('city_forecasts.p",{"_index":1498,"title":{},"content":{"30":{"position":[[10096,24]]}},"keywords":{}}],["open('earnings_dates.yaml",{"_index":3107,"title":{},"content":{"91":{"position":[[1934,27]]},"93":{"position":[[3308,27],[4347,27]]}},"keywords":{}}],["open_histori",{"_index":1607,"title":{},"content":{"34":{"position":[[1122,13],[1322,13],[1466,13],[1513,13]]},"39":{"position":[[653,14],[842,14]]}},"keywords":{}}],["open_history).sum",{"_index":1726,"title":{},"content":{"39":{"position":[[697,19],[955,19]]}},"keywords":{}}],["open_v",{"_index":1035,"title":{},"content":{"24":{"position":[[656,8],[702,9]]},"25":{"position":[[342,8],[436,9],[448,8]]},"34":{"position":[[1700,9]]}},"keywords":{}}],["open_vals[0:day",{"_index":1735,"title":{},"content":{"39":{"position":[[1388,17]]}},"keywords":{}}],["open_vals[0:len(invest",{"_index":1731,"title":{},"content":{"39":{"position":[[1145,27],[1218,27],[1626,27],[1699,27],[1973,28]]}},"keywords":{}}],["open_vals[0:len(invested)]).sum",{"_index":1737,"title":{},"content":{"39":{"position":[[1510,33],[1748,33]]}},"keywords":{}}],["open_vals[1:day",{"_index":1638,"title":{},"content":{"34":{"position":[[2177,17]]}},"keywords":{}}],["open_vals[1:length(invest",{"_index":1632,"title":{},"content":{"34":{"position":[[1928,30],[2004,30],[2294,30],[2404,30],[2480,30],[2540,30]]}},"keywords":{}}],["open_vals[day",{"_index":1733,"title":{},"content":{"39":{"position":[[1285,14],[2056,14]]}},"keywords":{}}],["open_vals[day+1",{"_index":1635,"title":{},"content":{"34":{"position":[[2070,16],[2605,17]]}},"keywords":{}}],["openingfutur",{"_index":1170,"title":{},"content":{"26":{"position":[[207,14]]}},"keywords":{}}],["openingsnasdaq",{"_index":1121,"title":{},"content":{"24":{"position":[[3010,14]]}},"keywords":{}}],["oper",{"_index":3339,"title":{},"content":{"96":{"position":[[1272,9]]},"160":{"position":[[522,9],[1935,9]]},"172":{"position":[[1284,9]]},"173":{"position":[[104,9],[1046,9],[1189,9]]},"176":{"position":[[160,8],[512,10],[584,10]]},"186":{"position":[[77,10]]},"193":{"position":[[966,10]]},"198":{"position":[[953,8]]}},"keywords":{}}],["opinion",{"_index":3349,"title":{},"content":{"96":{"position":[[1941,8]]}},"keywords":{}}],["opportun",{"_index":3931,"title":{},"content":{"122":{"position":[[57,11]]},"163":{"position":[[530,11]]}},"keywords":{}}],["opposit",{"_index":2941,"title":{},"content":{"88":{"position":[[3708,8]]}},"keywords":{}}],["opt",{"_index":4995,"title":{},"content":{"174":{"position":[[1166,3]]},"194":{"position":[[406,3]]}},"keywords":{}}],["optim",{"_index":700,"title":{"17":{"position":[[20,13]]},"136":{"position":[[0,10]]},"151":{"position":[[30,13]]},"153":{"position":[[40,10]]}},"content":{"20":{"position":[[519,12],[2197,7],[2298,12],[2771,13]]},"35":{"position":[[234,8]]},"73":{"position":[[661,8],[731,9]]},"75":{"position":[[23,8],[189,9]]},"76":{"position":[[2218,12]]},"82":{"position":[[1044,12]]},"83":{"position":[[250,12]]},"85":{"position":[[385,8],[463,9]]},"86":{"position":[[118,12],[193,12],[320,13],[993,8],[1208,13]]},"128":{"position":[[1378,9]]},"130":{"position":[[165,9]]},"141":{"position":[[252,8]]},"152":{"position":[[11,12]]},"153":{"position":[[134,13],[385,13],[923,9]]},"160":{"position":[[3037,8]]},"172":{"position":[[1844,8],[2257,13]]},"176":{"position":[[1638,8]]},"178":{"position":[[249,14]]},"188":{"position":[[216,9]]}},"keywords":{}}],["optimal.fun",{"_index":854,"title":{},"content":{"20":{"position":[[2491,11]]}},"keywords":{}}],["optimal.x",{"_index":850,"title":{},"content":{"20":{"position":[[2400,13]]}},"keywords":{}}],["optimize(d1_v",{"_index":2757,"title":{},"content":{"78":{"position":[[290,16]]}},"keywords":{}}],["optimize(data",{"_index":2718,"title":{},"content":{"76":{"position":[[1891,14]]}},"keywords":{}}],["option",{"_index":3430,"title":{},"content":{"97":{"position":[[5839,7],[5967,7]]},"173":{"position":[[647,8]]}},"keywords":{}}],["option<fixedoffset>)>",{"_index":4389,"title":{},"content":{"136":{"position":[[332,30]]}},"keywords":{}}],["option::some(z",{"_index":5317,"title":{},"content":{"194":{"position":[[412,16]]}},"keywords":{}}],["options={'maxit",{"_index":845,"title":{},"content":{"20":{"position":[[2270,19]]}},"keywords":{}}],["oracl",{"_index":1180,"title":{},"content":{"26":{"position":[[766,6]]}},"keywords":{}}],["orang",{"_index":4934,"title":{},"content":{"172":{"position":[[2383,7]]}},"keywords":{}}],["orchrt",{"_index":4953,"title":{},"content":{"173":{"position":[[844,6]]}},"keywords":{}}],["order",{"_index":305,"title":{},"content":{"6":{"position":[[4,5]]},"11":{"position":[[161,5]]},"20":{"position":[[1170,5]]},"24":{"position":[[1041,5]]},"25":{"position":[[761,5]]},"34":{"position":[[86,5],[874,5],[952,5]]},"88":{"position":[[3627,5]]},"104":{"position":[[282,5],[431,5]]},"139":{"position":[[441,6]]},"152":{"position":[[455,10]]},"156":{"position":[[905,10]]},"175":{"position":[[618,5]]},"188":{"position":[[2851,5]]},"189":{"position":[[810,5]]},"196":{"position":[[542,8],[1683,5]]}},"keywords":{}}],["ordering::seqcst",{"_index":4515,"title":{},"content":{"152":{"position":[[556,18],[1085,18]]},"156":{"position":[[997,18],[1190,18]]}},"keywords":{}}],["organ",{"_index":4056,"title":{},"content":{"125":{"position":[[1942,8]]},"150":{"position":[[501,13],[546,14]]}},"keywords":{}}],["orient",{"_index":4919,"title":{},"content":{"172":{"position":[[1373,8]]}},"keywords":{}}],["origin",{"_index":140,"title":{},"content":{"3":{"position":[[140,8]]},"4":{"position":[[292,8]]},"30":{"position":[[331,10]]},"61":{"position":[[1089,8]]},"86":{"position":[[628,10]]},"97":{"position":[[5847,11]]},"98":{"position":[[1252,10]]},"102":{"position":[[556,8],[661,8],[726,8],[825,8],[1287,8],[1393,8]]},"103":{"position":[[1890,10]]},"105":{"position":[[108,9]]},"106":{"position":[[646,8]]},"115":{"position":[[575,8],[613,8],[2967,8]]},"121":{"position":[[436,8],[2020,10]]},"122":{"position":[[502,8]]},"173":{"position":[[2148,8]]},"192":{"position":[[208,8],[293,6],[465,8],[539,7]]},"196":{"position":[[1353,8],[1504,8]]}},"keywords":{}}],["ornot",{"_index":2200,"title":{},"content":{"53":{"position":[[232,6],[421,6]]}},"keywords":{}}],["orresult",{"_index":5309,"title":{},"content":{"194":{"position":[[58,8]]}},"keywords":{}}],["os",{"_index":4651,"title":{},"content":{"160":{"position":[[254,2]]},"173":{"position":[[1797,2]]},"176":{"position":[[417,2]]}},"keywords":{}}],["oscil",{"_index":61,"title":{},"content":{"1":{"position":[[683,10]]}},"keywords":{}}],["osx",{"_index":3993,"title":{},"content":{"124":{"position":[[246,4]]}},"keywords":{}}],["other",{"_index":4921,"title":{},"content":{"172":{"position":[[1578,6]]}},"keywords":{}}],["ourselv",{"_index":2021,"title":{},"content":{"45":{"position":[[2721,10]]},"105":{"position":[[315,9]]}},"keywords":{}}],["out",{"_index":98,"title":{},"content":{"2":{"position":[[364,3]]},"3":{"position":[[1481,3],[1521,3]]},"4":{"position":[[1497,3]]},"7":{"position":[[397,3]]},"12":{"position":[[35,3]]},"22":{"position":[[242,3],[1157,3]]},"26":{"position":[[16,3]]},"28":{"position":[[588,3]]},"30":{"position":[[9,3]]},"32":{"position":[[1387,3]]},"45":{"position":[[304,3],[1571,3],[1795,3],[2592,3]]},"46":{"position":[[459,3]]},"51":{"position":[[376,3],[720,3],[2563,3],[3113,3],[3443,3]]},"52":{"position":[[16,3]]},"53":{"position":[[245,3],[557,3],[2223,3]]},"61":{"position":[[686,4],[1859,3]]},"64":{"position":[[28,3]]},"65":{"position":[[202,4],[1360,3],[1504,3],[1540,3],[2232,3],[2589,4]]},"73":{"position":[[220,3],[490,3]]},"77":{"position":[[199,3]]},"86":{"position":[[885,3]]},"88":{"position":[[2395,4]]},"91":{"position":[[2467,3]]},"92":{"position":[[280,3]]},"93":{"position":[[399,4]]},"95":{"position":[[480,4],[581,4]]},"96":{"position":[[1814,3]]},"97":{"position":[[2123,3],[5004,3],[5126,3],[5201,4],[5893,4],[6182,3],[6483,3]]},"102":{"position":[[20,3]]},"104":{"position":[[911,3]]},"105":{"position":[[3011,3]]},"112":{"position":[[1100,3]]},"120":{"position":[[444,4],[706,3]]},"121":{"position":[[897,3],[1414,4],[2198,3]]},"122":{"position":[[977,3]]},"123":{"position":[[89,3]]},"125":{"position":[[1254,3],[3032,3],[5329,3],[5436,3],[5877,3],[10000,3]]},"128":{"position":[[797,3],[1388,3]]},"129":{"position":[[375,3]]},"135":{"position":[[615,3]]},"141":{"position":[[261,3]]},"143":{"position":[[395,3]]},"146":{"position":[[425,3]]},"147":{"position":[[25,3]]},"148":{"position":[[370,3]]},"150":{"position":[[450,3]]},"152":{"position":[[854,3]]},"153":{"position":[[49,3],[99,3],[933,3]]},"155":{"position":[[1141,3]]},"157":{"position":[[104,3]]},"161":{"position":[[1046,3],[1397,3],[1570,3]]},"164":{"position":[[1112,3]]},"165":{"position":[[67,4]]},"170":{"position":[[29,3]]},"174":{"position":[[517,3],[750,3]]},"179":{"position":[[616,3],[696,3]]},"189":{"position":[[1692,3]]},"192":{"position":[[455,3]]},"193":{"position":[[764,3]]},"196":{"position":[[649,4]]}},"keywords":{}}],["out_dir",{"_index":3734,"title":{},"content":{"113":{"position":[[490,7]]}},"keywords":{}}],["outcom",{"_index":2678,"title":{},"content":{"76":{"position":[[257,7]]}},"keywords":{}}],["outdat",{"_index":248,"title":{},"content":{"4":{"position":[[644,9]]}},"keywords":{}}],["outhashmap::new",{"_index":4603,"title":{},"content":{"156":{"position":[[1835,18]]}},"keywords":{}}],["outhe'",{"_index":3900,"title":{},"content":{"121":{"position":[[1425,7]]}},"keywords":{}}],["outlier",{"_index":3175,"title":{},"content":{"91":{"position":[[5776,9]]}},"keywords":{}}],["outliv",{"_index":3416,"title":{},"content":{"97":{"position":[[4546,7]]},"155":{"position":[[95,7]]}},"keywords":{}}],["outlock_api::rwlock,lock_api::mutex",{"_index":4611,"title":{},"content":{"157":{"position":[[480,36]]}},"keywords":{}}],["outpac",{"_index":4019,"title":{},"content":{"125":{"position":[[564,8]]}},"keywords":{}}],["outperform",{"_index":1805,"title":{},"content":{"40":{"position":[[1048,12]]}},"keywords":{}}],["output",{"_index":1500,"title":{},"content":{"30":{"position":[[10132,7]]},"95":{"position":[[215,6]]},"125":{"position":[[2612,6]]},"128":{"position":[[409,6]]},"176":{"position":[[1244,6]]},"193":{"position":[[2305,7]]}},"keywords":{}}],["output_notebook",{"_index":1324,"title":{},"content":{"30":{"position":[[129,16],[280,17]]}},"keywords":{}}],["outsid",{"_index":2244,"title":{},"content":{"53":{"position":[[1060,7]]},"96":{"position":[[1932,8]]},"125":{"position":[[10436,7]]},"129":{"position":[[1088,7]]}},"keywords":{}}],["outu32,f64",{"_index":4277,"title":{},"content":{"129":{"position":[[248,10]]}},"keywords":{}}],["oven",{"_index":3845,"title":{},"content":{"118":{"position":[[307,5]]},"161":{"position":[[984,4],[1057,5],[1091,5],[1210,5],[1436,4]]}},"keywords":{}}],["over",{"_index":596,"title":{"91":{"position":[[28,4]]}},"content":{"13":{"position":[[1709,4],[2206,4]]},"14":{"position":[[2792,4],[3278,4]]},"15":{"position":[[2466,4],[2949,4]]},"18":{"position":[[53,4]]},"19":{"position":[[23,5],[71,4],[130,4]]},"20":{"position":[[53,4]]},"24":{"position":[[130,4],[274,4]]},"26":{"position":[[659,4]]},"28":{"position":[[80,4],[715,4],[2726,4],[4401,4]]},"30":{"position":[[538,4],[2374,4],[4547,4],[5590,4],[5661,4],[9167,4]]},"34":{"position":[[3549,4]]},"38":{"position":[[1096,4]]},"39":{"position":[[233,4]]},"40":{"position":[[62,4],[523,4],[861,4],[2059,4],[3003,4]]},"45":{"position":[[164,4]]},"73":{"position":[[354,4]]},"76":{"position":[[1241,5]]},"83":{"position":[[621,4]]},"85":{"position":[[394,5]]},"89":{"position":[[584,4]]},"91":{"position":[[95,4],[334,4],[2995,4],[4224,4],[4975,4],[5818,4]]},"92":{"position":[[140,4],[807,4]]},"95":{"position":[[355,4]]},"113":{"position":[[2500,4]]},"124":{"position":[[664,4]]},"125":{"position":[[152,4],[2254,4]]},"136":{"position":[[881,4],[890,5]]},"148":{"position":[[374,4]]},"199":{"position":[[873,4],[1017,4],[1306,4]]}},"keywords":{}}],["overal",{"_index":1400,"title":{},"content":{"30":{"position":[[4357,7]]},"105":{"position":[[3400,8]]},"188":{"position":[[3282,7]]}},"keywords":{}}],["overfit",{"_index":2809,"title":{},"content":{"82":{"position":[[1209,7]]},"83":{"position":[[454,9]]}},"keywords":{}}],["overflow",{"_index":5324,"title":{},"content":{"195":{"position":[[1066,8]]}},"keywords":{}}],["overhead",{"_index":5019,"title":{},"content":{"175":{"position":[[894,9]]}},"keywords":{}}],["overli",{"_index":4688,"title":{},"content":{"160":{"position":[[2295,6]]}},"keywords":{}}],["overloadable"becaus",{"_index":5360,"title":{},"content":{"198":{"position":[[636,25]]}},"keywords":{}}],["own",{"_index":3417,"title":{},"content":{"97":{"position":[[4608,5]]},"117":{"position":[[168,4],[236,5],[1485,5],[1507,5],[1632,4]]}},"keywords":{}}],["ownedseg",{"_index":3830,"title":{},"content":{"117":{"position":[[1460,13]]}},"keywords":{}}],["ownership",{"_index":3419,"title":{},"content":{"97":{"position":[[4702,9]]},"116":{"position":[[641,10],[677,9]]},"155":{"position":[[451,9]]},"160":{"position":[[1371,9]]},"193":{"position":[[3034,9]]}},"keywords":{}}],["ownershipmak",{"_index":3429,"title":{},"content":{"97":{"position":[[5728,13]]}},"keywords":{}}],["oxi",{"_index":713,"title":{},"content":{"17":{"position":[[176,6]]},"18":{"position":[[269,6]]},"19":{"position":[[495,6]]},"20":{"position":[[415,6],[2903,7]]}},"keywords":{}}],["p",{"_index":1722,"title":{},"content":{"39":{"position":[[571,2]]}},"keywords":{}}],["p"",{"_index":1489,"title":{},"content":{"30":{"position":[[9796,11],[10042,11]]}},"keywords":{}}],["p(pcurrent,pproposed)\\mathcal{p}(p_{curr",{"_index":2670,"title":{},"content":{"75":{"position":[[907,45]]}},"keywords":{}}],["p1−p",{"_index":1974,"title":{},"content":{"45":{"position":[[772,5]]}},"keywords":{}}],["p\\mathcal{p}p",{"_index":2672,"title":{},"content":{"75":{"position":[[1038,14]]}},"keywords":{}}],["p_2",{"_index":2636,"title":{},"content":{"74":{"position":[[598,3]]}},"keywords":{}}],["p_3",{"_index":2637,"title":{},"content":{"74":{"position":[[616,3]]}},"keywords":{}}],["p_val",{"_index":2595,"title":{},"content":{"70":{"position":[[990,7]]}},"keywords":{}}],["p_{11",{"_index":2639,"title":{},"content":{"74":{"position":[[650,6]]}},"keywords":{}}],["p_{12",{"_index":2640,"title":{},"content":{"74":{"position":[[672,6]]}},"keywords":{}}],["p_{proposed})p(pcurrent​,pproposed​)switch",{"_index":2671,"title":{},"content":{"75":{"position":[[953,42]]}},"keywords":{}}],["pack",{"_index":4861,"title":{},"content":{"168":{"position":[[206,6]]},"169":{"position":[[320,6]]}},"keywords":{}}],["packag",{"_index":107,"title":{},"content":{"2":{"position":[[462,7]]},"3":{"position":[[319,8]]},"108":{"position":[[397,7],[613,7]]},"109":{"position":[[240,9]]},"125":{"position":[[3942,7],[9556,8]]},"134":{"position":[[55,7]]},"190":{"position":[[544,8]]}},"keywords":{}}],["packages/ipykernel/parentpoller.py"",{"_index":5211,"title":{},"content":{"188":{"position":[[3822,41]]}},"keywords":{}}],["packaging/upgrades/etc",{"_index":4049,"title":{},"content":{"125":{"position":[[1516,23]]}},"keywords":{}}],["packet",{"_index":4774,"title":{},"content":{"163":{"position":[[1518,6],[1599,6]]},"175":{"position":[[802,7],[863,6],[1112,7],[1185,7]]}},"keywords":{}}],["packet_data",{"_index":4793,"title":{},"content":{"163":{"position":[[2054,12],[2116,13]]}},"keywords":{}}],["packet_len",{"_index":4789,"title":{},"content":{"163":{"position":[[1929,11]]}},"keywords":{}}],["pad",{"_index":3497,"title":{},"content":{"102":{"position":[[1060,6]]},"103":{"position":[[942,3],[1072,6]]}},"keywords":{}}],["padded.reshape((len(pad",{"_index":3530,"title":{},"content":{"103":{"position":[[1201,27]]}},"keywords":{}}],["page",{"_index":221,"title":{},"content":{"4":{"position":[[45,5]]},"22":{"position":[[86,5],[210,4],[790,4]]},"125":{"position":[[3857,4],[4025,5],[6667,4]]},"160":{"position":[[2936,4]]},"174":{"position":[[398,7],[593,6],[639,5],[697,4],[790,5]]}},"keywords":{}}],["paid",{"_index":547,"title":{},"content":{"13":{"position":[[237,4],[312,4]]},"14":{"position":[[164,4],[380,4]]},"15":{"position":[[178,4],[400,5],[480,5]]}},"keywords":{}}],["paid.at",{"_index":636,"title":{},"content":{"14":{"position":[[828,7]]}},"keywords":{}}],["pain",{"_index":3894,"title":{},"content":{"121":{"position":[[1246,5]]},"165":{"position":[[957,7]]},"190":{"position":[[45,4]]}},"keywords":{}}],["pair",{"_index":3116,"title":{},"content":{"91":{"position":[[2174,5]]}},"keywords":{}}],["palett",{"_index":1327,"title":{},"content":{"30":{"position":[[189,7]]}},"keywords":{}}],["palette[i",{"_index":1235,"title":{},"content":{"28":{"position":[[1057,10]]}},"keywords":{}}],["pan",{"_index":4821,"title":{},"content":{"165":{"position":[[63,3]]}},"keywords":{}}],["panda",{"_index":1328,"title":{},"content":{"30":{"position":[[204,6],[8325,6]]},"39":{"position":[[440,6]]},"43":{"position":[[274,6]]},"51":{"position":[[108,6]]},"62":{"position":[[304,6],[415,6]]},"68":{"position":[[428,6]]},"88":{"position":[[531,6]]},"90":{"position":[[202,6]]},"93":{"position":[[1252,6],[3838,6]]},"105":{"position":[[480,6]]}},"keywords":{}}],["pandas.tseries.holiday",{"_index":2963,"title":{},"content":{"90":{"position":[[220,22]]}},"keywords":{}}],["pandas.tseries.offset",{"_index":2965,"title":{},"content":{"90":{"position":[[280,22]]}},"keywords":{}}],["panic",{"_index":3507,"title":{},"content":{"103":{"position":[[269,5]]},"143":{"position":[[146,6],[287,5],[458,6]]},"144":{"position":[[234,5],[352,5],[401,5]]},"146":{"position":[[453,5]]},"147":{"position":[[352,5],[459,5],[514,5]]},"186":{"position":[[518,6]]}},"keywords":{}}],["panic!("init",{"_index":5143,"title":{},"content":{"186":{"position":[[619,17]]}},"keywords":{}}],["panic!("unexpect",{"_index":4532,"title":{},"content":{"152":{"position":[[1409,23],[1576,23]]},"156":{"position":[[1492,23],[1659,23]]}},"keywords":{}}],["panicalloc",{"_index":4525,"title":{},"content":{"152":{"position":[[1158,14],[1175,15],[1252,15],[1296,14]]},"156":{"position":[[1241,14],[1258,15],[1335,15],[1379,14]]}},"keywords":{}}],["panick",{"_index":166,"title":{},"content":{"3":{"position":[[631,9]]},"152":{"position":[[498,9],[998,10]]},"156":{"position":[[939,9],[1100,9]]}},"keywords":{}}],["paper",{"_index":2262,"title":{},"content":{"53":{"position":[[1271,5],[1987,5]]}},"keywords":{}}],["par",{"_index":1431,"title":{},"content":{"30":{"position":[[7543,3]]}},"keywords":{}}],["parallel",{"_index":4904,"title":{},"content":{"172":{"position":[[476,9],[685,9]]},"188":{"position":[[1864,8],[2410,9]]},"189":{"position":[[2354,9]]},"190":{"position":[[988,11]]}},"keywords":{}}],["param",{"_index":2375,"title":{},"content":{"61":{"position":[[1569,6]]}},"keywords":{}}],["paramet",{"_index":317,"title":{},"content":{"6":{"position":[[274,11],[624,10],[952,10]]},"14":{"position":[[1232,11]]},"15":{"position":[[599,10]]},"41":{"position":[[460,11]]},"74":{"position":[[124,11]]},"75":{"position":[[161,10],[427,10],[459,10],[505,10],[617,11],[668,9],[746,9],[806,9],[884,9],[1007,9]]},"85":{"position":[[208,9]]},"86":{"position":[[1011,10]]},"97":{"position":[[1720,9],[2396,10]]},"174":{"position":[[1104,10]]}},"keywords":{}}],["parameters.calcul",{"_index":2665,"title":{},"content":{"75":{"position":[[536,20]]}},"keywords":{}}],["parcel",{"_index":290,"title":{},"content":{"4":{"position":[[1339,6]]}},"keywords":{}}],["pardon",{"_index":3569,"title":{},"content":{"104":{"position":[[1630,7]]}},"keywords":{}}],["parking_lot",{"_index":4609,"title":{},"content":{"157":{"position":[[445,11]]}},"keywords":{}}],["pars",{"_index":879,"title":{"163":{"position":[[17,7]]}},"content":{"22":{"position":[[32,7],[236,5],[1151,5]]},"91":{"position":[[1881,5]]},"93":{"position":[[3891,5]]},"116":{"position":[[3234,6]]},"117":{"position":[[412,6],[903,7]]},"120":{"position":[[426,8]]},"122":{"position":[[284,8]]},"124":{"position":[[180,7]]},"165":{"position":[[405,7]]},"167":{"position":[[293,6]]}},"keywords":{}}],["parse(ev",{"_index":3283,"title":{},"content":{"93":{"position":[[4868,13],[5283,13]]}},"keywords":{}}],["parse(iso_str",{"_index":3124,"title":{},"content":{"91":{"position":[[2396,16]]}},"keywords":{}}],["parse(timestr",{"_index":4386,"title":{},"content":{"136":{"position":[[270,14]]}},"keywords":{}}],["parser",{"_index":920,"title":{},"content":{"22":{"position":[[988,6],[2486,6]]},"93":{"position":[[1388,6]]},"124":{"position":[[44,7]]},"136":{"position":[[689,6],[825,6],[874,6]]},"163":{"position":[[697,8],[725,6],[1642,6],[2433,6]]}},"keywords":{}}],["parser.articl",{"_index":923,"title":{},"content":{"22":{"position":[[1068,17]]}},"keywords":{}}],["parser.data",{"_index":974,"title":{},"content":{"22":{"position":[[2656,11]]}},"keywords":{}}],["parser.data.update({"text"",{"_index":972,"title":{},"content":{"22":{"position":[[2591,37]]}},"keywords":{}}],["parser.data.update({"url"",{"_index":971,"title":{},"content":{"22":{"position":[[2548,36]]}},"keywords":{}}],["parser.feed(article_html.text",{"_index":970,"title":{},"content":{"22":{"position":[[2517,30]]}},"keywords":{}}],["parser.feed(articles_html.text",{"_index":922,"title":{},"content":{"22":{"position":[[1017,31]]}},"keywords":{}}],["parser.parse(x",{"_index":3241,"title":{},"content":{"93":{"position":[[2779,15]]}},"keywords":{}}],["parser::default().pars",{"_index":4390,"title":{},"content":{"136":{"position":[[375,24]]}},"keywords":{}}],["parser::pars",{"_index":4395,"title":{},"content":{"136":{"position":[[515,13]]}},"keywords":{}}],["parseresult<(naivedatetim",{"_index":4388,"title":{},"content":{"136":{"position":[[301,30]]}},"keywords":{}}],["parsingpcap",{"_index":4769,"title":{},"content":{"163":{"position":[[817,11]]}},"keywords":{}}],["part",{"_index":1782,"title":{"40":{"position":[[24,5]]}},"content":{"51":{"position":[[1516,5]]},"64":{"position":[[195,4]]},"104":{"position":[[68,5]]},"113":{"position":[[572,4],[1082,4]]},"127":{"position":[[104,4]]},"133":{"position":[[21,4]]},"137":{"position":[[229,4]]},"150":{"position":[[956,4]]},"152":{"position":[[296,4]]},"160":{"position":[[2526,4]]},"164":{"position":[[37,4]]},"165":{"position":[[1186,4]]},"173":{"position":[[491,5]]},"176":{"position":[[948,5]]},"178":{"position":[[376,5]]},"180":{"position":[[74,4]]},"186":{"position":[[568,4]]}},"keywords":{}}],["parti",{"_index":4014,"title":{},"content":{"125":{"position":[[427,8]]}},"keywords":{}}],["particularli",{"_index":1341,"title":{},"content":{"30":{"position":[[656,12]]},"41":{"position":[[293,12]]}},"keywords":{}}],["partner",{"_index":3457,"title":{},"content":{"100":{"position":[[134,8]]}},"keywords":{}}],["pass",{"_index":473,"title":{},"content":{"9":{"position":[[634,6]]},"93":{"position":[[5101,6]]},"105":{"position":[[171,4]]},"121":{"position":[[1154,4]]},"141":{"position":[[331,4]]},"193":{"position":[[1294,4],[2951,7],[2998,7],[3047,7]]}},"keywords":{}}],["password",{"_index":2351,"title":{},"content":{"61":{"position":[[180,9],[646,9],[1017,9]]}},"keywords":{}}],["past",{"_index":1199,"title":{"91":{"position":[[37,4]]}},"content":{"28":{"position":[[89,4]]},"30":{"position":[[547,4],[5711,4]]},"33":{"position":[[341,4]]},"40":{"position":[[71,4]]},"57":{"position":[[200,4]]},"65":{"position":[[2253,4]]},"76":{"position":[[1431,4]]},"89":{"position":[[593,4]]},"91":{"position":[[104,4]]},"92":{"position":[[149,4]]},"93":{"position":[[2825,4],[2920,6]]},"125":{"position":[[161,4]]}},"keywords":{}}],["patch",{"_index":4119,"title":{},"content":{"125":{"position":[[5430,5]]}},"keywords":{}}],["path",{"_index":276,"title":{},"content":{"4":{"position":[[1051,4]]},"6":{"position":[[703,5],[1047,5]]},"7":{"position":[[585,6],[1059,5]]},"11":{"position":[[116,5]]},"12":{"position":[[187,5]]},"14":{"position":[[585,5]]},"108":{"position":[[504,5],[748,6]]},"112":{"position":[[608,5],[765,4],[894,5]]},"132":{"position":[[1006,4]]},"175":{"position":[[183,4]]}},"keywords":{}}],["path>",{"_index":122,"title":{},"content":{"2":{"position":[[730,9]]}},"keywords":{}}],["pattern",{"_index":2962,"title":{},"content":{"90":{"position":[[161,8]]},"91":{"position":[[5408,7],[5936,7]]},"92":{"position":[[1285,8],[1560,7]]},"121":{"position":[[527,9]]},"155":{"position":[[304,7]]},"179":{"position":[[343,7]]}},"keywords":{}}],["paus",{"_index":4914,"title":{},"content":{"172":{"position":[[1121,8]]},"173":{"position":[[1765,5]]}},"keywords":{}}],["pay",{"_index":670,"title":{},"content":{"15":{"position":[[215,4]]},"30":{"position":[[9479,3]]},"115":{"position":[[2590,3]]},"132":{"position":[[250,6]]},"161":{"position":[[686,6]]}},"keywords":{}}],["paymillion",{"_index":5002,"title":{},"content":{"175":{"position":[[58,11]]}},"keywords":{}}],["payoff",{"_index":582,"title":{},"content":{"13":{"position":[[1356,7]]},"14":{"position":[[2428,7]]},"15":{"position":[[2100,7]]}},"keywords":{}}],["pb",{"_index":2307,"title":{},"content":{"57":{"position":[[4,3]]}},"keywords":{}}],["pbar",{"_index":3265,"title":{},"content":{"93":{"position":[[3500,4]]}},"keywords":{}}],["pbar.update(i",{"_index":3270,"title":{},"content":{"93":{"position":[[3639,14]]}},"keywords":{}}],["pca",{"_index":1983,"title":{"99":{"position":[[0,3]]},"102":{"position":[[2,3]]}},"content":{"45":{"position":[[1382,3],[1575,3],[1978,3],[2036,3],[2628,3],[2823,3]]},"102":{"position":[[29,3],[65,3],[457,3],[862,3],[1090,3]]},"103":{"position":[[165,3],[756,4],[785,3],[850,3],[1281,3],[1293,3],[1467,4]]},"104":{"position":[[28,3],[112,3],[589,3],[747,3],[841,4],[1060,3],[1158,3],[1406,3],[1936,3]]},"105":{"position":[[523,5],[655,3],[961,3],[1005,5],[1387,4],[1510,4],[1560,4],[1952,3],[1956,3]]},"106":{"position":[[51,4],[271,3],[484,3],[563,3],[1007,3]]}},"keywords":{}}],["pca(n_components=dim",{"_index":1995,"title":{},"content":{"45":{"position":[[2042,22],[2829,22]]}},"keywords":{}}],["pca(n_components=n_compon",{"_index":3531,"title":{},"content":{"103":{"position":[[1299,30]]}},"keywords":{}}],["pca.components_.tobyt",{"_index":3593,"title":{},"content":{"105":{"position":[[1055,25]]}},"keywords":{}}],["pca.fit(reshap",{"_index":3532,"title":{},"content":{"103":{"position":[[1330,17]]}},"keywords":{}}],["pca.fit_transform(x",{"_index":2025,"title":{},"content":{"45":{"position":[[2862,20]]}},"keywords":{}}],["pca.fit_transform(x_no_bin",{"_index":1997,"title":{},"content":{"45":{"position":[[2075,27]]}},"keywords":{}}],["pca.inverse_transform(transformed).reshape((len(pad",{"_index":3536,"title":{},"content":{"103":{"position":[[1402,57]]}},"keywords":{}}],["pca.transform(reshap",{"_index":3534,"title":{},"content":{"103":{"position":[[1362,23]]}},"keywords":{}}],["pca_compression_result",{"_index":3608,"title":{},"content":{"105":{"position":[[1659,23],[1921,23]]}},"keywords":{}}],["pca_compression_results.column",{"_index":3611,"title":{},"content":{"105":{"position":[[1775,31]]}},"keywords":{}}],["pca_compression_results.index",{"_index":3616,"title":{},"content":{"105":{"position":[[1868,29]]}},"keywords":{}}],["pca_reduce(sign",{"_index":3520,"title":{},"content":{"103":{"position":[[877,18]]}},"keywords":{}}],["pca_reduce(tabulasa_left",{"_index":3539,"title":{},"content":{"103":{"position":[[1752,25],[2071,25]]},"105":{"position":[[1413,25],[2709,25],[2910,25],[3182,25]]}},"keywords":{}}],["pctl",{"_index":4858,"title":{},"content":{"168":{"position":[[172,4],[184,4]]},"169":{"position":[[286,4],[298,4]]}},"keywords":{}}],["pd",{"_index":1329,"title":{},"content":{"30":{"position":[[214,2],[8335,2]]},"39":{"position":[[450,2]]},"43":{"position":[[284,2]]},"51":{"position":[[118,2]]},"62":{"position":[[425,2]]},"68":{"position":[[438,2]]},"88":{"position":[[541,2]]},"90":{"position":[[212,2]]},"93":{"position":[[1262,2],[3848,2]]},"105":{"position":[[490,2]]}},"keywords":{}}],["pd.concat(hr_datafram",{"_index":2428,"title":{},"content":{"62":{"position":[[1225,24]]}},"keywords":{}}],["pd.concat(list(results.valu",{"_index":1779,"title":{},"content":{"39":{"position":[[3275,33]]}},"keywords":{}}],["pd.datafram",{"_index":1761,"title":{},"content":{"39":{"position":[[2642,14]]},"105":{"position":[[1685,14]]}},"keywords":{}}],["pd.dataframe(record['act",{"_index":2419,"title":{},"content":{"62":{"position":[[967,31]]}},"keywords":{}}],["pd.dataframe({"accuracy"",{"_index":1917,"title":{},"content":{"44":{"position":[[710,35]]}},"keywords":{}}],["pd.dataframe({'hashtag",{"_index":2128,"title":{},"content":{"51":{"position":[[2418,25]]}},"keywords":{}}],["pd.dataframe.from_dict(article_data).dropna",{"_index":987,"title":{},"content":{"22":{"position":[[3043,45]]}},"keywords":{}}],["pd.dataframe.from_dict(city_forecast",{"_index":1230,"title":{},"content":{"28":{"position":[[940,38]]},"30":{"position":[[1271,38]]}},"keywords":{}}],["pd.date_range(hr_df_concat.index[0",{"_index":2430,"title":{},"content":{"62":{"position":[[1338,36]]}},"keywords":{}}],["pd.date_range(start=datetime(year",{"_index":1479,"title":{},"content":{"30":{"position":[[9305,35]]}},"keywords":{}}],["pd.date_range(start_d",{"_index":2410,"title":{},"content":{"62":{"position":[[642,25]]}},"keywords":{}}],["pd.datetimeindex(start=datetime(year",{"_index":1240,"title":{},"content":{"28":{"position":[[1251,37],[3051,37]]},"30":{"position":[[1617,37],[2966,37],[4890,37],[6034,37]]}},"keywords":{}}],["pd.hdfstore('price_data.hdf",{"_index":3294,"title":{},"content":{"93":{"position":[[5494,29]]}},"keywords":{}}],["pd.read_csv('https://www.ishares.com/us/products/239714",{"_index":3247,"title":{},"content":{"93":{"position":[[3007,57]]}},"keywords":{}}],["pd.read_csv('split_train.csv",{"_index":1867,"title":{},"content":{"43":{"position":[[482,30]]}},"keywords":{}}],["pd.read_csv('train.csv",{"_index":2042,"title":{},"content":{"47":{"position":[[109,24]]}},"keywords":{}}],["pd.read_csv('tweets.csv",{"_index":2071,"title":{},"content":{"51":{"position":[[130,25]]}},"keywords":{}}],["pd.read_hdf('price_data.hdf",{"_index":3129,"title":{},"content":{"91":{"position":[[2775,29],[3531,29]]},"92":{"position":[[587,29]]}},"keywords":{}}],["pd.series(fair_1",{"_index":2564,"title":{},"content":{"68":{"position":[[572,16]]}},"keywords":{}}],["pd.series(sim",{"_index":1760,"title":{},"content":{"39":{"position":[[2618,14]]}},"keywords":{}}],["pd.series(word_dist[curr",{"_index":2165,"title":{},"content":{"51":{"position":[[4124,29]]}},"keywords":{}}],["pd.series(x1",{"_index":2603,"title":{},"content":{"70":{"position":[[1161,12]]},"71":{"position":[[1312,12]]}},"keywords":{}}],["peac",{"_index":3895,"title":{},"content":{"121":{"position":[[1257,5]]}},"keywords":{}}],["peak",{"_index":3101,"title":{},"content":{"91":{"position":[[1566,4]]}},"keywords":{}}],["peek",{"_index":4293,"title":{},"content":{"129":{"position":[[980,7]]}},"keywords":{}}],["penal",{"_index":1687,"title":{},"content":{"38":{"position":[[97,8],[823,8]]}},"keywords":{}}],["penalti",{"_index":4985,"title":{},"content":{"174":{"position":[[562,7]]}},"keywords":{}}],["peopl",{"_index":1322,"title":{},"content":{"30":{"position":[[21,6],[394,6],[2456,6],[9222,6],[9238,6]]},"32":{"position":[[25,7]]},"51":{"position":[[224,6]]},"59":{"position":[[33,6]]},"61":{"position":[[13,6],[105,6]]},"66":{"position":[[194,6]]},"89":{"position":[[227,6]]},"96":{"position":[[632,6]]},"101":{"position":[[909,6]]},"112":{"position":[[305,6]]},"120":{"position":[[349,6],[603,6]]},"122":{"position":[[1317,6]]},"123":{"position":[[901,6]]},"125":{"position":[[350,6]]},"150":{"position":[[156,6],[587,6]]},"160":{"position":[[2411,8]]},"176":{"position":[[180,7]]}},"keywords":{}}],["people'",{"_index":1342,"title":{},"content":{"30":{"position":[[717,8]]}},"keywords":{}}],["pep",{"_index":361,"title":{},"content":{"6":{"position":[[896,3]]}},"keywords":{}}],["per",{"_index":369,"title":{},"content":{"6":{"position":[[1025,3],[1094,3]]},"51":{"position":[[1950,3]]},"64":{"position":[[639,3]]},"65":{"position":[[525,3],[560,3]]},"101":{"position":[[87,3]]},"105":{"position":[[605,3],[752,3]]}},"keywords":{}}],["percentag",{"_index":1274,"title":{},"content":{"28":{"position":[[2189,12],[3862,12]]},"30":{"position":[[844,11],[2584,10]]},"90":{"position":[[4816,10]]}},"keywords":{}}],["percept",{"_index":1343,"title":{},"content":{"30":{"position":[[726,11]]}},"keywords":{}}],["perci",{"_index":4159,"title":{},"content":{"125":{"position":[[8266,5],[8339,6],[8787,5],[8853,5]]}},"keywords":{}}],["percymov",{"_index":4210,"title":{},"content":{"125":{"position":[[11358,11]]}},"keywords":{}}],["perf",{"_index":4989,"title":{},"content":{"174":{"position":[[715,4]]},"176":{"position":[[671,4]]}},"keywords":{}}],["perfect",{"_index":3989,"title":{},"content":{"123":{"position":[[1125,8]]}},"keywords":{}}],["perfectli",{"_index":5256,"title":{},"content":{"189":{"position":[[2998,9]]}},"keywords":{}}],["perform",{"_index":775,"title":{"171":{"position":[[17,11]]}},"content":{"20":{"position":[[504,10]]},"40":{"position":[[1165,10],[1512,8],[2519,8],[3268,9],[3370,9]]},"44":{"position":[[1741,8]]},"45":{"position":[[30,8],[100,11],[1131,7],[2650,10]]},"46":{"position":[[307,7]]},"73":{"position":[[239,7]]},"75":{"position":[[820,8]]},"88":{"position":[[2288,7],[2351,7]]},"91":{"position":[[55,7],[1723,8]]},"93":{"position":[[97,11],[168,12],[655,7],[785,11]]},"143":{"position":[[472,11]]},"148":{"position":[[42,11],[442,11]]},"158":{"position":[[14,11]]},"160":{"position":[[3320,12]]},"163":{"position":[[2361,12]]},"164":{"position":[[226,11]]},"165":{"position":[[182,12],[1022,12],[1472,7]]},"166":{"position":[[142,11]]},"169":{"position":[[108,7],[197,11]]},"170":{"position":[[255,12],[283,11]]},"172":{"position":[[1432,12],[1692,11],[2539,12]]},"174":{"position":[[130,11]]},"176":{"position":[[6,11],[289,11],[1419,11]]},"189":{"position":[[567,11],[1252,11],[1645,7],[2640,12]]}},"keywords":{}}],["performance"",{"_index":5049,"title":{},"content":{"176":{"position":[[911,18]]}},"keywords":{}}],["performancey",{"_index":4620,"title":{},"content":{"158":{"position":[[147,14]]}},"keywords":{}}],["period",{"_index":496,"title":{},"content":{"10":{"position":[[356,8]]},"18":{"position":[[68,7]]},"19":{"position":[[89,7]]},"20":{"position":[[71,7]]},"34":{"position":[[3556,6]]},"40":{"position":[[1268,7],[1535,7],[3250,7],[3469,8]]},"52":{"position":[[698,7]]},"65":{"position":[[318,7],[778,7],[957,7],[1058,8],[1111,7],[1167,8],[1221,7]]},"91":{"position":[[341,6]]}},"keywords":{}}],["peripher",{"_index":4687,"title":{},"content":{"160":{"position":[[2171,11]]}},"keywords":{}}],["permut",{"_index":2693,"title":{},"content":{"76":{"position":[[864,7],[2800,11]]}},"keywords":{}}],["permute(cur_d1",{"_index":2737,"title":{},"content":{"76":{"position":[[2611,15]]}},"keywords":{}}],["permute(d1_dens",{"_index":2696,"title":{},"content":{"76":{"position":[[969,19]]}},"keywords":{}}],["person",{"_index":1890,"title":{},"content":{"43":{"position":[[1361,7],[1409,7]]},"59":{"position":[[54,8]]},"60":{"position":[[27,8]]},"101":{"position":[[919,10]]},"105":{"position":[[3347,10]]},"125":{"position":[[10875,10]]},"150":{"position":[[539,6]]},"161":{"position":[[91,8]]}},"keywords":{}}],["perspect",{"_index":2651,"title":{},"content":{"74":{"position":[[1307,12]]},"173":{"position":[[247,12]]},"198":{"position":[[191,11]]}},"keywords":{}}],["phasea",{"_index":4214,"title":{},"content":{"125":{"position":[[11490,6]]}},"keywords":{}}],["philosoph",{"_index":2545,"title":{},"content":{"66":{"position":[[518,15]]}},"keywords":{}}],["philosophi",{"_index":5053,"title":{},"content":{"176":{"position":[[1455,11]]}},"keywords":{}}],["phoenix",{"_index":622,"title":{"14":{"position":[[0,7]]},"15":{"position":[[0,7]]}},"content":{"14":{"position":[[27,7],[227,7],[2943,7],[3334,7]]},"15":{"position":[[5,7],[58,8],[2617,7],[3005,7]]}},"keywords":{}}],["phoenix_no_memori",{"_index":651,"title":{},"content":{"14":{"position":[[2322,17],[2601,19]]}},"keywords":{}}],["phoenix_with_memori",{"_index":683,"title":{},"content":{"15":{"position":[[1992,19],[2273,21]]}},"keywords":{}}],["phonomena",{"_index":2898,"title":{},"content":{"88":{"position":[[2076,10]]}},"keywords":{}}],["pic",{"_index":3841,"title":{},"content":{"118":{"position":[[134,5]]},"161":{"position":[[252,5]]}},"keywords":{}}],["pick",{"_index":2143,"title":{},"content":{"51":{"position":[[3255,4],[3327,4]]},"124":{"position":[[479,4]]}},"keywords":{}}],["pickl",{"_index":1330,"title":{},"content":{"30":{"position":[[273,6],[900,6],[10061,6]]}},"keywords":{}}],["pickle.dump(city_forecast",{"_index":1497,"title":{},"content":{"30":{"position":[[10068,27]]}},"keywords":{}}],["pickle.load(open('city_forecasts.p",{"_index":1227,"title":{},"content":{"28":{"position":[[881,36]]},"30":{"position":[[1213,36]]}},"keywords":{}}],["pictur",{"_index":2557,"title":{},"content":{"68":{"position":[[224,7]]},"118":{"position":[[238,8]]},"135":{"position":[[70,7]]}},"keywords":{}}],["piec",{"_index":2717,"title":{},"content":{"76":{"position":[[1869,6]]},"97":{"position":[[5460,5]]}},"keywords":{}}],["pij∈(0,1);i,j∈{1,…,6}p_{ij",{"_index":2821,"title":{},"content":{"85":{"position":[[241,27]]}},"keywords":{}}],["pin",{"_index":4972,"title":{},"content":{"173":{"position":[[2201,7]]},"176":{"position":[[1002,7]]}},"keywords":{}}],["pip_ipi",{"_index":2642,"title":{},"content":{"74":{"position":[[778,8]]}},"keywords":{}}],["pipelin",{"_index":4198,"title":{},"content":{"125":{"position":[[10309,9]]},"174":{"position":[[321,9]]}},"keywords":{}}],["pipelining/specul",{"_index":4973,"title":{},"content":{"174":{"position":[[5,23]]}},"keywords":{}}],["place",{"_index":147,"title":{},"content":{"3":{"position":[[299,7]]},"4":{"position":[[334,5]]},"22":{"position":[[2695,6]]},"30":{"position":[[8064,6]]},"32":{"position":[[681,6]]},"98":{"position":[[262,6]]},"123":{"position":[[1004,5]]},"125":{"position":[[3324,6],[5071,6],[10583,5]]},"135":{"position":[[520,7]]},"136":{"position":[[758,6]]},"155":{"position":[[961,6]]},"156":{"position":[[652,5]]},"179":{"position":[[99,6]]}},"keywords":{}}],["plan",{"_index":1848,"title":{"41":{"position":[[12,5]]}},"content":{"75":{"position":[[1216,5]]},"96":{"position":[[2094,4]]},"113":{"position":[[2485,8]]},"132":{"position":[[381,8]]},"161":{"position":[[120,8],[1714,8]]}},"keywords":{}}],["platform",{"_index":4187,"title":{},"content":{"125":{"position":[[9513,8]]},"160":{"position":[[3469,8]]}},"keywords":{}}],["play",{"_index":62,"title":{},"content":{"1":{"position":[[694,7]]},"41":{"position":[[28,7],[435,7]]},"45":{"position":[[2635,4]]},"46":{"position":[[91,5]]},"98":{"position":[[617,7]]},"125":{"position":[[9917,4]]},"139":{"position":[[931,4]]},"150":{"position":[[620,4]]}},"keywords":{}}],["playground",{"_index":4538,"title":{},"content":{"152":{"position":[[1689,10]]},"153":{"position":[[1060,10]]},"156":{"position":[[1749,10]]},"179":{"position":[[754,10],[1178,10],[1618,10]]},"184":{"position":[[390,10],[739,10],[1172,10]]},"185":{"position":[[868,10]]},"186":{"position":[[675,10]]},"195":{"position":[[853,10]]}},"keywords":{}}],["pleas",{"_index":1445,"title":{},"content":{"30":{"position":[[8195,6]]},"43":{"position":[[223,6]]},"111":{"position":[[256,6]]},"147":{"position":[[65,6]]},"158":{"position":[[425,6]]},"160":{"position":[[4308,6]]}},"keywords":{}}],["plenti",{"_index":1216,"title":{},"content":{"28":{"position":[[620,6]]},"35":{"position":[[187,6]]},"89":{"position":[[50,6]]},"118":{"position":[[47,6]]},"125":{"position":[[340,6]]},"139":{"position":[[548,6]]},"176":{"position":[[1554,6]]},"183":{"position":[[670,6]]}},"keywords":{}}],["plot",{"_index":2919,"title":{},"content":{"88":{"position":[[2747,4],[3152,4]]},"91":{"position":[[902,6],[1378,7]]},"175":{"position":[[100,4]]}},"keywords":{}}],["plot(x=x",{"_index":436,"title":{},"content":{"7":{"position":[[1209,9]]}},"keywords":{}}],["plot_hilo(ax",{"_index":2906,"title":{},"content":{"88":{"position":[[2442,13]]}},"keywords":{}}],["plot_hilo(ax_aapl",{"_index":2921,"title":{},"content":{"88":{"position":[[2812,18],[2882,18]]}},"keywords":{}}],["plot_hilo(ax_fb",{"_index":2931,"title":{},"content":{"88":{"position":[[3211,16],[3278,16]]}},"keywords":{}}],["plot_study(array",{"_index":2978,"title":{},"content":{"90":{"position":[[743,18]]}},"keywords":{}}],["plot_study(five_day_ev",{"_index":3154,"title":{},"content":{"91":{"position":[[4169,27]]}},"keywords":{}}],["plot_study_small(array",{"_index":3014,"title":{},"content":{"90":{"position":[[2122,24]]}},"keywords":{}}],["plot_study_small(data",{"_index":3046,"title":{},"content":{"90":{"position":[[4169,22]]}},"keywords":{}}],["plt",{"_index":1718,"title":{},"content":{"39":{"position":[[481,3]]},"43":{"position":[[334,3]]},"51":{"position":[[1653,3]]},"68":{"position":[[469,3]]},"88":{"position":[[310,3]]}},"keywords":{}}],["plt.annot",{"_index":3051,"title":{},"content":{"90":{"position":[[4380,16]]}},"keywords":{}}],["plt.annotate('$\\pm",{"_index":3057,"title":{},"content":{"90":{"position":[[4472,19]]}},"keywords":{}}],["plt.annotate('mean",{"_index":3047,"title":{},"content":{"90":{"position":[[4244,18]]}},"keywords":{}}],["plt.annotate('min/max",{"_index":3061,"title":{},"content":{"90":{"position":[[4589,21]]}},"keywords":{}}],["plt.axhline(1",{"_index":2012,"title":{},"content":{"45":{"position":[[2365,13],[3145,13]]}},"keywords":{}}],["plt.axhline(naive_guess",{"_index":2009,"title":{},"content":{"45":{"position":[[2302,24],[3082,24]]}},"keywords":{}}],["plt.bar(coef_rang",{"_index":2763,"title":{},"content":{"78":{"position":[[470,19],[669,19]]}},"keywords":{}}],["plt.errorbar(range(1",{"_index":3017,"title":{},"content":{"90":{"position":[[3015,21]]}},"keywords":{}}],["plt.fill_between(range(0",{"_index":3016,"title":{},"content":{"90":{"position":[[2790,25]]}},"keywords":{}}],["plt.gcf().set_size_inches(10",{"_index":2773,"title":{},"content":{"78":{"position":[[764,29]]}},"keywords":{}}],["plt.gcf().set_size_inches(12",{"_index":2014,"title":{},"content":{"45":{"position":[[2440,29],[3220,29]]},"90":{"position":[[4210,29]]}},"keywords":{}}],["plt.gcf().set_size_inches(18",{"_index":1792,"title":{},"content":{"40":{"position":[[276,29],[445,29],[1810,29],[1981,29],[2753,29],[2925,29]]},"91":{"position":[[4292,29]]}},"keywords":{}}],["plt.gcf().suptitle("distribut",{"_index":1793,"title":{},"content":{"40":{"position":[[310,37],[1844,37],[2787,37]]}},"keywords":{}}],["plt.gcf().suptitle("profit",{"_index":1798,"title":{},"content":{"40":{"position":[[478,38],[2014,38],[2958,38]]}},"keywords":{}}],["plt.gcf().suptitle('act",{"_index":3155,"title":{},"content":{"91":{"position":[[4197,26]]}},"keywords":{}}],["plt.hist(d1_val",{"_index":2768,"title":{},"content":{"78":{"position":[[579,16]]}},"keywords":{}}],["plt.legend",{"_index":2015,"title":{},"content":{"45":{"position":[[2473,13],[3253,13]]}},"keywords":{}}],["plt.legend(loc=2",{"_index":2896,"title":{},"content":{"88":{"position":[[2006,18]]},"90":{"position":[[3121,17]]}},"keywords":{}}],["plt.legend(loc=3",{"_index":2884,"title":{},"content":{"88":{"position":[[1631,17]]},"90":{"position":[[4192,17]]}},"keywords":{}}],["plt.plot(dim_rang",{"_index":2004,"title":{},"content":{"45":{"position":[[2200,19],[2980,19]]}},"keywords":{}}],["plt.plot(range(range_begin",{"_index":3015,"title":{},"content":{"90":{"position":[[2743,27]]}},"keywords":{}}],["plt.subplot",{"_index":2864,"title":{},"content":{"88":{"position":[[1079,14]]}},"keywords":{}}],["plt.subplot(221",{"_index":2762,"title":{},"content":{"78":{"position":[[453,16]]}},"keywords":{}}],["plt.subplot(222",{"_index":2767,"title":{},"content":{"78":{"position":[[562,16]]}},"keywords":{}}],["plt.subplot(223",{"_index":2770,"title":{},"content":{"78":{"position":[[652,16]]}},"keywords":{}}],["plt.subplots(1",{"_index":2914,"title":{},"content":{"88":{"position":[[2690,15]]},"90":{"position":[[1321,15]]},"91":{"position":[[419,15]]}},"keywords":{}}],["plt.title("$d_1",{"_index":2610,"title":{},"content":{"71":{"position":[[1358,21]]}},"keywords":{}}],["plt.title("appl",{"_index":2885,"title":{},"content":{"88":{"position":[[1649,21]]}},"keywords":{}}],["plt.title('$d_1",{"_index":2605,"title":{},"content":{"70":{"position":[[1208,16]]}},"keywords":{}}],["plt.title('empir",{"_index":2769,"title":{},"content":{"78":{"position":[[616,20]]}},"keywords":{}}],["plt.title('facebook",{"_index":2893,"title":{},"content":{"88":{"position":[[1958,19]]}},"keywords":{}}],["plt.title('fair",{"_index":2567,"title":{},"content":{"68":{"position":[[627,15]]}},"keywords":{}}],["plt.title('recov",{"_index":2772,"title":{},"content":{"78":{"position":[[728,20]]}},"keywords":{}}],["plt.title('tru",{"_index":2766,"title":{},"content":{"78":{"position":[[531,15]]}},"keywords":{}}],["plt.vlines(date2num(datetime(2016",{"_index":2878,"title":{},"content":{"88":{"position":[[1510,34],[1837,34]]}},"keywords":{}}],["plt.xlim",{"_index":3018,"title":{},"content":{"90":{"position":[[3139,10]]}},"keywords":{}}],["plu",{"_index":634,"title":{},"content":{"14":{"position":[[806,4],[1143,4]]},"61":{"position":[[1117,5]]},"194":{"position":[[518,4]]}},"keywords":{}}],["plugin",{"_index":204,"title":{},"content":{"3":{"position":[[1296,7]]},"4":{"position":[[32,6]]}},"keywords":{}}],["pm",{"_index":1502,"title":{},"content":{"30":{"position":[[10194,2],[10248,2],[10298,2],[10349,2],[10387,2]]},"53":{"position":[[1431,3]]},"65":{"position":[[2549,2]]},"121":{"position":[[1089,2]]}},"keywords":{}}],["podcast",{"_index":3298,"title":{"94":{"position":[[12,10]]}},"content":{},"keywords":{}}],["poi(1)\\sim",{"_index":2116,"title":{},"content":{"51":{"position":[[1963,11]]}},"keywords":{}}],["poi(1)∼poi(1",{"_index":2117,"title":{},"content":{"51":{"position":[[1975,14]]}},"keywords":{}}],["point",{"_index":179,"title":{"113":{"position":[[17,6]]}},"content":{"3":{"position":[[856,6]]},"4":{"position":[[268,5]]},"25":{"position":[[2742,6]]},"28":{"position":[[477,5]]},"33":{"position":[[156,5]]},"50":{"position":[[157,5]]},"82":{"position":[[69,7]]},"86":{"position":[[358,7]]},"91":{"position":[[2642,6]]},"92":{"position":[[454,6],[1632,6]]},"93":{"position":[[2003,5]]},"97":{"position":[[2237,6]]},"105":{"position":[[693,6]]},"110":{"position":[[464,5]]},"112":{"position":[[1094,5],[1499,5]]},"113":{"position":[[932,7],[2102,7]]},"117":{"position":[[562,5]]},"123":{"position":[[482,5]]},"125":{"position":[[1683,5],[2834,6],[3237,5],[3804,5],[7505,6],[9177,5],[10225,5],[10354,5]]},"136":{"position":[[236,5]]},"147":{"position":[[19,5]]},"157":{"position":[[95,8]]},"163":{"position":[[357,6]]},"164":{"position":[[1229,5]]},"175":{"position":[[154,5],[165,5]]},"178":{"position":[[479,6]]},"179":{"position":[[11,5]]},"185":{"position":[[30,6]]},"190":{"position":[[50,6]]},"192":{"position":[[122,5],[165,6],[175,6],[302,5],[327,7],[376,5],[384,5],[478,7],[550,5]]},"193":{"position":[[913,5],[1776,5],[1811,5],[1843,5],[2218,5],[2731,5],[2766,5],[2798,5],[3184,5],[3252,6],[3262,6]]},"194":{"position":[[786,5]]}},"keywords":{}}],["point.capnp",{"_index":3695,"title":{},"content":{"110":{"position":[[422,12]]}},"keywords":{}}],["point_capnp",{"_index":3733,"title":{},"content":{"113":{"position":[[448,11]]}},"keywords":{}}],["point_capnp.r",{"_index":3714,"title":{},"content":{"112":{"position":[[694,14]]},"113":{"position":[[604,14]]}},"keywords":{}}],["point_capnp::point::owned>",{"_index":3828,"title":{},"content":{"117":{"position":[[1332,29]]}},"keywords":{}}],["point_capnp::point::read",{"_index":3813,"title":{},"content":{"116":{"position":[[2955,26]]},"117":{"position":[[1688,26]]}},"keywords":{}}],["point_capnp::point::reader<'_>",{"_index":3807,"title":{},"content":{"116":{"position":[[1007,38],[1307,38],[2001,38]]}},"keywords":{}}],["point_msg",{"_index":3747,"title":{},"content":{"113":{"position":[[1352,9]]}},"keywords":{}}],["point_msg.set_x(12",{"_index":3749,"title":{},"content":{"113":{"position":[[1461,20]]}},"keywords":{}}],["point_msg.set_y(14",{"_index":3750,"title":{},"content":{"113":{"position":[[1482,20]]}},"keywords":{}}],["point_read",{"_index":3761,"title":{},"content":{"113":{"position":[[2177,12]]},"115":{"position":[[365,12],[462,14],[641,14]]},"116":{"position":[[70,13],[465,12]]},"117":{"position":[[1254,13],[1427,12],[1619,12],[1953,12]]}},"keywords":{}}],["point_reader.get().unwrap",{"_index":3833,"title":{},"content":{"117":{"position":[[1750,28]]}},"keywords":{}}],["point_reader:point_capnp::point::reader<'_>",{"_index":3777,"title":{},"content":{"115":{"position":[[1042,51],[1389,51],[2130,51]]}},"keywords":{}}],["point_root",{"_index":3832,"title":{},"content":{"117":{"position":[[1737,10]]}},"keywords":{}}],["pointer",{"_index":3360,"title":{"155":{"position":[[6,9]]}},"content":{"97":{"position":[[121,8]]},"115":{"position":[[2930,7]]},"116":{"position":[[37,7],[2671,8]]},"127":{"position":[[886,8]]},"128":{"position":[[1806,7],[1857,7]]},"155":{"position":[[230,7],[502,8],[628,8],[917,7],[1038,8],[1062,7]]},"156":{"position":[[280,8]]},"157":{"position":[[364,8]]},"159":{"position":[[603,7],[753,9],[969,8],[1131,8]]},"181":{"position":[[805,8],[914,8]]},"193":{"position":[[493,7],[3057,8]]},"197":{"position":[[1247,7]]},"198":{"position":[[415,8]]}},"keywords":{}}],["pointer"",{"_index":4558,"title":{},"content":{"155":{"position":[[45,13]]}},"keywords":{}}],["poisson",{"_index":2061,"title":{},"content":{"49":{"position":[[554,7]]},"51":{"position":[[1870,7]]}},"keywords":{}}],["polici",{"_index":380,"title":{"123":{"position":[[18,7]]}},"content":{"7":{"position":[[105,6]]},"123":{"position":[[107,6]]}},"keywords":{}}],["polyglot",{"_index":4824,"title":{},"content":{"165":{"position":[[195,9]]}},"keywords":{}}],["polynomi",{"_index":1954,"title":{},"content":{"44":{"position":[[1916,10]]},"45":{"position":[[546,10]]},"76":{"position":[[164,10]]},"86":{"position":[[924,10]]}},"keywords":{}}],["polynomial.polynomial(d1_dens",{"_index":2681,"title":{},"content":{"76":{"position":[[349,33]]}},"keywords":{}}],["polynomial.polynomial(d2_dens",{"_index":2683,"title":{},"content":{"76":{"position":[[390,33]]}},"keywords":{}}],["pool",{"_index":3260,"title":{},"content":{"93":{"position":[[3391,5]]}},"keywords":{}}],["pool.submit(earnings_releas",{"_index":3262,"title":{},"content":{"93":{"position":[[3402,31]]}},"keywords":{}}],["poor",{"_index":1125,"title":{"100":{"position":[[26,5]]}},"content":{"24":{"position":[[3114,4]]},"103":{"position":[[2042,5],[2226,5]]},"105":{"position":[[2825,4]]},"165":{"position":[[1003,4]]},"189":{"position":[[2635,4]]}},"keywords":{}}],["poorli",{"_index":2902,"title":{},"content":{"88":{"position":[[2296,7],[2359,7]]},"93":{"position":[[663,6]]}},"keywords":{}}],["pop",{"_index":2968,"title":{},"content":{"90":{"position":[[450,3]]},"128":{"position":[[897,3],[1492,3]]}},"keywords":{}}],["popinstruct",{"_index":4717,"title":{},"content":{"160":{"position":[[4081,15]]}},"keywords":{}}],["popular",{"_index":3480,"title":{},"content":{"101":{"position":[[615,8]]},"150":{"position":[[924,7]]}},"keywords":{}}],["port",{"_index":1711,"title":{"119":{"position":[[15,7]]}},"content":{"39":{"position":[[286,6]]},"164":{"position":[[184,4]]},"166":{"position":[[602,4]]}},"keywords":{}}],["portabl",{"_index":287,"title":{},"content":{"4":{"position":[[1257,9]]}},"keywords":{}}],["portfolio",{"_index":795,"title":{},"content":{"20":{"position":[[860,10],[1527,9],[1554,9],[1605,10]]}},"keywords":{}}],["pose",{"_index":3393,"title":{},"content":{"97":{"position":[[2458,5]]}},"keywords":{}}],["posit",{"_index":745,"title":{},"content":{"19":{"position":[[231,9]]},"20":{"position":[[116,10],[990,10]]},"33":{"position":[[1026,9],[1247,9]]},"34":{"position":[[3540,8],[3939,9]]},"35":{"position":[[104,8]]},"38":{"position":[[1189,9]]},"81":{"position":[[82,8]]},"150":{"position":[[812,9]]},"161":{"position":[[63,10]]}},"keywords":{}}],["possibl",{"_index":1578,"title":{},"content":{"33":{"position":[[557,8],[978,8]]},"51":{"position":[[1100,8]]},"68":{"position":[[38,9]]},"69":{"position":[[261,9]]},"76":{"position":[[1201,13],[1585,11],[2990,8]]},"90":{"position":[[5341,8]]},"102":{"position":[[645,8],[1450,8]]},"115":{"position":[[2911,11]]},"120":{"position":[[1027,8]]},"121":{"position":[[456,9]]},"122":{"position":[[522,9]]},"125":{"position":[[3302,8]]},"132":{"position":[[91,8]]},"159":{"position":[[1230,9]]},"160":{"position":[[1323,9],[1698,8]]},"164":{"position":[[1498,9]]},"175":{"position":[[221,9]]},"181":{"position":[[682,9]]}},"keywords":{}}],["possible.y",{"_index":1579,"title":{},"content":{"33":{"position":[[722,12]]}},"keywords":{}}],["post",{"_index":250,"title":{"41":{"position":[[31,5]]}},"content":{"4":{"position":[[659,5]]},"26":{"position":[[905,7]]},"30":{"position":[[7972,4],[8189,5],[8273,5],[8312,5]]},"35":{"position":[[276,4],[294,4]]},"39":{"position":[[214,5]]},"41":{"position":[[413,5]]},"45":{"position":[[614,5]]},"53":{"position":[[862,4],[1324,7]]},"66":{"position":[[334,4]]},"86":{"position":[[674,4],[697,4]]},"96":{"position":[[639,4]]},"118":{"position":[[230,7]]},"125":{"position":[[2210,4],[2303,4],[2373,4],[2396,4]]},"133":{"position":[[33,5]]},"136":{"position":[[169,4]]},"166":{"position":[[72,6]]}},"keywords":{}}],["posts/contributor",{"_index":4221,"title":{},"content":{"125":{"position":[[11656,19]]}},"keywords":{}}],["potenti",{"_index":359,"title":{},"content":{"6":{"position":[[876,10]]},"35":{"position":[[446,10]]},"38":{"position":[[432,9]]},"91":{"position":[[5800,9]]},"98":{"position":[[1033,11]]},"123":{"position":[[504,9]]},"124":{"position":[[364,11]]},"160":{"position":[[4384,9]]},"172":{"position":[[1108,9]]},"190":{"position":[[583,13]]},"198":{"position":[[303,9]]}},"keywords":{}}],["power",{"_index":2018,"title":{},"content":{"45":{"position":[[2538,6],[3474,6]]}},"keywords":{}}],["ppp",{"_index":1975,"title":{},"content":{"45":{"position":[[783,3]]}},"keywords":{}}],["pr",{"_index":4108,"title":{},"content":{"125":{"position":[[5114,2]]}},"keywords":{}}],["practic",{"_index":1696,"title":{"114":{"position":[[20,9]]}},"content":{"38":{"position":[[731,9]]},"76":{"position":[[1632,8]]},"105":{"position":[[254,9]]},"106":{"position":[[1114,9]]},"113":{"position":[[2530,9]]},"122":{"position":[[712,9]]},"123":{"position":[[991,9]]},"129":{"position":[[2664,8]]},"188":{"position":[[4035,9]]},"197":{"position":[[1461,9]]}},"keywords":{}}],["pre",{"_index":4266,"title":{},"content":{"128":{"position":[[808,3]]},"150":{"position":[[295,3]]},"168":{"position":[[130,3]]},"193":{"position":[[316,3]]}},"keywords":{}}],["preced",{"_index":3099,"title":{},"content":{"91":{"position":[[1465,9],[2527,9]]},"92":{"position":[[339,9]]}},"keywords":{}}],["precip_day",{"_index":1420,"title":{},"content":{"30":{"position":[[6325,11]]}},"keywords":{}}],["precip_prob_sampl",{"_index":1419,"title":{},"content":{"30":{"position":[[6240,19],[6422,19]]}},"keywords":{}}],["precip_prob_v",{"_index":1418,"title":{},"content":{"30":{"position":[[6150,16],[6305,19],[6366,17]]}},"keywords":{}}],["precip_sampl",{"_index":1301,"title":{},"content":{"28":{"position":[[3257,14],[3519,14]]},"30":{"position":[[5091,14],[5198,14]]}},"keywords":{}}],["precip_v",{"_index":1299,"title":{},"content":{"28":{"position":[[3167,11],[3317,14]]},"30":{"position":[[5006,11],[5151,14]]}},"keywords":{}}],["precipit",{"_index":1219,"title":{},"content":{"28":{"position":[[686,13],[3764,13],[4325,13]]},"29":{"position":[[122,13]]},"30":{"position":[[4477,13],[4526,13],[4648,13],[5336,13],[5576,13]]}},"keywords":{}}],["precipprob",{"_index":1296,"title":{},"content":{"28":{"position":[[2916,19]]},"30":{"position":[[4761,19]]}},"keywords":{}}],["precis",{"_index":2657,"title":{},"content":{"74":{"position":[[1629,7]]},"98":{"position":[[1098,7]]},"145":{"position":[[30,10]]},"146":{"position":[[15,7]]},"160":{"position":[[4145,7]]},"176":{"position":[[92,9]]}},"keywords":{}}],["predetermin",{"_index":1597,"title":{},"content":{"34":{"position":[[629,13]]}},"keywords":{}}],["predict",{"_index":1016,"title":{"25":{"position":[[16,10]]},"42":{"position":[[0,10]]}},"content":{"24":{"position":[[92,10],[157,10],[244,10],[2632,10],[2979,10]]},"25":{"position":[[47,7],[2355,10],[2663,10],[2695,10]]},"26":{"position":[[116,10],[268,10],[343,7],[473,10],[578,10]]},"33":{"position":[[747,10]]},"43":{"position":[[716,11],[855,10],[1482,10]]},"44":{"position":[[421,10],[953,10],[1881,11]]},"45":{"position":[[1278,11],[1419,10],[1637,7],[3463,10]]},"46":{"position":[[182,7]]},"63":{"position":[[96,11]]},"65":{"position":[[2267,9]]},"88":{"position":[[3660,7]]},"89":{"position":[[180,8],[423,7]]},"92":{"position":[[1666,12]]},"93":{"position":[[777,7],[843,11]]},"139":{"position":[[867,7]]},"143":{"position":[[343,8]]},"174":{"position":[[166,11]]},"194":{"position":[[548,7]]}},"keywords":{}}],["predictablegold",{"_index":1124,"title":{},"content":{"24":{"position":[[3093,15]]}},"keywords":{}}],["prediction_dict",{"_index":1068,"title":{},"content":{"24":{"position":[[1596,15]]},"25":{"position":[[1350,15]]}},"keywords":{}}],["prediction_dict[index",{"_index":1085,"title":{},"content":{"24":{"position":[[2211,22]]},"25":{"position":[[1935,22]]}},"keywords":{}}],["predictor",{"_index":1126,"title":{},"content":{"24":{"position":[[3119,9]]},"44":{"position":[[174,10]]},"45":{"position":[[942,9]]},"174":{"position":[[386,10]]}},"keywords":{}}],["prefer",{"_index":1881,"title":{},"content":{"43":{"position":[[797,9]]}},"keywords":{}}],["prefetch",{"_index":5092,"title":{},"content":{"180":{"position":[[306,8]]}},"keywords":{}}],["preliminari",{"_index":1850,"title":{},"content":{"41":{"position":[[111,11]]}},"keywords":{}}],["prepar",{"_index":2899,"title":{},"content":{"88":{"position":[[2102,8]]},"100":{"position":[[67,8]]},"109":{"position":[[609,8]]}},"keywords":{}}],["preponder",{"_index":2945,"title":{},"content":{"89":{"position":[[122,13]]}},"keywords":{}}],["prescript",{"_index":4057,"title":{},"content":{"125":{"position":[[2078,13]]}},"keywords":{}}],["present",{"_index":619,"title":{},"content":{"13":{"position":[[2245,7]]},"14":{"position":[[3317,7]]},"15":{"position":[[2988,7]]},"32":{"position":[[700,7]]},"36":{"position":[[25,12]]},"64":{"position":[[135,7]]},"90":{"position":[[131,7]]}},"keywords":{}}],["preserv",{"_index":1483,"title":{},"content":{"30":{"position":[[9597,8]]}},"keywords":{}}],["press",{"_index":2291,"title":{},"content":{"54":{"position":[[204,5]]}},"keywords":{}}],["prestart",{"_index":4138,"title":{},"content":{"125":{"position":[[6427,8]]}},"keywords":{}}],["presum",{"_index":2733,"title":{},"content":{"76":{"position":[[2288,11]]},"91":{"position":[[5017,10]]},"93":{"position":[[855,10]]},"111":{"position":[[837,10]]}},"keywords":{}}],["pretenti",{"_index":3860,"title":{},"content":{"120":{"position":[[738,11]]}},"keywords":{}}],["pretti",{"_index":1119,"title":{"100":{"position":[[19,6]]}},"content":{"24":{"position":[[2965,6]]},"51":{"position":[[2136,6]]},"53":{"position":[[1882,6]]},"55":{"position":[[5,6]]},"63":{"position":[[47,6]]},"98":{"position":[[128,6],[462,6]]},"106":{"position":[[93,6]]},"110":{"position":[[37,6],[502,6]]},"112":{"position":[[973,6]]},"116":{"position":[[2511,6]]},"121":{"position":[[1493,6]]},"125":{"position":[[1768,6],[5000,6],[9187,6]]},"128":{"position":[[1670,6]]},"134":{"position":[[402,6]]},"161":{"position":[[1574,6]]}},"keywords":{}}],["prevail",{"_index":2939,"title":{},"content":{"88":{"position":[[3598,10]]}},"keywords":{}}],["prevent",{"_index":3794,"title":{},"content":{"115":{"position":[[3034,10]]},"125":{"position":[[3520,7]]}},"keywords":{}}],["previou",{"_index":1019,"title":{},"content":{"24":{"position":[[283,8]]},"30":{"position":[[620,8],[4227,8],[4406,8],[5760,8],[7214,8]]},"34":{"position":[[858,8]]},"49":{"position":[[229,8]]},"115":{"position":[[2471,8]]},"116":{"position":[[2329,8]]},"117":{"position":[[197,8]]},"183":{"position":[[215,8]]},"186":{"position":[[580,8]]}},"keywords":{}}],["previous",{"_index":4545,"title":{},"content":{"153":{"position":[[481,10]]},"161":{"position":[[660,11]]},"166":{"position":[[91,10]]},"169":{"position":[[74,10]]},"183":{"position":[[648,10]]}},"keywords":{}}],["price",{"_index":306,"title":{},"content":{"6":{"position":[[13,5],[1098,5]]},"12":{"position":[[88,7]]},"13":{"position":[[74,5],[766,5],[792,5]]},"14":{"position":[[17,7],[215,6],[638,6],[1623,5],[1649,5],[1765,5]]},"15":{"position":[[1010,5],[1036,5],[1155,5]]},"32":{"position":[[496,5],[548,5],[1101,5],[1259,5],[2315,6]]},"33":{"position":[[142,5],[193,5],[327,6],[434,5],[496,5],[631,5],[665,6]]},"34":{"position":[[426,5],[520,5],[566,5],[651,5]]},"88":{"position":[[1671,5],[1978,5],[3134,5],[3513,5]]},"90":{"position":[[4263,5],[4779,5],[4834,5],[4916,5],[5087,5],[5180,5],[5264,5]]},"91":{"position":[[318,5],[2602,5]]},"92":{"position":[[414,5]]},"93":{"position":[[2027,5],[3753,5],[5536,6],[5589,6]]},"163":{"position":[[228,7]]}},"keywords":{}}],["price_athena",{"_index":563,"title":{},"content":{"13":{"position":[[601,12]]}},"keywords":{}}],["price_athena(s0",{"_index":579,"title":{},"content":{"13":{"position":[[1170,16]]}},"keywords":{}}],["price_data.hdf",{"_index":3128,"title":{},"content":{"91":{"position":[[2695,14]]},"92":{"position":[[507,14]]}},"keywords":{}}],["price_dict",{"_index":3276,"title":{},"content":{"93":{"position":[[4655,10]]}},"keywords":{}}],["price_dict.item",{"_index":3295,"title":{},"content":{"93":{"position":[[5546,19]]}},"keywords":{}}],["price_dict[tick",{"_index":3286,"title":{},"content":{"93":{"position":[[4931,18],[5346,18]]}},"keywords":{}}],["price_funct",{"_index":578,"title":{},"content":{"13":{"position":[[1133,14]]},"14":{"position":[[2167,14]]},"15":{"position":[[1835,14]]}},"keywords":{}}],["price_function(motion[i",{"_index":583,"title":{},"content":{"13":{"position":[[1366,25]]},"14":{"position":[[2438,25]]},"15":{"position":[[2110,25]]}},"keywords":{}}],["price_phoenix_no_memori",{"_index":646,"title":{},"content":{"14":{"position":[[1431,23]]}},"keywords":{}}],["price_phoenix_no_memory(s0",{"_index":650,"title":{},"content":{"14":{"position":[[2204,27]]}},"keywords":{}}],["price_phoenix_with_memori",{"_index":677,"title":{},"content":{"15":{"position":[[800,25]]}},"keywords":{}}],["price_phoenix_with_memory(s0",{"_index":682,"title":{},"content":{"15":{"position":[[1872,29]]}},"keywords":{}}],["prices_stor",{"_index":3293,"title":{},"content":{"93":{"position":[[5479,12]]}},"keywords":{}}],["prices_store[tick",{"_index":3296,"title":{},"content":{"93":{"position":[[5566,20]]}},"keywords":{}}],["primit",{"_index":4222,"title":{"126":{"position":[[0,10]]},"127":{"position":[[9,10]]},"128":{"position":[[22,10]]},"129":{"position":[[5,9]]}},"content":{"127":{"position":[[31,9],[274,11],[422,10],[1011,9]]},"128":{"position":[[1720,11]]},"129":{"position":[[120,9],[199,10],[2071,10]]},"130":{"position":[[109,10],[150,10]]},"157":{"position":[[568,11]]},"196":{"position":[[179,10],[224,10]]}},"keywords":{}}],["principl",{"_index":554,"title":{},"content":{"13":{"position":[[390,9],[461,9]]},"14":{"position":[[514,9]]},"38":{"position":[[48,10]]},"45":{"position":[[1082,9]]},"68":{"position":[[277,10]]},"97":{"position":[[1333,9],[3398,9]]},"117":{"position":[[831,9]]},"122":{"position":[[465,9]]},"172":{"position":[[796,9]]},"188":{"position":[[805,9]]}},"keywords":{}}],["print",{"_index":1090,"title":{},"content":{"24":{"position":[[2385,7]]},"25":{"position":[[2108,7]]},"53":{"position":[[174,7]]},"61":{"position":[[1853,5]]},"179":{"position":[[609,6],[689,6],[999,6],[1112,6]]}},"keywords":{}}],["print(",{"_index":1494,"title":{},"content":{"30":{"position":[[9908,8]]}},"keywords":{}}],["print("articl",{"_index":1087,"title":{},"content":{"24":{"position":[[2305,20]]},"25":{"position":[[2029,20]]}},"keywords":{}}],["print("end",{"_index":1495,"title":{},"content":{"30":{"position":[[9951,15]]}},"keywords":{}}],["print("four",{"_index":2509,"title":{},"content":{"65":{"position":[[935,16]]}},"keywords":{}}],["print("heartbeat",{"_index":2436,"title":{},"content":{"62":{"position":[[1479,22]]},"64":{"position":[[1741,22]]}},"keywords":{}}],["print("look",{"_index":3219,"title":{},"content":{"93":{"position":[[2288,20]]}},"keywords":{}}],["print("na",{"_index":1943,"title":{},"content":{"44":{"position":[[1501,17]]}},"keywords":{}}],["print("predict",{"_index":1091,"title":{},"content":{"24":{"position":[[2393,22]]},"25":{"position":[[2116,22]]}},"keywords":{}}],["print("quart",{"_index":2524,"title":{},"content":{"65":{"position":[[1897,20]]}},"keywords":{}}],["print("remain",{"_index":2492,"title":{},"content":{"64":{"position":[[1812,21]]},"65":{"position":[[1012,21],[1970,21]]}},"keywords":{}}],["print("retriev",{"_index":1486,"title":{},"content":{"30":{"position":[[9688,22]]}},"keywords":{}}],["print("run",{"_index":2036,"title":{},"content":{"46":{"position":[[609,19]]}},"keywords":{}}],["print("satisfi",{"_index":1938,"title":{},"content":{"44":{"position":[[1356,21]]}},"keywords":{}}],["print("simul",{"_index":2758,"title":{},"content":{"78":{"position":[[344,21]]}},"keywords":{}}],["print("{}".format(list_2[index_dt",{"_index":1067,"title":{},"content":{"24":{"position":[[1533,47]]},"25":{"position":[[1253,47]]}},"keywords":{}}],["print('iter",{"_index":2735,"title":{},"content":{"76":{"position":[[2502,17]]}},"keywords":{}}],["print(pd.dataframe.from_dict(count_dict",{"_index":1089,"title":{},"content":{"24":{"position":[[2343,41]]},"25":{"position":[[2066,41]]}},"keywords":{}}],["print(pd.dataframe.from_dict(prediction_dict",{"_index":1093,"title":{},"content":{"24":{"position":[[2433,46]]},"25":{"position":[[2156,46]]}},"keywords":{}}],["print(self.x",{"_index":4306,"title":{},"content":{"129":{"position":[[1962,13]]}},"keywords":{}}],["print(simulate_tweet",{"_index":2197,"title":{},"content":{"53":{"position":[[150,23]]}},"keywords":{}}],["printf("mean",{"_index":590,"title":{},"content":{"13":{"position":[[1551,18]]},"14":{"position":[[2634,18]]},"15":{"position":[[2308,18]]}},"keywords":{}}],["printf("pres",{"_index":601,"title":{},"content":{"13":{"position":[[1829,21]]},"14":{"position":[[2912,21]]},"15":{"position":[[2586,21]]}},"keywords":{}}],["printf("tim",{"_index":537,"title":{},"content":{"12":{"position":[[588,18]]}},"keywords":{}}],["println",{"_index":3351,"title":{},"content":{"96":{"position":[[1968,8]]}},"keywords":{}}],["println!("cel",{"_index":5074,"title":{},"content":{"179":{"position":[[623,20],[703,20],[1021,20],[1122,20]]}},"keywords":{}}],["println!("const",{"_index":5126,"title":{},"content":{"184":{"position":[[663,20]]}},"keywords":{}}],["println!("initi",{"_index":5084,"title":{},"content":{"179":{"position":[[1561,27]]}},"keywords":{}}],["println!("initializing..."",{"_index":5083,"title":{},"content":{"179":{"position":[[1360,39]]},"186":{"position":[[459,39]]}},"keywords":{}}],["println!("stat",{"_index":5123,"title":{},"content":{"184":{"position":[[323,21]]}},"keywords":{}}],["println("actu",{"_index":504,"title":{},"content":{"10":{"position":[[484,20]]}},"keywords":{}}],["println("day",{"_index":1652,"title":{},"content":{"34":{"position":[[2908,18]]}},"keywords":{}}],["println("max",{"_index":1650,"title":{},"content":{"34":{"position":[[2857,17]]}},"keywords":{}}],["println("mean",{"_index":595,"title":{},"content":{"13":{"position":[[1690,18]]},"14":{"position":[[2773,18]]},"15":{"position":[[2447,18]]}},"keywords":{}}],["println("profit",{"_index":1654,"title":{},"content":{"34":{"position":[[2967,21]]}},"keywords":{}}],["prior",{"_index":669,"title":{},"content":{"15":{"position":[[186,5]]},"18":{"position":[[62,5]]},"30":{"position":[[7552,5]]},"43":{"position":[[128,5]]},"91":{"position":[[124,5],[5379,5]]},"93":{"position":[[109,5]]}},"keywords":{}}],["prior_clos",{"_index":1032,"title":{},"content":{"24":{"position":[[617,11],[714,12],[729,11]]}},"keywords":{}}],["priorit",{"_index":4628,"title":{},"content":{"159":{"position":[[310,10]]}},"keywords":{}}],["prioriti",{"_index":3892,"title":{},"content":{"121":{"position":[[1159,8]]}},"keywords":{}}],["privaci",{"_index":2480,"title":{},"content":{"64":{"position":[[1374,7]]}},"keywords":{}}],["privat",{"_index":4816,"title":{},"content":{"164":{"position":[[1339,7]]}},"keywords":{}}],["prob",{"_index":1421,"title":{},"content":{"30":{"position":[[6339,5],[6358,4]]},"51":{"position":[[2461,7],[3632,7],[3679,6],[3965,5],[4071,6],[4154,5],[4222,6]]}},"keywords":{}}],["probabl",{"_index":1380,"title":{},"content":{"30":{"position":[[2851,8]]},"51":{"position":[[776,11],[947,8],[3242,12],[3339,11],[3363,11],[3451,13]]},"74":{"position":[[65,11],[794,11],[878,11]]},"75":{"position":[[848,11],[1026,11]]},"76":{"position":[[235,13],[522,13],[1085,11]]},"91":{"position":[[365,8]]},"121":{"position":[[2537,8]]},"125":{"position":[[396,8]]},"150":{"position":[[424,8]]},"174":{"position":[[940,8]]},"188":{"position":[[4099,8]]}},"keywords":{}}],["problem",{"_index":81,"title":{},"content":{"2":{"position":[[101,8],[495,7]]},"3":{"position":[[430,8]]},"4":{"position":[[492,8],[576,7]]},"45":{"position":[[3495,7]]},"73":{"position":[[687,9]]},"74":{"position":[[178,8]]},"85":{"position":[[172,7]]},"86":{"position":[[98,8]]},"125":{"position":[[905,8],[1145,8]]},"143":{"position":[[41,9]]},"150":{"position":[[286,8]]},"165":{"position":[[152,8],[583,7],[1303,8]]},"172":{"position":[[1978,7]]},"190":{"position":[[880,8]]}},"keywords":{}}],["proce",{"_index":2093,"title":{},"content":{"51":{"position":[[924,7]]}},"keywords":{}}],["procedur",{"_index":4445,"title":{"144":{"position":[[8,10]]}},"content":{},"keywords":{}}],["proceed",{"_index":2106,"title":{},"content":{"51":{"position":[[1372,10],[1437,10]]}},"keywords":{}}],["process",{"_index":1854,"title":{"75":{"position":[[4,7]]},"111":{"position":[[29,8]]}},"content":{"41":{"position":[[521,8]]},"45":{"position":[[1542,8]]},"51":{"position":[[2801,7]]},"61":{"position":[[1415,11]]},"73":{"position":[[252,8]]},"82":{"position":[[1057,7]]},"93":{"position":[[1041,10]]},"100":{"position":[[250,10]]},"102":{"position":[[131,7]]},"103":{"position":[[1285,7]]},"104":{"position":[[713,10]]},"106":{"position":[[1161,10]]},"111":{"position":[[44,7]]},"113":{"position":[[745,7]]},"122":{"position":[[1426,7]]},"125":{"position":[[4096,8]]},"164":{"position":[[738,7]]},"165":{"position":[[965,7]]},"173":{"position":[[375,7],[551,9],[679,7],[740,9],[2067,7]]},"176":{"position":[[440,8]]},"188":{"position":[[245,11],[2668,10]]}},"keywords":{}}],["processbecom",{"_index":4128,"title":{},"content":{"125":{"position":[[5723,14]]}},"keywords":{}}],["processor",{"_index":128,"title":{},"content":{"2":{"position":[[814,9]]},"163":{"position":[[44,10]]},"173":{"position":[[1747,9]]},"174":{"position":[[61,10]]}},"keywords":{}}],["prod(forward_structur",{"_index":599,"title":{},"content":{"13":{"position":[[1797,24]]},"14":{"position":[[2879,24]]},"15":{"position":[[2553,24]]}},"keywords":{}}],["prod_{i=1}^n",{"_index":2646,"title":{},"content":{"74":{"position":[[1105,13]]}},"keywords":{}}],["produc",{"_index":1674,"title":{},"content":{"35":{"position":[[416,8]]}},"keywords":{}}],["product",{"_index":246,"title":{"150":{"position":[[22,10]]}},"content":{"4":{"position":[[605,10]]},"12":{"position":[[116,9]]},"14":{"position":[[83,11],[235,7]]},"74":{"position":[[1379,7]]},"125":{"position":[[10815,10]]},"143":{"position":[[296,10]]},"160":{"position":[[896,12]]},"161":{"position":[[137,11]]},"176":{"position":[[1367,10]]}},"keywords":{}}],["profit",{"_index":1590,"title":{"37":{"position":[[0,13]]}},"content":{"33":{"position":[[1319,10]]},"34":{"position":[[304,7],[1859,6],[1874,10],[2041,11],[2350,10],[2623,6],[2686,7],[2734,7],[3232,7],[3281,7],[3303,6],[3404,7],[3464,7],[3694,6],[3795,7],[3856,7],[3980,6]]},"35":{"position":[[439,6]]},"38":{"position":[[75,7],[297,6],[501,13]]},"39":{"position":[[548,13],[1089,10],[1256,11],[1570,10],[1883,11],[2071,6],[2135,6]]},"40":{"position":[[817,7],[841,13],[973,13],[1425,13],[2219,13],[2393,13],[3331,14],[3442,10]]},"41":{"position":[[156,7]]}},"keywords":{}}],["profit"",{"_index":1655,"title":{},"content":{"34":{"position":[[2989,14]]}},"keywords":{}}],["profitability"",{"_index":1794,"title":{},"content":{"40":{"position":[[362,20],[1896,20],[2839,20]]}},"keywords":{}}],["profitability(x[1",{"_index":1770,"title":{},"content":{"39":{"position":[[2903,19]]}},"keywords":{}}],["program",{"_index":2283,"title":{},"content":{"53":{"position":[[1845,7]]},"86":{"position":[[1125,7]]},"97":{"position":[[80,8],[490,7]]},"112":{"position":[[418,11]]},"117":{"position":[[2146,9]]},"125":{"position":[[998,11]]},"127":{"position":[[521,7]]},"128":{"position":[[1070,7]]},"134":{"position":[[200,7]]},"135":{"position":[[176,7]]},"136":{"position":[[153,8]]},"137":{"position":[[144,7]]},"139":{"position":[[761,8]]},"143":{"position":[[178,7]]},"153":{"position":[[467,8],[966,7]]},"160":{"position":[[554,7],[1167,8],[1854,7],[2262,8],[3161,7],[3270,8]]},"163":{"position":[[565,7]]},"172":{"position":[[1858,7],[1993,7],[2493,11]]},"173":{"position":[[141,8],[465,9],[1242,8],[1920,7]]},"176":{"position":[[637,7]]},"178":{"position":[[53,7],[390,9]]},"180":{"position":[[87,7],[154,7]]},"182":{"position":[[151,8],[539,7]]},"188":{"position":[[25,11]]},"195":{"position":[[157,8],[806,7]]}},"keywords":{}}],["programm",{"_index":3442,"title":{},"content":{"98":{"position":[[437,11]]},"120":{"position":[[879,11]]},"121":{"position":[[53,11],[82,12]]},"160":{"position":[[103,11],[274,11]]}},"keywords":{}}],["progress",{"_index":1394,"title":{},"content":{"30":{"position":[[4104,11]]},"123":{"position":[[1100,9]]},"125":{"position":[[11095,9]]}},"keywords":{}}],["progressbar",{"_index":3105,"title":{},"content":{"91":{"position":[[1892,11],[1911,11]]},"93":{"position":[[1402,11],[3947,11],[3966,11]]}},"keywords":{}}],["progressbar()(ticker_d",{"_index":3146,"title":{},"content":{"91":{"position":[[3445,28]]}},"keywords":{}}],["progressbar()(tickers[0:1500",{"_index":3278,"title":{},"content":{"93":{"position":[[4706,31]]}},"keywords":{}}],["progressbar()(tickers[1500",{"_index":3292,"title":{},"content":{"93":{"position":[[5122,30]]}},"keywords":{}}],["progressbar.progressbar(term_width=80",{"_index":3266,"title":{},"content":{"93":{"position":[[3507,38]]}},"keywords":{}}],["project",{"_index":10,"title":{"107":{"position":[[20,7]]},"109":{"position":[[36,8]]}},"content":{"1":{"position":[[85,7],[226,8]]},"3":{"position":[[192,7]]},"57":{"position":[[307,8],[355,8]]},"58":{"position":[[899,7]]},"100":{"position":[[87,7],[334,8],[390,7]]},"109":{"position":[[73,8],[657,8]]},"110":{"position":[[173,8]]},"111":{"position":[[818,8]]},"112":{"position":[[86,7],[666,7]]},"113":{"position":[[40,7],[2453,8]]},"118":{"position":[[182,9]]},"125":{"position":[[7389,8],[7757,7],[8204,8],[11628,7]]},"161":{"position":[[182,9]]},"163":{"position":[[290,7]]},"190":{"position":[[124,8]]}},"keywords":{}}],["project"",{"_index":4357,"title":{},"content":{"132":{"position":[[870,13]]}},"keywords":{}}],["prologu",{"_index":4760,"title":{"163":{"position":[[0,9]]}},"content":{},"keywords":{}}],["promis",{"_index":2551,"title":{},"content":{"66":{"position":[[841,7]]},"125":{"position":[[4256,7],[4354,7]]}},"keywords":{}}],["proof",{"_index":4195,"title":{},"content":{"125":{"position":[[10195,5],[10444,6]]}},"keywords":{}}],["proper",{"_index":448,"title":{},"content":{"8":{"position":[[144,6]]}},"keywords":{}}],["properli",{"_index":3899,"title":{},"content":{"121":{"position":[[1397,8]]},"133":{"position":[[108,8]]}},"keywords":{}}],["properti",{"_index":667,"title":{},"content":{"15":{"position":[[125,9]]},"156":{"position":[[185,8]]},"185":{"position":[[519,9]]}},"keywords":{}}],["proport",{"_index":5030,"title":{},"content":{"175":{"position":[[1316,12]]}},"keywords":{}}],["proportion",{"_index":4896,"title":{},"content":{"170":{"position":[[299,15]]}},"keywords":{}}],["propos",{"_index":2666,"title":{},"content":{"75":{"position":[[659,8]]},"76":{"position":[[73,8],[876,8]]},"139":{"position":[[920,7]]}},"keywords":{}}],["protect",{"_index":555,"title":{},"content":{"13":{"position":[[400,10],[422,10],[945,10]]},"14":{"position":[[453,10],[475,10],[1300,10],[1963,10]]},"15":{"position":[[1631,10]]},"38":{"position":[[569,7]]},"146":{"position":[[483,10]]}},"keywords":{}}],["protection_barri",{"_index":560,"title":{},"content":{"13":{"position":[[549,18],[667,19],[981,18],[1214,19]]},"14":{"position":[[1379,18],[1524,19],[1999,18],[2275,19]]},"15":{"position":[[748,18],[895,19],[1667,18],[1945,19]]}},"keywords":{}}],["proto",{"_index":3679,"title":{"109":{"position":[[25,5]]},"164":{"position":[[6,6]]}},"content":{"109":{"position":[[541,5],[651,5]]},"111":{"position":[[76,5],[612,5]]},"112":{"position":[[1244,5]]},"113":{"position":[[24,6],[133,5],[773,5],[2558,5]]},"116":{"position":[[3247,5]]},"117":{"position":[[55,5],[695,5],[2101,5]]},"164":{"position":[[62,5],[306,5],[806,5],[1027,5],[1198,5],[1481,5]]},"165":{"position":[[170,6],[398,6],[1130,5]]},"166":{"position":[[332,5]]},"168":{"position":[[200,5],[246,5]]},"169":{"position":[[314,5],[360,5]]}},"keywords":{}}],["proto'",{"_index":3663,"title":{},"content":{"108":{"position":[[277,7]]}},"keywords":{}}],["proto'sbenchmarksto",{"_index":4808,"title":{},"content":{"164":{"position":[[635,19]]}},"keywords":{}}],["protocol",{"_index":3707,"title":{},"content":{"111":{"position":[[515,8]]},"125":{"position":[[4885,8],[4905,8]]},"175":{"position":[[552,9],[579,8]]}},"keywords":{}}],["proud",{"_index":4080,"title":{},"content":{"125":{"position":[[3358,5]]}},"keywords":{}}],["prove",{"_index":2356,"title":{"68":{"position":[[0,7]]}},"content":{"61":{"position":[[626,5]]},"125":{"position":[[3288,5],[9261,5]]},"155":{"position":[[1225,5]]},"160":{"position":[[4179,5]]},"183":{"position":[[857,5]]},"193":{"position":[[2200,5]]}},"keywords":{}}],["proven",{"_index":3802,"title":{},"content":{"116":{"position":[[634,6]]}},"keywords":{}}],["provid",{"_index":2365,"title":{},"content":{"61":{"position":[[1170,9]]},"97":{"position":[[780,8]]},"157":{"position":[[179,8],[421,8]]},"179":{"position":[[315,8]]},"183":{"position":[[74,8]]},"190":{"position":[[386,8],[911,7]]},"195":{"position":[[438,8]]}},"keywords":{}}],["providesextens",{"_index":5260,"title":{},"content":{"190":{"position":[[352,17]]}},"keywords":{}}],["pt",{"_index":1895,"title":{"44":{"position":[[25,3]]},"45":{"position":[[25,3]]}},"content":{},"keywords":{}}],["ptr",{"_index":4262,"title":{},"content":{"128":{"position":[[529,3],[642,3],[876,3],[1594,3]]},"152":{"position":[[1507,4]]},"156":{"position":[[1590,4]]},"183":{"position":[[393,3],[539,3]]}},"keywords":{}}],["pub",{"_index":3731,"title":{},"content":{"113":{"position":[[440,3]]},"129":{"position":[[414,3],[1526,3]]},"136":{"position":[[263,3]]},"152":{"position":[[466,3]]},"153":{"position":[[743,3]]},"155":{"position":[[1339,3],[1402,3],[1463,3],[1526,3]]},"156":{"position":[[623,3]]},"163":{"position":[[1737,3]]},"180":{"position":[[418,3]]},"181":{"position":[[98,3],[214,3]]},"183":{"position":[[323,3],[463,3]]},"192":{"position":[[184,3]]},"193":{"position":[[1738,3],[2693,3],[3173,3],[3227,3],[3528,3]]},"194":{"position":[[299,3]]},"196":{"position":[[1141,3],[1523,3],[1734,3]]},"197":{"position":[[928,3],[1147,3]]},"199":{"position":[[1231,3],[1368,3],[1524,3]]}},"keywords":{}}],["public",{"_index":4229,"title":{},"content":{"127":{"position":[[594,6],[1244,6]]},"199":{"position":[[102,6],[262,6]]}},"keywords":{}}],["publicli",{"_index":5042,"title":{},"content":{"176":{"position":[[218,8]]}},"keywords":{}}],["publish",{"_index":3874,"title":{},"content":{"121":{"position":[[122,7]]}},"keywords":{}}],["pubugn9",{"_index":1326,"title":{},"content":{"30":{"position":[[178,7]]}},"keywords":{}}],["pull",{"_index":2168,"title":{"52":{"position":[[0,7]]}},"content":{"59":{"position":[[43,4]]},"62":{"position":[[339,4]]},"161":{"position":[[1392,4]]}},"keywords":{}}],["pun",{"_index":3570,"title":{},"content":{"104":{"position":[[1642,4]]},"160":{"position":[[3640,4]]}},"keywords":{}}],["purchas",{"_index":1537,"title":{},"content":{"32":{"position":[[1143,9]]},"33":{"position":[[1278,9]]}},"keywords":{}}],["purchase_histori",{"_index":1606,"title":{},"content":{"34":{"position":[[1104,17],[1448,17]]},"39":{"position":[[635,17],[677,17],[824,17],[900,17],[920,16]]}},"keywords":{}}],["purchase_history*current_clos",{"_index":1617,"title":{},"content":{"34":{"position":[[1288,30]]}},"keywords":{}}],["pure",{"_index":2448,"title":{},"content":{"63":{"position":[[135,6]]},"97":{"position":[[2277,4]]},"161":{"position":[[277,6]]},"190":{"position":[[736,4]]}},"keywords":{}}],["purpos",{"_index":2481,"title":{},"content":{"64":{"position":[[1382,8]]},"125":{"position":[[5036,7],[6238,7],[9617,7]]}},"keywords":{}}],["push",{"_index":4255,"title":{},"content":{"128":{"position":[[447,4],[759,4],[1281,4]]},"160":{"position":[[4072,4]]},"176":{"position":[[981,7]]}},"keywords":{}}],["push_vec(&v",{"_index":4455,"title":{},"content":{"144":{"position":[[358,17],[407,17]]}},"keywords":{}}],["push_vec(v",{"_index":4451,"title":{},"content":{"144":{"position":[[177,11]]}},"keywords":{}}],["put",{"_index":45,"title":{"116":{"position":[[11,3]]}},"content":{"1":{"position":[[527,3]]},"13":{"position":[[1020,3],[1081,4]]},"14":{"position":[[2054,3],[2115,4]]},"15":{"position":[[1722,3],[1783,4]]},"52":{"position":[[523,3]]},"64":{"position":[[1396,3]]},"97":{"position":[[547,3]]},"102":{"position":[[172,3]]},"109":{"position":[[196,3]]},"110":{"position":[[393,3]]},"111":{"position":[[263,3]]},"113":{"position":[[162,3],[213,3]]},"125":{"position":[[932,3]]},"130":{"position":[[348,3]]},"136":{"position":[[797,3]]},"160":{"position":[[3066,3]]},"161":{"position":[[618,3],[759,3],[1109,3]]},"164":{"position":[[1443,3]]},"172":{"position":[[900,3]]},"188":{"position":[[1,3]]},"193":{"position":[[718,3]]}},"keywords":{}}],["pv",{"_index":598,"title":{},"content":{"13":{"position":[[1773,2],[1905,3]]},"14":{"position":[[2856,2],[2986,3]]},"15":{"position":[[2530,2],[2657,3]]}},"keywords":{}}],["pyeval_savethread",{"_index":5206,"title":{},"content":{"188":{"position":[[3666,18]]}},"keywords":{}}],["pyo3",{"_index":3915,"title":{},"content":{"121":{"position":[[2080,5]]}},"keywords":{}}],["pypi",{"_index":4927,"title":{},"content":{"172":{"position":[[1815,5]]}},"keywords":{}}],["python",{"_index":1712,"title":{"129":{"position":[[20,8]]}},"content":{"39":{"position":[[296,6]]},"95":{"position":[[382,7]]},"96":{"position":[[41,6],[112,6],[424,6],[868,6]]},"98":{"position":[[600,7]]},"103":{"position":[[115,6]]},"120":{"position":[[81,6],[157,6]]},"121":{"position":[[75,6],[130,6],[234,7],[1272,6],[1615,6]]},"122":{"position":[[255,7]]},"129":{"position":[[1763,6],[2035,6],[2707,6]]},"130":{"position":[[288,6]]},"132":{"position":[[115,6],[131,7],[220,7]]},"160":{"position":[[1036,8]]},"172":{"position":[[111,7],[1600,7]]},"188":{"position":[[68,7],[168,6],[482,6],[664,6],[3652,6]]},"189":{"position":[[88,6],[134,6]]},"190":{"position":[[299,6],[741,7],[1052,7]]},"196":{"position":[[325,6]]}},"keywords":{}}],["python'",{"_index":3908,"title":{},"content":{"121":{"position":[[1704,8]]}},"keywords":{}}],["python,java",{"_index":5045,"title":{},"content":{"176":{"position":[[595,14]]}},"keywords":{}}],["python."",{"_index":5226,"title":{},"content":{"189":{"position":[[40,13]]}},"keywords":{}}],["q",{"_index":354,"title":{},"content":{"6":{"position":[[791,1],[927,1]]},"11":{"position":[[438,2]]},"12":{"position":[[396,2]]},"144":{"position":[[142,2]]},"145":{"position":[[118,2]]},"146":{"position":[[146,2]]}},"keywords":{}}],["q_format",{"_index":2854,"title":{},"content":{"88":{"position":[[744,8]]},"93":{"position":[[4159,8]]}},"keywords":{}}],["qadapt",{"_index":4411,"title":{"138":{"position":[[0,6]]}},"content":{"143":{"position":[[22,6],[121,6],[377,6],[531,6]]},"144":{"position":[[145,6],[154,7]]},"145":{"position":[[121,6],[130,7]]},"146":{"position":[[149,6],[158,7]]},"147":{"position":[[34,6]]},"148":{"position":[[157,6],[492,6]]}},"keywords":{}}],["qadapt::assert_no_alloc",{"_index":4457,"title":{},"content":{"145":{"position":[[46,24]]}},"keywords":{}}],["qadapt::enter_protect",{"_index":4464,"title":{},"content":{"146":{"position":[[46,24]]}},"keywords":{}}],["qadapt::exit_protect",{"_index":4465,"title":{},"content":{"146":{"position":[[75,23]]}},"keywords":{}}],["qadapt::no_alloc",{"_index":4448,"title":{},"content":{"144":{"position":[[77,17]]}},"keywords":{}}],["qadapt::qadapt",{"_index":4449,"title":{},"content":{"144":{"position":[[99,15]]},"145":{"position":[[75,15]]},"146":{"position":[[103,15]]}},"keywords":{}}],["qget",{"_index":1719,"title":{},"content":{"39":{"position":[[511,4]]}},"keywords":{}}],["qget(nam",{"_index":1744,"title":{},"content":{"39":{"position":[[2216,10]]}},"keywords":{}}],["qr−q",{"_index":332,"title":{},"content":{"6":{"position":[[448,4]]}},"keywords":{}}],["qualifi",{"_index":3139,"title":{},"content":{"91":{"position":[[3165,7]]},"92":{"position":[[977,7]]}},"keywords":{}}],["qualiti",{"_index":3439,"title":{},"content":{"98":{"position":[[389,8]]},"101":{"position":[[1115,8]]},"102":{"position":[[1220,8]]},"103":{"position":[[2009,7]]},"105":{"position":[[344,8]]},"106":{"position":[[401,8]]},"125":{"position":[[7010,7]]},"175":{"position":[[418,7]]}},"keywords":{}}],["quality"",{"_index":4079,"title":{},"content":{"125":{"position":[[3214,13]]}},"keywords":{}}],["quandl",{"_index":706,"title":{},"content":{"17":{"position":[[96,6]]},"23":{"position":[[189,6]]},"34":{"position":[[1017,6]]},"39":{"position":[[490,6]]},"88":{"position":[[487,6],[603,6]]},"93":{"position":[[3935,6],[4018,6],[4599,6]]}},"keywords":{}}],["quandl.get("goog/amex_iwm"",{"_index":1010,"title":{},"content":{"23":{"position":[[505,37]]}},"keywords":{}}],["quandl.get("goog/ams_dia"",{"_index":1008,"title":{},"content":{"23":{"position":[[438,36]]}},"keywords":{}}],["quandl.get("goog/epa_qqq"",{"_index":1011,"title":{},"content":{"23":{"position":[[575,36]]}},"keywords":{}}],["quandl.get("goog/nyse_spy"",{"_index":1005,"title":{},"content":{"23":{"position":[[370,37]]}},"keywords":{}}],["quandl.get('yahoo",{"_index":2856,"title":{},"content":{"88":{"position":[[780,19]]},"93":{"position":[[4195,19]]}},"keywords":{}}],["quandl.get('yahoo/{}'.format(tick",{"_index":722,"title":{},"content":{"17":{"position":[[266,36]]}},"keywords":{}}],["quandl.get(market_tick",{"_index":724,"title":{},"content":{"17":{"position":[[344,25]]}},"keywords":{}}],["quandl.notfounderror",{"_index":3289,"title":{},"content":{"93":{"position":[[5011,21],[5426,21]]}},"keywords":{}}],["quandl_key",{"_index":2842,"title":{},"content":{"88":{"position":[[271,10]]},"93":{"position":[[3820,10]]}},"keywords":{}}],["quandlget(nam",{"_index":1625,"title":{},"content":{"34":{"position":[[1655,15]]}},"keywords":{}}],["quantiti",{"_index":1559,"title":{},"content":{"32":{"position":[[2219,8]]},"49":{"position":[[465,8]]}},"keywords":{}}],["quarter",{"_index":2457,"title":{},"content":{"64":{"position":[[444,9],[710,9]]},"65":{"position":[[351,7],[587,8],[1373,8],[1553,8],[2051,8]]}},"keywords":{}}],["quarterhrdhr_dhrd",{"_index":2463,"title":{},"content":{"64":{"position":[[643,19]]},"65":{"position":[[529,19]]}},"keywords":{}}],["quarterli",{"_index":462,"title":{},"content":{"9":{"position":[[220,9],[311,9],[519,9]]}},"keywords":{}}],["quarterly_count",{"_index":2466,"title":{},"content":{"64":{"position":[[777,15],[978,15]]},"65":{"position":[[649,15]]}},"keywords":{}}],["quarters_left",{"_index":2522,"title":{},"content":{"65":{"position":[[1775,13],[1862,13]]}},"keywords":{}}],["queen",{"_index":2242,"title":{},"content":{"53":{"position":[[1010,5]]}},"keywords":{}}],["quest",{"_index":3942,"title":{},"content":{"122":{"position":[[546,5]]}},"keywords":{}}],["question",{"_index":19,"title":{"89":{"position":[[16,9]]}},"content":{"1":{"position":[[187,8]]},"32":{"position":[[345,8]]},"44":{"position":[[1190,8]]},"66":{"position":[[726,8]]},"68":{"position":[[10,8]]},"86":{"position":[[16,9]]},"89":{"position":[[374,8],[479,8]]},"93":{"position":[[960,9]]},"125":{"position":[[1557,8]]},"159":{"position":[[142,10]]},"176":{"position":[[751,10]]}},"keywords":{}}],["quick",{"_index":55,"title":{},"content":{"1":{"position":[[624,5]]},"51":{"position":[[3278,5]]},"90":{"position":[[4709,5]]},"108":{"position":[[322,5]]},"121":{"position":[[2465,5]]},"139":{"position":[[938,5]]},"161":{"position":[[473,5]]}},"keywords":{}}],["quickli",{"_index":1618,"title":{},"content":{"34":{"position":[[1398,8]]},"66":{"position":[[658,7]]},"73":{"position":[[653,7]]},"76":{"position":[[705,7]]},"83":{"position":[[215,8]]},"86":{"position":[[524,7],[543,7],[873,7]]},"110":{"position":[[570,7]]},"122":{"position":[[594,7]]},"125":{"position":[[2491,8],[3696,7]]},"132":{"position":[[798,8]]}},"keywords":{}}],["quirk",{"_index":3905,"title":{},"content":{"121":{"position":[[1622,6]]}},"keywords":{}}],["quirki",{"_index":4336,"title":{},"content":{"130":{"position":[[431,6]]}},"keywords":{}}],["quit",{"_index":1184,"title":{},"content":{"26":{"position":[[837,5]]},"121":{"position":[[1437,5]]}},"keywords":{}}],["quiz",{"_index":2233,"title":{},"content":{"53":{"position":[[885,4]]}},"keywords":{}}],["quot",{"_index":1088,"title":{},"content":{"24":{"position":[[2335,7]]},"96":{"position":[[1201,6],[1739,7],[2285,9]]},"163":{"position":[[221,6]]},"179":{"position":[[644,11],[724,11],[1042,11],[1143,11]]},"184":{"position":[[355,11],[704,11]]}},"keywords":{}}],["quot;$app_dir"",{"_index":4117,"title":{},"content":{"125":{"position":[[5337,20],[5885,20]]}},"keywords":{}}],["quot;$app_dir/app_loader.js"",{"_index":4122,"title":{},"content":{"125":{"position":[[5545,34],[6006,34]]}},"keywords":{}}],["quot;$app_dir/bundle.js"",{"_index":4124,"title":{},"content":{"125":{"position":[[5583,30],[5666,30],[6044,30]]}},"keywords":{}}],["quot;$dir/node_modules/webpack",{"_index":4120,"title":{},"content":{"125":{"position":[[5473,31],[5935,31]]}},"keywords":{}}],["quot;$wasm_dir/debug/$wasm_name.wasm"",{"_index":4115,"title":{},"content":{"125":{"position":[[5283,43],[5831,43]]}},"keywords":{}}],["quot;<stdin>"",{"_index":4330,"title":{},"content":{"129":{"position":[[2471,26]]}},"keywords":{}}],["quot;"",{"_index":1602,"title":{},"content":{"34":{"position":[[1034,12]]}},"keywords":{}}],["quot;""given",{"_index":884,"title":{},"content":{"22":{"position":[[180,23]]}},"keywords":{}}],["quot;.format(c",{"_index":1487,"title":{},"content":{"30":{"position":[[9735,21]]}},"keywords":{}}],["quot;.format(datetime.now().strftime("%i:%m:%",{"_index":1496,"title":{},"content":{"30":{"position":[[9987,54]]}},"keywords":{}}],["quot;.format(end",{"_index":2037,"title":{},"content":{"46":{"position":[[635,19]]}},"keywords":{}}],["quot;.format(four_year_period",{"_index":2510,"title":{},"content":{"65":{"position":[[976,35]]}},"keywords":{}}],["quot;.format(heartbeats_until_2016",{"_index":2491,"title":{},"content":{"64":{"position":[[1772,39]]}},"keywords":{}}],["quot;.format(hr_df_full.index[0",{"_index":2437,"title":{},"content":{"62":{"position":[[1517,36]]}},"keywords":{}}],["quot;.format(len(i",{"_index":1939,"title":{},"content":{"44":{"position":[[1416,22]]}},"keywords":{}}],["quot;.format(list(zip(tick",{"_index":849,"title":{},"content":{"20":{"position":[[2366,33]]}},"keywords":{}}],["quot;.format(naive_guess",{"_index":1944,"title":{},"content":{"44":{"position":[[1535,29]]}},"keywords":{}}],["quot;.format(quarters_left",{"_index":2525,"title":{},"content":{"65":{"position":[[1938,31]]}},"keywords":{}}],["quot;.format(remaining_2016",{"_index":2493,"title":{},"content":{"64":{"position":[[1846,32]]}},"keywords":{}}],["quot;.format(remaining_4i",{"_index":2511,"title":{},"content":{"65":{"position":[[1067,30]]}},"keywords":{}}],["quot;.format(remaining_year",{"_index":2526,"title":{},"content":{"65":{"position":[[2015,32]]}},"keywords":{}}],["quot;.format(request.uri",{"_index":3326,"title":{},"content":{"96":{"position":[[517,28]]}},"keywords":{}}],["quot;.format(tick",{"_index":3220,"title":{},"content":{"93":{"position":[[2319,24]]}},"keywords":{}}],["quot;/home/bspeice/.virtualenvs/releas",{"_index":5209,"title":{},"content":{"188":{"position":[[3754,40]]}},"keywords":{}}],["quot;/point_capnp.rs"",{"_index":3737,"title":{},"content":{"113":{"position":[[693,30]]}},"keywords":{}}],["quot;/usr/lib/python3.7/threading.py"",{"_index":5213,"title":{},"content":{"188":{"position":[[3884,44],[3963,44]]}},"keywords":{}}],["quot;0.1.0"",{"_index":3686,"title":{},"content":{"109":{"position":[[296,17]]}},"keywords":{}}],["quot;0.8"",{"_index":3691,"title":{},"content":{"109":{"position":[[407,15],[450,15]]}},"keywords":{}}],["quot;1000"",{"_index":5103,"title":{},"content":{"181":{"position":[[508,16]]}},"keywords":{}}],["quot;adjust",{"_index":1751,"title":{},"content":{"39":{"position":[[2342,14],[2408,14]]}},"keywords":{}}],["quot;alway",{"_index":1950,"title":{},"content":{"44":{"position":[[1712,12]]}},"keywords":{}}],["quot;appl",{"_index":4157,"title":{},"content":{"125":{"position":[[8230,17]]}},"keywords":{}}],["quot;author_articles_wrapper"",{"_index":892,"title":{},"content":{"22":{"position":[[373,36]]}},"keywords":{}}],["quot;binding"",{"_index":4302,"title":{},"content":{"129":{"position":[[1669,19]]}},"keywords":{}}],["quot;bit",{"_index":4731,"title":{},"content":{"161":{"position":[[367,11]]}},"keywords":{}}],["quot;boilerplate"",{"_index":4215,"title":{},"content":{"125":{"position":[[11502,23]]}},"keywords":{}}],["quot;bradle",{"_index":3687,"title":{},"content":{"109":{"position":[[324,14]]}},"keywords":{}}],["quot;brok",{"_index":3508,"title":{},"content":{"103":{"position":[[278,11]]}},"keywords":{}}],["quot;build",{"_index":224,"title":{},"content":{"4":{"position":[[66,11]]}},"keywords":{}}],["quot;builder"",{"_index":4804,"title":{},"content":{"164":{"position":[[319,19]]}},"keywords":{}}],["quot;bundl",{"_index":226,"title":{},"content":{"4":{"position":[[96,12]]}},"keywords":{}}],["quot;busi",{"_index":5159,"title":{},"content":{"188":{"position":[[751,10]]}},"keywords":{}}],["quot;canon",{"_index":3936,"title":{},"content":{"122":{"position":[[200,15],[1051,15]]}},"keywords":{}}],["quot;capnp_cookbook_1"",{"_index":3685,"title":{},"content":{"109":{"position":[[257,28]]}},"keywords":{}}],["quot;close"",{"_index":1755,"title":{},"content":{"39":{"position":[[2456,17]]}},"keywords":{}}],["quot;cloudy"",{"_index":1351,"title":{},"content":{"30":{"position":[[1112,18]]}},"keywords":{}}],["quot;compil",{"_index":24,"title":{},"content":{"1":{"position":[[258,13]]},"189":{"position":[[25,14]]}},"keywords":{}}],["quot;component"",{"_index":3553,"title":{},"content":{"104":{"position":[[210,21]]}},"keywords":{}}],["quot;components."",{"_index":3552,"title":{},"content":{"104":{"position":[[172,23]]}},"keywords":{}}],["quot;concaten",{"_index":3341,"title":{},"content":{"96":{"position":[[1386,17]]}},"keywords":{}}],["quot;crude"",{"_index":1076,"title":{},"content":{"24":{"position":[[1893,19]]},"25":{"position":[[1617,19]]}},"keywords":{}}],["quot;data",{"_index":4502,"title":{},"content":{"150":{"position":[[767,10]]}},"keywords":{}}],["quot;debug"",{"_index":4705,"title":{},"content":{"160":{"position":[[3546,17]]}},"keywords":{}}],["quot;devops"",{"_index":4492,"title":{},"content":{"150":{"position":[[218,19]]}},"keywords":{}}],["quot;djia"",{"_index":1073,"title":{},"content":{"24":{"position":[[1696,17],[1827,17]]},"25":{"position":[[1417,17],[1551,17]]}},"keywords":{}}],["quot;dow"",{"_index":1078,"title":{},"content":{"24":{"position":[[1931,16]]},"25":{"position":[[1655,16]]}},"keywords":{}}],["quot;extern",{"_index":4183,"title":{},"content":{"125":{"position":[[9404,12]]}},"keywords":{}}],["quot;foreach"",{"_index":5375,"title":{},"content":{"199":{"position":[[334,19]]}},"keywords":{}}],["quot;forward"",{"_index":5032,"title":{},"content":{"175":{"position":[[1436,19]]}},"keywords":{}}],["quot;fun",{"_index":4355,"title":{},"content":{"132":{"position":[[852,9]]}},"keywords":{}}],["quot;futur",{"_index":953,"title":{},"content":{"22":{"position":[[1790,13]]}},"keywords":{}}],["quot;garden",{"_index":4724,"title":{},"content":{"161":{"position":[[27,15]]}},"keywords":{}}],["quot;get",{"_index":199,"title":{},"content":{"3":{"position":[[1216,13]]}},"keywords":{}}],["quot;give"",{"_index":5273,"title":{},"content":{"193":{"position":[[144,16]]}},"keywords":{}}],["quot;given",{"_index":925,"title":{},"content":{"22":{"position":[[1127,11]]}},"keywords":{}}],["quot;global"",{"_index":5110,"title":{},"content":{"182":{"position":[[332,18]]}},"keywords":{}}],["quot;gold"",{"_index":1077,"title":{},"content":{"24":{"position":[[1913,17]]},"25":{"position":[[1637,17]]}},"keywords":{}}],["quot;good",{"_index":3575,"title":{},"content":{"105":{"position":[[227,10]]}},"keywords":{}}],["quot;gotcha"",{"_index":4565,"title":{},"content":{"155":{"position":[[754,19]]}},"keywords":{}}],["quot;heap"",{"_index":4912,"title":{},"content":{"172":{"position":[[763,16]]}},"keywords":{}}],["quot;hey",{"_index":3978,"title":{},"content":{"123":{"position":[[618,10]]}},"keywords":{}}],["quot;high",{"_index":3567,"title":{},"content":{"104":{"position":[[1174,10]]},"125":{"position":[[3203,10]]},"176":{"position":[[900,10]]}},"keywords":{}}],["quot;hold",{"_index":863,"title":{},"content":{"20":{"position":[[2811,15]]}},"keywords":{}}],["quot;http://seekingalpha.com"",{"_index":965,"title":{},"content":{"22":{"position":[[2353,35]]}},"keywords":{}}],["quot;http://seekingalpha.com/author/wal",{"_index":902,"title":{},"content":{"22":{"position":[[607,41]]}},"keywords":{}}],["quot;https://api.forecast.io/forecast/"",{"_index":1469,"title":{},"content":{"30":{"position":[[8806,45]]}},"keywords":{}}],["quot;i",{"_index":3405,"title":{},"content":{"97":{"position":[[3847,8]]},"132":{"position":[[887,7]]}},"keywords":{}}],["quot;id"",{"_index":891,"title":{},"content":{"22":{"position":[[356,16]]}},"keywords":{}}],["quot;if",{"_index":4058,"title":{},"content":{"125":{"position":[[2101,8]]}},"keywords":{}}],["quot;improve"",{"_index":1960,"title":{},"content":{"45":{"position":[[144,19]]}},"keywords":{}}],["quot;index"",{"_index":3409,"title":{},"content":{"97":{"position":[[3919,19],[4481,19],[4917,19],[6428,19]]}},"keywords":{}}],["quot;information"",{"_index":1968,"title":{},"content":{"45":{"position":[[443,23]]}},"keywords":{}}],["quot;it'",{"_index":4081,"title":{},"content":{"125":{"position":[[3451,10]]}},"keywords":{}}],["quot;just",{"_index":295,"title":{},"content":{"4":{"position":[[1459,10]]},"125":{"position":[[7080,10]]}},"keywords":{}}],["quot;knew"",{"_index":2900,"title":{},"content":{"88":{"position":[[2236,16]]}},"keywords":{}}],["quot;likelihood"",{"_index":2655,"title":{},"content":{"74":{"position":[[1556,22]]}},"keywords":{}}],["quot;link"",{"_index":4087,"title":{},"content":{"125":{"position":[[3751,16]]}},"keywords":{}}],["quot;look",{"_index":3865,"title":{},"content":{"120":{"position":[[987,11]]}},"keywords":{}}],["quot;low",{"_index":3554,"title":{},"content":{"104":{"position":[[349,9]]}},"keywords":{}}],["quot;maintenance"",{"_index":3966,"title":{},"content":{"123":{"position":[[20,23]]}},"keywords":{}}],["quot;memory"",{"_index":666,"title":{},"content":{"15":{"position":[[106,18]]}},"keywords":{}}],["quot;miss",{"_index":4164,"title":{},"content":{"125":{"position":[[8418,13]]}},"keywords":{}}],["quot;modern",{"_index":69,"title":{},"content":{"1":{"position":[[763,12]]}},"keywords":{}}],["quot;modules,"",{"_index":112,"title":{},"content":{"2":{"position":[[570,20]]}},"keywords":{}}],["quot;months"",{"_index":423,"title":{},"content":{"7":{"position":[[904,18]]}},"keywords":{}}],["quot;most",{"_index":3558,"title":{},"content":{"104":{"position":[[637,10]]}},"keywords":{}}],["quot;mov",{"_index":4212,"title":{},"content":{"125":{"position":[[11451,10]]}},"keywords":{}}],["quot;nasdaq"",{"_index":1075,"title":{},"content":{"24":{"position":[[1762,19],[1863,19],[1948,19]]},"25":{"position":[[1485,19],[1587,19],[1672,19]]}},"keywords":{}}],["quot;new",{"_index":3493,"title":{},"content":{"102":{"position":[[585,9]]}},"keywords":{}}],["quot;next",{"_index":1971,"title":{},"content":{"45":{"position":[[646,10]]}},"keywords":{}}],["quot;noisy"",{"_index":3565,"title":{},"content":{"104":{"position":[[1079,17]]}},"keywords":{}}],["quot;ops"",{"_index":4491,"title":{},"content":{"150":{"position":[[194,15]]}},"keywords":{}}],["quot;optimize"",{"_index":2662,"title":{},"content":{"75":{"position":[[274,20]]}},"keywords":{}}],["quot;owned"",{"_index":3798,"title":{},"content":{"116":{"position":[[92,17]]}},"keywords":{}}],["quot;packed"",{"_index":4811,"title":{},"content":{"164":{"position":[[841,18],[926,18]]}},"keywords":{}}],["quot;pars",{"_index":4766,"title":{},"content":{"163":{"position":[[636,12]]}},"keywords":{}}],["quot;pca",{"_index":3614,"title":{},"content":{"105":{"position":[[1844,9]]}},"keywords":{}}],["quot;pca"",{"_index":3613,"title":{},"content":{"105":{"position":[[1827,16]]}},"keywords":{}}],["quot;point"",{"_index":3720,"title":{},"content":{"112":{"position":[[1169,17]]}},"keywords":{}}],["quot;primitive"",{"_index":4248,"title":{},"content":{"128":{"position":[[189,21]]}},"keywords":{}}],["quot;prior"",{"_index":2054,"title":{},"content":{"49":{"position":[[119,17]]}},"keywords":{}}],["quot;proposed"",{"_index":2663,"title":{},"content":{"75":{"position":[[399,20]]}},"keywords":{}}],["quot;raini",{"_index":1414,"title":{},"content":{"30":{"position":[[5907,11]]}},"keywords":{}}],["quot;raw"",{"_index":3612,"title":{},"content":{"105":{"position":[[1809,17]]}},"keywords":{}}],["quot;read",{"_index":5062,"title":{},"content":{"179":{"position":[[36,10]]}},"keywords":{}}],["quot;real",{"_index":4685,"title":{},"content":{"160":{"position":[[2134,10]]}},"keywords":{}}],["quot;realized"",{"_index":5090,"title":{},"content":{"180":{"position":[[170,20]]}},"keywords":{}}],["quot;russ"",{"_index":1074,"title":{},"content":{"24":{"position":[[1729,17],[1845,17]]},"25":{"position":[[1451,17],[1569,17]]}},"keywords":{}}],["quot;rust",{"_index":3897,"title":{},"content":{"121":{"position":[[1350,10]]}},"keywords":{}}],["quot;rvalues"",{"_index":5088,"title":{},"content":{"179":{"position":[[1667,20]]}},"keywords":{}}],["quot;s&p"",{"_index":1079,"title":{},"content":{"24":{"position":[[1968,20]]},"25":{"position":[[1692,20]]}},"keywords":{}}],["quot;safe"",{"_index":4702,"title":{},"content":{"160":{"position":[[3421,16]]}},"keywords":{}}],["quot;saturday"",{"_index":3027,"title":{},"content":{"90":{"position":[[3558,20]]}},"keywords":{}}],["quot;scale"",{"_index":78,"title":{},"content":{"2":{"position":[[53,17]]}},"keywords":{}}],["quot;slow,"",{"_index":4418,"title":{},"content":{"139":{"position":[[338,17]]}},"keywords":{}}],["quot;smart",{"_index":4557,"title":{},"content":{"155":{"position":[[33,11]]}},"keywords":{}}],["quot;spy"",{"_index":1072,"title":{},"content":{"24":{"position":[[1664,17],[1809,17]]},"25":{"position":[[1384,17],[1533,17]]}},"keywords":{}}],["quot;stack."",{"_index":4674,"title":{},"content":{"160":{"position":[[1288,18]]}},"keywords":{}}],["quot;stop",{"_index":4911,"title":{},"content":{"172":{"position":[[617,10]]}},"keywords":{}}],["quot;stor",{"_index":5027,"title":{},"content":{"175":{"position":[[1126,11]]}},"keywords":{}}],["quot;store"",{"_index":5031,"title":{},"content":{"175":{"position":[[1371,17]]}},"keywords":{}}],["quot;stored"",{"_index":5104,"title":{},"content":{"181":{"position":[[540,18]]}},"keywords":{}}],["quot;tabulasa.wav"",{"_index":3511,"title":{},"content":{"103":{"position":[[328,24]]}},"keywords":{}}],["quot;th",{"_index":4729,"title":{},"content":{"161":{"position":[[333,9]]},"198":{"position":[[602,9]]}},"keywords":{}}],["quot;trend",{"_index":3073,"title":{},"content":{"91":{"position":[[197,14]]}},"keywords":{}}],["quot;typ",{"_index":237,"title":{},"content":{"4":{"position":[[354,11]]}},"keywords":{}}],["quot;union"",{"_index":4895,"title":{},"content":{"170":{"position":[[90,17]]}},"keywords":{}}],["quot;unlimit",{"_index":1512,"title":{},"content":{"32":{"position":[[66,15]]}},"keywords":{}}],["quot;unpacked"",{"_index":4813,"title":{},"content":{"164":{"position":[[883,20]]}},"keywords":{}}],["quot;us",{"_index":3452,"title":{},"content":{"98":{"position":[[982,9]]}},"keywords":{}}],["quot;value"",{"_index":5057,"title":{},"content":{"178":{"position":[[68,17]]}},"keywords":{}}],["quot;wal",{"_index":5194,"title":{},"content":{"188":{"position":[[2728,10]]}},"keywords":{}}],["quot;webpack",{"_index":271,"title":{},"content":{"4":{"position":[[941,13]]}},"keywords":{}}],["quot;webpack"",{"_index":4016,"title":{},"content":{"125":{"position":[[460,19]]}},"keywords":{}}],["quot;wget/1.13.4"",{"_index":919,"title":{},"content":{"22":{"position":[[962,25],[2460,25]]}},"keywords":{}}],["quot;what",{"_index":4348,"title":{},"content":{"132":{"position":[[459,10]]}},"keywords":{}}],["quot;whi",{"_index":3946,"title":{},"content":{"122":{"position":[[864,9]]}},"keywords":{}}],["quot;yahoo/aapl"",{"_index":1787,"title":{},"content":{"40":{"position":[[158,23]]}},"keywords":{}}],["quot;yahoo/cat"",{"_index":1816,"title":{},"content":{"40":{"position":[[1691,22]]}},"keywords":{}}],["quot;yahoo/goog"",{"_index":1789,"title":{},"content":{"40":{"position":[[206,24],[1738,24]]}},"keywords":{}}],["quot;yahoo/nflx"",{"_index":1788,"title":{},"content":{"40":{"position":[[182,23],[1714,23]]}},"keywords":{}}],["quot;years"",{"_index":421,"title":{},"content":{"7":{"position":[[853,17]]}},"keywords":{}}],["quot;yes/no"",{"_index":4627,"title":{},"content":{"159":{"position":[[123,18]]}},"keywords":{}}],["quot;you",{"_index":3332,"title":{},"content":{"96":{"position":[[757,9],[1176,9]]}},"keywords":{}}],["quot;you'r",{"_index":3325,"title":{},"content":{"96":{"position":[[494,12]]}},"keywords":{}}],["r",{"_index":3381,"title":{},"content":{"97":{"position":[[1877,3]]}},"keywords":{}}],["r>",{"_index":3382,"title":{},"content":{"97":{"position":[[1881,6],[1934,7]]}},"keywords":{}}],["r').read",{"_index":3108,"title":{},"content":{"91":{"position":[[1962,11]]},"93":{"position":[[4375,11]]}},"keywords":{}}],["r3000",{"_index":3246,"title":{},"content":{"93":{"position":[[2999,5]]}},"keywords":{}}],["r3000['exchang",{"_index":3254,"title":{},"content":{"93":{"position":[[3240,18]]}},"keywords":{}}],["r3000[(r3000['exchang",{"_index":3253,"title":{},"content":{"93":{"position":[[3200,24]]}},"keywords":{}}],["r3000_equiti",{"_index":3252,"title":{},"content":{"93":{"position":[[3183,14]]}},"keywords":{}}],["r3000_equities.index",{"_index":3264,"title":{},"content":{"93":{"position":[[3478,21]]}},"keywords":{}}],["r3000_equities.ix[t]['tick",{"_index":3263,"title":{},"content":{"93":{"position":[[3434,32]]}},"keywords":{}}],["r_m",{"_index":737,"title":{},"content":{"19":{"position":[[19,3]]}},"keywords":{}}],["rack",{"_index":4750,"title":{},"content":{"161":{"position":[[1144,4]]}},"keywords":{}}],["radio",{"_index":5010,"title":{},"content":{"175":{"position":[[449,6]]}},"keywords":{}}],["rain",{"_index":1309,"title":{},"content":{"28":{"position":[[4285,4]]},"30":{"position":[[435,7],[4597,4],[5963,4]]}},"keywords":{}}],["rain/cloud",{"_index":1441,"title":{},"content":{"30":{"position":[[8010,10]]}},"keywords":{}}],["rainfal",{"_index":1294,"title":{},"content":{"28":{"position":[[2861,8]]}},"keywords":{}}],["raini",{"_index":1339,"title":{},"content":{"30":{"position":[[592,5],[5749,5],[5845,5],[6646,5],[6851,5],[7097,6],[7151,5],[7685,5]]}},"keywords":{}}],["rais",{"_index":1515,"title":{},"content":{"32":{"position":[[113,7]]}},"keywords":{}}],["ran",{"_index":2617,"title":{},"content":{"72":{"position":[[438,3]]},"125":{"position":[[4122,3]]},"146":{"position":[[421,3]]}},"keywords":{}}],["randn(m",{"_index":401,"title":{},"content":{"7":{"position":[[498,9]]}},"keywords":{}}],["random",{"_index":1708,"title":{},"content":{"39":{"position":[[170,6]]},"51":{"position":[[3024,6]]},"53":{"position":[[52,6]]},"75":{"position":[[140,6]]},"76":{"position":[[904,6]]},"90":{"position":[[4013,6]]}},"keywords":{}}],["randomli",{"_index":2134,"title":{},"content":{"51":{"position":[[2838,8]]},"76":{"position":[[1052,8],[3127,8]]}},"keywords":{}}],["rang",{"_index":2399,"title":{},"content":{"62":{"position":[[292,5]]},"104":{"position":[[1777,5]]}},"keywords":{}}],["range(0",{"_index":1137,"title":{},"content":{"25":{"position":[[294,8]]},"28":{"position":[[1077,8]]},"30":{"position":[[2152,8],[3638,8],[3857,8],[5411,8],[6711,8],[6936,8]]},"44":{"position":[[677,8]]},"53":{"position":[[136,8]]}},"keywords":{}}],["range(1",{"_index":1029,"title":{},"content":{"24":{"position":[[569,8]]},"90":{"position":[[4110,8]]}},"keywords":{}}],["range(1990",{"_index":1255,"title":{},"content":{"28":{"position":[[1768,11]]},"30":{"position":[[1354,11]]}},"keywords":{}}],["range(1990,2016",{"_index":1474,"title":{},"content":{"30":{"position":[[9071,16]]}},"keywords":{}}],["range(2",{"_index":907,"title":{},"content":{"22":{"position":[[751,8]]},"188":{"position":[[1105,8]]},"189":{"position":[[1167,8],[1437,8]]}},"keywords":{}}],["range(7",{"_index":1355,"title":{},"content":{"30":{"position":[[1381,8]]}},"keywords":{}}],["range_begin",{"_index":2994,"title":{},"content":{"90":{"position":[[1340,11],[2695,11]]}},"keywords":{}}],["range_end",{"_index":2995,"title":{},"content":{"90":{"position":[[1364,9],[1421,11],[1473,11],[1523,11],[1672,11],[1898,11],[2719,9],[2771,11],[2816,11],[3037,11]]}},"keywords":{}}],["rap",{"_index":2286,"title":{},"content":{"53":{"position":[[2171,3]]}},"keywords":{}}],["raph",{"_index":4642,"title":{},"content":{"159":{"position":[[1254,4]]}},"keywords":{}}],["rare",{"_index":4342,"title":{},"content":{"132":{"position":[[183,6]]}},"keywords":{}}],["rate",{"_index":461,"title":{},"content":{"9":{"position":[[207,4],[239,5],[329,4],[537,5],[691,4]]},"10":{"position":[[397,5]]},"11":{"position":[[234,5]]},"13":{"position":[[385,4]]},"62":{"position":[[99,4],[1725,4]]},"66":{"position":[[144,4]]},"93":{"position":[[4606,4]]}},"keywords":{}}],["rate=sampler",{"_index":3519,"title":{},"content":{"103":{"position":[[682,16],[1827,16],[2144,16]]},"105":{"position":[[2781,16],[2979,16],[3254,16]]}},"keywords":{}}],["rates)σ\\sigma",{"_index":338,"title":{},"content":{"6":{"position":[[517,14]]}},"keywords":{}}],["rates/pages/textview.aspx?data=yield",{"_index":494,"title":{},"content":{"10":{"position":[[274,36]]}},"keywords":{}}],["ratio",{"_index":735,"title":{"19":{"position":[[23,6]]}},"content":{"105":{"position":[[3068,5]]}},"keywords":{}}],["raw",{"_index":2834,"title":{},"content":{"86":{"position":[[1079,3]]},"105":{"position":[[1948,3]]},"167":{"position":[[140,3]]}},"keywords":{}}],["raw_estimate(transform",{"_index":3581,"title":{},"content":{"105":{"position":[[497,25],[1484,25]]}},"keywords":{}}],["raw_pca_estim",{"_index":3604,"title":{},"content":{"105":{"position":[[1465,16],[1624,17]]}},"keywords":{}}],["raw_siz",{"_index":3606,"title":{},"content":{"105":{"position":[[1565,8],[1614,9]]}},"keywords":{}}],["rax",{"_index":4271,"title":{},"content":{"128":{"position":[[1286,3],[1496,3]]},"129":{"position":[[556,4],[591,3]]},"193":{"position":[[1572,5]]}},"keywords":{}}],["ray",{"_index":5268,"title":{},"content":{"192":{"position":[[423,6],[523,3]]}},"keywords":{}}],["rb",{"_index":1228,"title":{},"content":{"28":{"position":[[918,6]]},"30":{"position":[[1250,6]]}},"keywords":{}}],["rbp",{"_index":4256,"title":{},"content":{"128":{"position":[[452,3],[460,4],[533,4],[646,4],[764,3],[772,4],[880,4],[901,3]]}},"keywords":{}}],["rc",{"_index":4637,"title":{},"content":{"159":{"position":[[984,3]]}},"keywords":{}}],["rc::new(0",{"_index":4583,"title":{},"content":{"155":{"position":[[1449,11]]}},"keywords":{}}],["rdi",{"_index":4283,"title":{},"content":{"129":{"position":[[543,4],[680,4]]},"193":{"position":[[1262,5]]}},"keywords":{}}],["re",{"_index":638,"title":{"94":{"position":[[9,2]]}},"content":{"14":{"position":[[1185,2]]},"25":{"position":[[95,2]]},"55":{"position":[[24,2]]},"88":{"position":[[976,2]]},"93":{"position":[[1364,2]]},"111":{"position":[[635,2]]},"136":{"position":[[369,3],[708,2],[858,2]]},"164":{"position":[[447,2],[578,2]]},"189":{"position":[[354,2]]}},"keywords":{}}],["re.match(r'\\d+/\\d+/\\d",{"_index":3208,"title":{},"content":{"93":{"position":[[1772,24]]}},"keywords":{}}],["reach",{"_index":242,"title":{},"content":{"4":{"position":[[440,5]]},"13":{"position":[[905,7]]},"14":{"position":[[1923,7]]},"15":{"position":[[1591,7]]},"52":{"position":[[688,7]]},"76":{"position":[[2338,5]]},"172":{"position":[[175,7]]}},"keywords":{}}],["react",{"_index":28,"title":{},"content":{"1":{"position":[[320,5]]},"3":{"position":[[365,5],[401,5]]},"4":{"position":[[39,5]]},"91":{"position":[[4891,6]]},"93":{"position":[[566,6]]},"125":{"position":[[963,5],[11586,5]]},"176":{"position":[[1079,5]]}},"keywords":{}}],["reaction",{"_index":3172,"title":{},"content":{"91":{"position":[[5476,8]]}},"keywords":{}}],["read",{"_index":1709,"title":{"55":{"position":[[12,8]]},"135":{"position":[[0,7]]},"179":{"position":[[0,4]]}},"content":{"39":{"position":[[195,4]]},"91":{"position":[[1740,4]]},"104":{"position":[[58,4]]},"128":{"position":[[41,7]]},"160":{"position":[[2202,7],[3994,4]]},"163":{"position":[[143,4],[384,4]]},"164":{"position":[[613,7],[749,7],[918,7],[1400,4]]},"165":{"position":[[1152,7]]},"166":{"position":[[188,4]]},"169":{"position":[[65,4]]},"173":{"position":[[955,7]]},"178":{"position":[[563,4]]},"182":{"position":[[553,4]]},"185":{"position":[[332,5]]},"193":{"position":[[1317,4]]}},"keywords":{}}],["readabl",{"_index":3929,"title":{},"content":{"121":{"position":[[2738,9]]}},"keywords":{}}],["reader",{"_index":3723,"title":{"116":{"position":[[19,6]]}},"content":{"112":{"position":[[1292,6],[1432,7],[1580,6]]},"113":{"position":[[1947,7]]},"116":{"position":[[609,6],[3117,6],[3163,6]]},"117":{"position":[[260,6]]}},"keywords":{}}],["readi",{"_index":4744,"title":{},"content":{"161":{"position":[[934,6]]},"193":{"position":[[1699,5]]}},"keywords":{}}],["real",{"_index":497,"title":{},"content":{"10":{"position":[[374,4]]},"11":{"position":[[78,4]]}},"keywords":{}}],["real_drop_in_plac",{"_index":4597,"title":{},"content":{"156":{"position":[[602,19]]},"199":{"position":[[1200,20]]}},"keywords":{}}],["realist",{"_index":1510,"title":{"105":{"position":[[7,9]]}},"content":{"32":{"position":[[15,9]]},"105":{"position":[[2876,10]]},"190":{"position":[[114,9]]}},"keywords":{}}],["realiti",{"_index":1344,"title":{},"content":{"30":{"position":[[755,8]]}},"keywords":{}}],["realiz",{"_index":2832,"title":{},"content":{"86":{"position":[[836,8]]},"120":{"position":[[590,7]]},"175":{"position":[[346,8]]}},"keywords":{}}],["realli",{"_index":1284,"title":{"149":{"position":[[21,6]]}},"content":{"28":{"position":[[2483,6],[2510,6]]},"40":{"position":[[3680,6]]},"41":{"position":[[12,6]]},"50":{"position":[[46,6]]},"53":{"position":[[438,6]]},"61":{"position":[[510,6],[555,6],[2031,6]]},"73":{"position":[[9,6]]},"88":{"position":[[154,6]]},"91":{"position":[[4591,6]]},"96":{"position":[[1568,6]]},"97":{"position":[[214,6],[3145,6],[4191,6]]},"101":{"position":[[193,6]]},"106":{"position":[[200,6],[988,6]]},"113":{"position":[[2065,6]]},"115":{"position":[[874,6],[3074,6]]},"117":{"position":[[531,6]]},"121":{"position":[[2397,6]]},"125":{"position":[[67,6],[893,6],[1219,6],[1635,7],[3186,6]]},"127":{"position":[[1132,6]]},"128":{"position":[[916,6]]},"129":{"position":[[289,6]]},"130":{"position":[[129,6]]},"132":{"position":[[575,6]]},"163":{"position":[[2233,6]]}},"keywords":{}}],["reallygarbag",{"_index":4670,"title":{},"content":{"160":{"position":[[1057,13]]}},"keywords":{}}],["realtalk",{"_index":2216,"title":{},"content":{"53":{"position":[[518,9]]}},"keywords":{}}],["reason",{"_index":1697,"title":{},"content":{"38":{"position":[[741,6]]},"85":{"position":[[149,10]]},"116":{"position":[[2661,8]]},"117":{"position":[[108,8]]},"120":{"position":[[976,10]]},"127":{"position":[[5,6]]},"139":{"position":[[94,7]]},"152":{"position":[[44,6]]},"160":{"position":[[1119,6],[2616,7],[3251,7]]},"175":{"position":[[20,6]]},"195":{"position":[[1043,10]]}},"keywords":{}}],["reasonable:if",{"_index":5357,"title":{},"content":{"198":{"position":[[230,13]]}},"keywords":{}}],["receiv",{"_index":633,"title":{},"content":{"14":{"position":[[775,7],[924,7],[1009,7],[1112,7]]},"123":{"position":[[557,7]]},"125":{"position":[[840,9]]},"136":{"position":[[621,8]]},"189":{"position":[[1242,7]]}},"keywords":{}}],["recent",{"_index":158,"title":{},"content":{"3":{"position":[[485,6]]},"30":{"position":[[60,6],[443,9],[603,8]]},"88":{"position":[[3,8]]},"125":{"position":[[1576,6]]},"161":{"position":[[7,8],[522,8]]},"163":{"position":[[467,8]]},"165":{"position":[[93,8]]},"172":{"position":[[558,6]]},"188":{"position":[[3729,6]]}},"keywords":{}}],["recip",{"_index":4745,"title":{},"content":{"161":{"position":[[950,6]]}},"keywords":{}}],["reclaim",{"_index":4574,"title":{},"content":{"155":{"position":[[1207,10]]}},"keywords":{}}],["recogn",{"_index":2784,"title":{},"content":{"81":{"position":[[70,9]]}},"keywords":{}}],["recommend",{"_index":120,"title":{},"content":{"2":{"position":[[689,15]]},"3":{"position":[[84,15]]},"97":{"position":[[4400,11]]},"125":{"position":[[3536,12],[7481,9],[10675,9]]}},"keywords":{}}],["recompil",{"_index":4022,"title":{},"content":{"125":{"position":[[649,9]]}},"keywords":{}}],["recon",{"_index":3603,"title":{},"content":{"105":{"position":[[1405,5]]}},"keywords":{}}],["reconcil",{"_index":4009,"title":{},"content":{"125":{"position":[[182,9]]}},"keywords":{}}],["reconstruct",{"_index":3535,"title":{},"content":{"103":{"position":[[1386,13],[1485,13],[1736,13],[2055,13],[2184,13]]},"104":{"position":[[291,11],[971,11]]},"105":{"position":[[2693,13],[2894,13],[3166,13]]},"106":{"position":[[630,11]]}},"keywords":{}}],["record",{"_index":1021,"title":{},"content":{"24":{"position":[[380,8]]},"26":{"position":[[167,8]]},"30":{"position":[[4323,8],[7255,7]]},"43":{"position":[[359,6]]},"62":{"position":[[889,7],[1186,6]]},"93":{"position":[[1887,6]]},"133":{"position":[[117,6]]},"155":{"position":[[1016,8]]},"176":{"position":[[676,6]]},"179":{"position":[[1447,6]]}},"keywords":{}}],["record['act",{"_index":2416,"title":{},"content":{"62":{"position":[[920,18]]}},"keywords":{}}],["record_font_tag",{"_index":927,"title":{},"content":{"22":{"position":[[1193,16]]}},"keywords":{}}],["record_to_df(record",{"_index":2415,"title":{},"content":{"62":{"position":[[838,21]]}},"keywords":{}}],["record_to_df(record.json",{"_index":2426,"title":{},"content":{"62":{"position":[[1153,28]]}},"keywords":{}}],["recov",{"_index":2746,"title":{},"content":{"78":{"position":[[72,7]]},"82":{"position":[[1177,9]]}},"keywords":{}}],["recreat",{"_index":3893,"title":{},"content":{"121":{"position":[[1195,8]]}},"keywords":{}}],["recurs",{"_index":2208,"title":{},"content":{"53":{"position":[[388,9]]},"189":{"position":[[2948,11]]}},"keywords":{}}],["redirect_uri",{"_index":2381,"title":{},"content":{"61":{"position":[[1712,15]]}},"keywords":{}}],["reduc",{"_index":1447,"title":{},"content":{"30":{"position":[[8360,6]]},"43":{"position":[[1444,6]]},"44":{"position":[[21,6]]},"45":{"position":[[312,6],[744,6]]},"51":{"position":[[1083,6]]},"101":{"position":[[660,6]]},"174":{"position":[[800,6]]}},"keywords":{}}],["reduce(lambda",{"_index":1481,"title":{},"content":{"30":{"position":[[9414,13]]},"51":{"position":[[1127,13]]}},"keywords":{}}],["reduct",{"_index":1894,"title":{"44":{"position":[[15,9]]},"45":{"position":[[15,9]]}},"content":{"45":{"position":[[712,10],[1071,10],[1158,9],[1594,9]]},"102":{"position":[[161,10],[1127,9]]},"105":{"position":[[965,9]]}},"keywords":{}}],["redund",{"_index":3919,"title":{},"content":{"121":{"position":[[2235,9]]},"124":{"position":[[680,9]]}},"keywords":{}}],["refcel",{"_index":4568,"title":{},"content":{"155":{"position":[[790,8]]},"159":{"position":[[725,9]]},"180":{"position":[[572,8]]}},"keywords":{}}],["refcell<u32>",{"_index":5093,"title":{},"content":{"180":{"position":[[379,18]]}},"keywords":{}}],["refcell<u8>",{"_index":5077,"title":{},"content":{"179":{"position":[[869,17]]},"184":{"position":[[1126,17]]},"185":{"position":[[682,18]]}},"keywords":{}}],["refcell::new(0",{"_index":5132,"title":{},"content":{"184":{"position":[[1146,16]]}},"keywords":{}}],["refcell::new(24",{"_index":5094,"title":{},"content":{"180":{"position":[[400,17]]}},"keywords":{}}],["refcell::new(25",{"_index":5073,"title":{},"content":{"179":{"position":[[588,17],[889,17]]}},"keywords":{}}],["refcell::new(8",{"_index":5136,"title":{},"content":{"185":{"position":[[840,15]]}},"keywords":{}}],["refcell::newfunct",{"_index":5098,"title":{},"content":{"180":{"position":[[629,21]]}},"keywords":{}}],["refer",{"_index":1593,"title":{"115":{"position":[[20,10]]}},"content":{"34":{"position":[[360,5],[665,8]]},"91":{"position":[[2630,9]]},"92":{"position":[[442,9]]},"93":{"position":[[1993,9]]},"97":{"position":[[5275,9],[5644,10],[5926,10]]},"98":{"position":[[921,9]]},"108":{"position":[[258,5]]},"113":{"position":[[1027,9]]},"115":{"position":[[62,10],[546,9]]},"121":{"position":[[675,9]]},"125":{"position":[[796,10],[2880,9]]},"127":{"position":[[259,8]]},"129":{"position":[[1277,5]]},"136":{"position":[[548,9]]},"155":{"position":[[1159,9]]},"159":{"position":[[503,10]]},"172":{"position":[[159,9]]},"179":{"position":[[473,10],[1715,5]]},"182":{"position":[[113,9]]},"183":{"position":[[680,10],[732,6]]},"184":{"position":[[231,9]]},"193":{"position":[[3009,9]]},"196":{"position":[[301,9],[842,9],[1260,9]]},"199":{"position":[[1186,10]]}},"keywords":{}}],["referenc",{"_index":3420,"title":{},"content":{"97":{"position":[[4737,10]]}},"keywords":{}}],["reference/valu",{"_index":5108,"title":{},"content":{"182":{"position":[[239,15]]}},"keywords":{}}],["references.python",{"_index":5326,"title":{},"content":{"196":{"position":[[246,17]]}},"keywords":{}}],["refin",{"_index":3196,"title":{},"content":{"93":{"position":[[1148,7]]}},"keywords":{}}],["reflect",{"_index":218,"title":{"4":{"position":[[13,11]]}},"content":{"30":{"position":[[747,7],[2663,7],[4017,7]]}},"keywords":{}}],["reform",{"_index":3948,"title":{},"content":{"122":{"position":[[888,6]]}},"keywords":{}}],["refus",{"_index":202,"title":{},"content":{"3":{"position":[[1262,6]]},"97":{"position":[[469,7]]},"185":{"position":[[534,7]]}},"keywords":{}}],["regardless",{"_index":5039,"title":{},"content":{"176":{"position":[[27,10]]}},"keywords":{}}],["regex",{"_index":4109,"title":{},"content":{"125":{"position":[[5138,5]]}},"keywords":{}}],["region",{"_index":4673,"title":{},"content":{"160":{"position":[[1270,6]]}},"keywords":{}}],["regist",{"_index":2341,"title":{"60":{"position":[[0,11]]}},"content":{"59":{"position":[[96,11]]},"60":{"position":[[14,10]]},"173":{"position":[[1498,11]]},"193":{"position":[[518,11],[1278,9],[1578,8],[3161,10]]},"197":{"position":[[1042,8]]}},"keywords":{}}],["regress",{"_index":1882,"title":{},"content":{"43":{"position":[[840,11]]}},"keywords":{}}],["regular",{"_index":4456,"title":{"145":{"position":[[8,7]]}},"content":{"160":{"position":[[153,7]]},"176":{"position":[[172,7]]},"199":{"position":[[170,7]]}},"keywords":{}}],["reject",{"_index":4095,"title":{},"content":{"125":{"position":[[4370,8]]}},"keywords":{}}],["rel",{"_index":1699,"title":{},"content":{"38":{"position":[[859,8]]},"65":{"position":[[134,12]]},"83":{"position":[[525,10]]},"106":{"position":[[105,8]]},"122":{"position":[[1358,10]]},"127":{"position":[[290,8]]},"193":{"position":[[471,8]]}},"keywords":{}}],["relat",{"_index":4201,"title":{},"content":{"125":{"position":[[10530,7]]},"172":{"position":[[1704,7]]},"182":{"position":[[22,7]]}},"keywords":{}}],["relativedelta(days=1",{"_index":1003,"title":{},"content":{"23":{"position":[[342,21]]}},"keywords":{}}],["releas",{"_index":2292,"title":{"87":{"position":[[27,8]]},"187":{"position":[[0,7]]}},"content":{"54":{"position":[[210,8]]},"88":{"position":[[1621,9],[1948,9],[2124,9],[3078,9],[3463,9],[3681,8]]},"89":{"position":[[198,9],[444,9],[624,8],[881,8]]},"90":{"position":[[3579,8]]},"91":{"position":[[135,8],[839,9],[1309,9],[1488,8],[4931,9],[5390,8]]},"93":{"position":[[130,7],[247,8],[356,7]]},"108":{"position":[[685,7]]},"122":{"position":[[1202,8],[1418,7]]},"141":{"position":[[231,8]]},"143":{"position":[[429,7]]},"146":{"position":[[217,7]]},"148":{"position":[[333,8]]},"160":{"position":[[3655,7],[3692,7]]},"163":{"position":[[476,8]]},"188":{"position":[[953,7],[1197,7],[1354,9],[2341,8],[3194,8]]},"189":{"position":[[819,7]]}},"keywords":{}}],["release).al",{"_index":4706,"title":{},"content":{"160":{"position":[[3717,12]]}},"keywords":{}}],["release?given",{"_index":2953,"title":{},"content":{"89":{"position":[[680,13]]}},"keywords":{}}],["reli",{"_index":3654,"title":{},"content":{"106":{"position":[[567,6]]},"158":{"position":[[175,4]]},"176":{"position":[[966,4]]},"181":{"position":[[906,4]]}},"keywords":{}}],["reliabl",{"_index":4666,"title":{},"content":{"160":{"position":[[879,12]]}},"keywords":{}}],["reliev",{"_index":4661,"title":{},"content":{"160":{"position":[[660,8]]}},"keywords":{}}],["religion",{"_index":2205,"title":{},"content":{"53":{"position":[[341,8]]}},"keywords":{}}],["remain",{"_index":2137,"title":{},"content":{"51":{"position":[[2985,9]]},"61":{"position":[[1103,7]]},"64":{"position":[[1911,9]]},"65":{"position":[[93,10],[965,10],[1119,10],[1133,9],[2082,9]]},"70":{"position":[[1296,7]]},"163":{"position":[[1834,10],[2042,11]]},"188":{"position":[[1380,7]]},"189":{"position":[[850,6],[1281,7]]}},"keywords":{}}],["remaining_2016",{"_index":2490,"title":{},"content":{"64":{"position":[[1683,14]]},"65":{"position":[[831,14],[881,14]]}},"keywords":{}}],["remaining_4i",{"_index":2508,"title":{},"content":{"65":{"position":[[866,12],[1598,12]]}},"keywords":{}}],["remaining_leap",{"_index":2520,"title":{},"content":{"65":{"position":[[1581,14],[1791,14],[1845,14]]}},"keywords":{}}],["remaining_year",{"_index":2523,"title":{},"content":{"65":{"position":[[1828,14],[2361,14]]}},"keywords":{}}],["remedi",{"_index":4365,"title":{},"content":{"133":{"position":[[149,6]]},"172":{"position":[[2085,7]]}},"keywords":{}}],["rememb",{"_index":67,"title":{},"content":{"1":{"position":[[745,8]]},"15":{"position":[[138,9]]},"97":{"position":[[2774,8]]},"127":{"position":[[502,8]]}},"keywords":{}}],["remov",{"_index":1966,"title":{},"content":{"45":{"position":[[369,8],[3396,7]]},"90":{"position":[[378,6],[395,7],[595,6],[645,6]]},"91":{"position":[[1984,6],[4101,6]]},"93":{"position":[[4397,6]]},"104":{"position":[[1162,7],[1901,6]]},"115":{"position":[[2500,7]]},"125":{"position":[[5147,6]]},"145":{"position":[[283,6]]},"153":{"position":[[419,6]]}},"keywords":{}}],["render",{"_index":82,"title":{},"content":{"2":{"position":[[122,9],[189,6]]}},"keywords":{}}],["repeat",{"_index":3168,"title":{},"content":{"91":{"position":[[4948,6]]},"92":{"position":[[20,6],[1549,6]]},"115":{"position":[[2638,8]]},"160":{"position":[[4447,10]]},"189":{"position":[[901,6]]}},"keywords":{}}],["replac",{"_index":3279,"title":{},"content":{"93":{"position":[[4745,7],[5160,7]]},"125":{"position":[[287,7]]},"179":{"position":[[491,9]]}},"keywords":{}}],["replay",{"_index":4980,"title":{},"content":{"174":{"position":[[263,7]]}},"keywords":{}}],["repli",{"_index":2074,"title":{},"content":{"51":{"position":[[201,5],[231,7]]}},"keywords":{}}],["replic",{"_index":3568,"title":{},"content":{"104":{"position":[[1498,9]]}},"keywords":{}}],["repmat(1:n",{"_index":410,"title":{},"content":{"7":{"position":[[663,11]]}},"keywords":{}}],["report",{"_index":3024,"title":{},"content":{"90":{"position":[[3487,7]]},"93":{"position":[[1862,7],[1956,7]]},"167":{"position":[[170,8]]}},"keywords":{}}],["repres",{"_index":978,"title":{},"content":{"22":{"position":[[2782,9]]},"43":{"position":[[1273,11]]},"90":{"position":[[4759,10],[4799,11],[5028,10]]},"102":{"position":[[253,10],[767,12]]},"104":{"position":[[144,9],[1244,9],[1321,9]]},"113":{"position":[[2087,9]]},"117":{"position":[[709,11],[857,10]]},"163":{"position":[[268,14]]},"188":{"position":[[2646,10]]}},"keywords":{}}],["represent",{"_index":4812,"title":{},"content":{"164":{"position":[[860,15]]}},"keywords":{}}],["reput",{"_index":1207,"title":{},"content":{"28":{"position":[[274,10],[823,10]]}},"keywords":{}}],["req",{"_index":3412,"title":{},"content":{"97":{"position":[[4439,5],[4875,5]]}},"keywords":{}}],["req.url",{"_index":3336,"title":{},"content":{"96":{"position":[[1210,10],[1747,11],[1907,7],[2295,11]]}},"keywords":{}}],["request",{"_index":914,"title":{"62":{"position":[[0,10]]}},"content":{"22":{"position":[[879,8]]},"30":{"position":[[8374,8]]},"61":{"position":[[831,7],[1277,8],[1867,7]]},"93":{"position":[[1348,8]]},"96":{"position":[[682,8],[980,7],[1101,8],[1631,8],[2177,8]]},"97":{"position":[[683,8],[1512,8],[1574,8],[3668,8],[4454,8],[4890,8]]},"123":{"position":[[807,8]]},"156":{"position":[[86,7]]}},"keywords":{}}],["request_url",{"_index":2382,"title":{},"content":{"61":{"position":[[1767,11]]}},"keywords":{}}],["requests.adapters.httpadapter(max_retries=0",{"_index":3235,"title":{},"content":{"93":{"position":[[2602,44]]}},"keywords":{}}],["requests.get(pag",{"_index":916,"title":{},"content":{"22":{"position":[[910,18]]}},"keywords":{}}],["requests.get(sa",{"_index":967,"title":{},"content":{"22":{"position":[[2404,15]]}},"keywords":{}}],["requests.get(url).json",{"_index":1473,"title":{},"content":{"30":{"position":[[9038,24]]}},"keywords":{}}],["requests.sess",{"_index":3234,"title":{},"content":{"93":{"position":[[2579,18]]}},"keywords":{}}],["requests_oauthlib",{"_index":2401,"title":{},"content":{"62":{"position":[[369,17]]}},"keywords":{}}],["requir",{"_index":6,"title":{},"content":{"1":{"position":[[19,11]]},"3":{"position":[[160,12]]},"32":{"position":[[2248,8]]},"59":{"position":[[87,8]]},"61":{"position":[[1391,8]]},"125":{"position":[[8010,8],[9378,8]]},"128":{"position":[[102,9]]},"136":{"position":[[529,8],[949,9]]},"160":{"position":[[2282,12]]},"164":{"position":[[604,8],[1318,8]]},"174":{"position":[[1254,8]]},"176":{"position":[[76,7]]},"190":{"position":[[327,8],[553,7]]},"196":{"position":[[571,8]]}},"keywords":{}}],["res.1",{"_index":4394,"title":{},"content":{"136":{"position":[[484,7]]}},"keywords":{}}],["rescu",{"_index":32,"title":{},"content":{"1":{"position":[[348,6]]}},"keywords":{}}],["research",{"_index":2303,"title":{},"content":{"55":{"position":[[208,8]]},"125":{"position":[[9839,9]]},"170":{"position":[[447,8]]}},"keywords":{}}],["reserv",{"_index":4432,"title":{},"content":{"140":{"position":[[103,8],[193,7]]},"141":{"position":[[282,9]]},"145":{"position":[[227,8]]},"146":{"position":[[336,8]]},"153":{"position":[[802,7]]},"173":{"position":[[417,7]]}},"keywords":{}}],["reshap",{"_index":3495,"title":{},"content":{"102":{"position":[[993,7]]},"103":{"position":[[1147,7],[1190,8]]}},"keywords":{}}],["resist",{"_index":182,"title":{},"content":{"3":{"position":[[914,7]]}},"keywords":{}}],["resolut",{"_index":3976,"title":{},"content":{"123":{"position":[[421,10]]}},"keywords":{}}],["resolv",{"_index":4099,"title":{},"content":{"125":{"position":[[4651,9],[4963,7],[8544,7],[9012,7]]}},"keywords":{}}],["resourc",{"_index":176,"title":{},"content":{"3":{"position":[[825,10]]},"4":{"position":[[457,9],[682,8]]}},"keywords":{}}],["respond",{"_index":1856,"title":{},"content":{"41":{"position":[[629,7]]},"123":{"position":[[604,8]]}},"keywords":{}}],["respons",{"_index":1612,"title":{},"content":{"34":{"position":[[1207,14]]},"105":{"position":[[3331,9]]},"125":{"position":[[4234,8]]},"155":{"position":[[426,11]]}},"keywords":{}}],["response_typ",{"_index":2378,"title":{},"content":{"61":{"position":[[1657,16]]}},"keywords":{}}],["response_url",{"_index":2387,"title":{},"content":{"61":{"position":[[2155,14]]}},"keywords":{}}],["responsibl",{"_index":5330,"title":{},"content":{"196":{"position":[[620,13]]}},"keywords":{}}],["rest",{"_index":33,"title":{},"content":{"1":{"position":[[363,4]]},"66":{"position":[[268,4]]},"175":{"position":[[1065,5]]}},"keywords":{}}],["result",{"_index":483,"title":{"53":{"position":[[4,8]]},"167":{"position":[[0,8]]}},"content":{"10":{"position":[[86,8]]},"15":{"position":[[486,9]]},"30":{"position":[[2751,8],[7893,8]]},"34":{"position":[[3497,7]]},"39":{"position":[[72,7],[2633,6],[3029,6],[3097,7]]},"40":{"position":[[2116,7]]},"41":{"position":[[123,7],[244,7]]},"43":{"position":[[1302,8]]},"51":{"position":[[3686,7]]},"58":{"position":[[344,6]]},"69":{"position":[[34,7]]},"72":{"position":[[561,7],[593,8],[669,7]]},"73":{"position":[[844,7]]},"74":{"position":[[98,6],[830,7]]},"76":{"position":[[117,8]]},"81":{"position":[[91,7]]},"82":{"position":[[996,7]]},"83":{"position":[[11,7],[146,8],[192,7]]},"91":{"position":[[1659,8],[3927,7],[5892,7]]},"92":{"position":[[1643,7]]},"93":{"position":[[443,7]]},"96":{"position":[[299,6]]},"97":{"position":[[3515,7]]},"101":{"position":[[863,9]]},"105":{"position":[[73,7],[815,6]]},"106":{"position":[[1124,8]]},"132":{"position":[[730,7]]},"152":{"position":[[805,6]]},"167":{"position":[[144,7],[240,7]]},"178":{"position":[[615,9]]},"189":{"position":[[2023,6]]},"193":{"position":[[217,7],[544,7],[1026,6],[1190,7],[1543,6]]}},"keywords":{}}],["result["days"",{"_index":1767,"title":{},"content":{"39":{"position":[[2783,24]]}},"keywords":{}}],["result["investments"",{"_index":1772,"title":{},"content":{"39":{"position":[[2955,31]]}},"keywords":{}}],["result["max"",{"_index":1765,"title":{},"content":{"39":{"position":[[2719,23]]}},"keywords":{}}],["result["profit"",{"_index":1762,"title":{},"content":{"39":{"position":[[2657,26]]}},"keywords":{}}],["result["score"",{"_index":1769,"title":{},"content":{"39":{"position":[[2848,25]]}},"keywords":{}}],["results[tick",{"_index":1778,"title":{},"content":{"39":{"position":[[3239,15]]}},"keywords":{}}],["results_df",{"_index":1775,"title":{},"content":{"39":{"position":[[3162,10],[3257,10]]}},"keywords":{}}],["ret",{"_index":749,"title":{},"content":{"19":{"position":[[295,4]]},"20":{"position":[[249,4]]},"128":{"position":[[742,3],[905,3],[1500,3],[1620,3]]},"129":{"position":[[731,3]]}},"keywords":{}}],["ret.abs().max",{"_index":767,"title":{},"content":{"20":{"position":[[254,15]]}},"keywords":{}}],["ret.mean",{"_index":750,"title":{},"content":{"19":{"position":[[300,11]]}},"keywords":{}}],["ret.std",{"_index":752,"title":{},"content":{"19":{"position":[[346,9]]}},"keywords":{}}],["retriev",{"_index":1348,"title":{},"content":{"30":{"position":[[876,9],[8216,10],[9625,9],[9976,10],[10142,10],[10199,10],[10253,10],[10303,10],[10367,10]]},"60":{"position":[[83,8]]},"62":{"position":[[1691,9]]},"89":{"position":[[951,8]]},"91":{"position":[[3292,9]]},"92":{"position":[[1104,9]]},"117":{"position":[[1668,8]]},"193":{"position":[[1624,8]]}},"keywords":{}}],["retrieve_data(url",{"_index":964,"title":{},"content":{"22":{"position":[[2328,19]]}},"keywords":{}}],["retrieve_int",{"_index":5347,"title":{},"content":{"197":{"position":[[748,14],[873,14]]}},"keywords":{}}],["retrieve_int(&a",{"_index":5352,"title":{},"content":{"197":{"position":[[1370,21]]}},"keywords":{}}],["retrieve_int(&b",{"_index":5353,"title":{},"content":{"197":{"position":[[1392,21]]}},"keywords":{}}],["retrieve_int(u",{"_index":5348,"title":{},"content":{"197":{"position":[[935,15]]}},"keywords":{}}],["return",{"_index":402,"title":{"18":{"position":[[16,7]]},"23":{"position":[[13,7]]}},"content":{"7":{"position":[[512,6]]},"12":{"position":[[510,6]]},"13":{"position":[[813,6],[1000,6],[1063,6],[1418,6]]},"14":{"position":[[1670,6],[2018,6],[2097,6],[2490,6]]},"15":{"position":[[1060,6],[1686,6],[1765,6],[2162,6]]},"17":{"position":[[11,6]]},"18":{"position":[[44,8],[77,7]]},"19":{"position":[[64,6],[122,7]]},"20":{"position":[[828,6],[1718,6],[1727,6],[1844,6],[2533,7],[2977,7]]},"22":{"position":[[1173,7],[1660,6],[1711,6],[2649,6],[2757,8]]},"24":{"position":[[186,7],[267,6],[741,6],[1067,7],[1581,6]]},"25":{"position":[[457,6],[787,7],[1301,6]]},"28":{"position":[[1149,6],[1182,6],[1701,6],[1816,6],[2946,6],[2986,6],[3487,6],[3568,6]]},"30":{"position":[[1521,6],[1554,6],[1907,6],[3316,6],[4791,6],[4831,6],[5166,6],[6384,6],[9031,6]]},"34":{"position":[[1336,6],[1527,6],[2668,6]]},"39":{"position":[[717,6],[975,6],[2118,6],[3022,6],[3268,6]]},"40":{"position":[[3542,7]]},"45":{"position":[[2142,6],[2922,6]]},"51":{"position":[[3715,6],[3789,6],[3863,6],[4008,6],[4193,6]]},"52":{"position":[[1139,6]]},"62":{"position":[[897,6],[1127,6]]},"70":{"position":[[1001,6]]},"76":{"position":[[451,6],[791,6],[1772,6],[3270,6],[3319,6]]},"88":{"position":[[645,9],[902,6],[1400,6]]},"90":{"position":[[3960,6]]},"91":{"position":[[3049,6],[3302,6]]},"92":{"position":[[861,6],[1114,6],[1533,8]]},"93":{"position":[[221,7],[2879,6],[4060,9],[4317,6]]},"96":{"position":[[487,6]]},"97":{"position":[[1298,7],[1669,7],[3504,6],[5548,8]]},"103":{"position":[[1460,6]]},"105":{"position":[[806,6],[835,6],[1115,6],[1607,6]]},"125":{"position":[[4345,8]]},"188":{"position":[[1037,6],[1140,6],[1272,6],[1435,6],[3576,6],[3597,6]]},"189":{"position":[[1126,6],[1202,6],[1396,6],[1472,6],[3120,6],[3129,6]]},"196":{"position":[[787,8]]},"199":{"position":[[248,6],[410,6]]}},"keywords":{}}],["returns[tick].mean",{"_index":729,"title":{},"content":{"18":{"position":[[161,20]]},"20":{"position":[[1414,21]]}},"keywords":{}}],["returns_a",{"_index":817,"title":{},"content":{"20":{"position":[[1371,9],[1904,10]]}},"keywords":{}}],["reveal",{"_index":4274,"title":{},"content":{"129":{"position":[[18,6]]}},"keywords":{}}],["revel",{"_index":4276,"title":{},"content":{"129":{"position":[[47,10],[802,11]]}},"keywords":{}}],["review",{"_index":2209,"title":{},"content":{"53":{"position":[[404,6]]}},"keywords":{}}],["rewind",{"_index":4979,"title":{},"content":{"174":{"position":[[252,6]]}},"keywords":{}}],["rewir",{"_index":150,"title":{},"content":{"3":{"position":[[375,8]]}},"keywords":{}}],["rewrit",{"_index":3997,"title":{},"content":{"124":{"position":[[328,7]]}},"keywords":{}}],["rich",{"_index":4653,"title":{},"content":{"160":{"position":[[330,4]]}},"keywords":{}}],["rid",{"_index":2518,"title":{},"content":{"65":{"position":[[1468,3]]}},"keywords":{}}],["ride",{"_index":1812,"title":{},"content":{"40":{"position":[[1575,6]]}},"keywords":{}}],["right",{"_index":160,"title":{},"content":{"3":{"position":[[538,5]]},"4":{"position":[[467,5]]},"24":{"position":[[3399,6]]},"26":{"position":[[437,6]]},"32":{"position":[[334,6],[2235,5]]},"38":{"position":[[761,5]]},"53":{"position":[[1068,5]]},"57":{"position":[[11,6]]},"70":{"position":[[435,7],[609,7]]},"71":{"position":[[535,7],[709,7]]},"74":{"position":[[704,7]]},"91":{"position":[[3772,5]]},"96":{"position":[[414,6],[819,6],[1453,6]]},"115":{"position":[[687,6]]},"116":{"position":[[706,6]]},"118":{"position":[[94,5]]},"121":{"position":[[1443,6]]},"124":{"position":[[64,6]]},"127":{"position":[[80,5]]},"129":{"position":[[144,6],[608,5]]},"175":{"position":[[82,6]]},"196":{"position":[[1392,5]]}},"keywords":{}}],["rigor",{"_index":1707,"title":{},"content":{"39":{"position":[[29,8]]},"160":{"position":[[4489,10]]},"176":{"position":[[1494,8]]}},"keywords":{}}],["rip",{"_index":4285,"title":{},"content":{"129":{"position":[[561,4]]},"183":{"position":[[397,4],[543,4]]}},"keywords":{}}],["risk",{"_index":556,"title":{},"content":{"13":{"position":[[474,4]]},"14":{"position":[[527,4]]}},"keywords":{}}],["roadmap",{"_index":3990,"title":{"124":{"position":[[0,7]]}},"content":{},"keywords":{}}],["roadmap/issues/16",{"_index":3746,"title":{},"content":{"113":{"position":[[1219,17]]}},"keywords":{}}],["rock",{"_index":3844,"title":{},"content":{"118":{"position":[[294,5]]}},"keywords":{}}],["roman",{"_index":2224,"title":{},"content":{"53":{"position":[[697,5]]}},"keywords":{}}],["room",{"_index":4753,"title":{},"content":{"161":{"position":[[1293,4]]}},"keywords":{}}],["roughli",{"_index":5195,"title":{},"content":{"188":{"position":[[2763,7]]}},"keywords":{}}],["round",{"_index":373,"title":{},"content":{"6":{"position":[[1087,6]]},"74":{"position":[[1436,8]]}},"keywords":{}}],["roundabout",{"_index":4334,"title":{},"content":{"130":{"position":[[18,10]]}},"keywords":{}}],["rout",{"_index":3368,"title":{},"content":{"97":{"position":[[934,7],[3071,6]]},"98":{"position":[[47,7]]},"101":{"position":[[428,6]]},"175":{"position":[[1,8],[371,5],[534,7]]}},"keywords":{}}],["router",{"_index":3366,"title":{},"content":{"97":{"position":[[773,6],[1082,6],[3803,9],[4009,6],[4023,6],[6381,6]]}},"keywords":{}}],["router.get("/"",{"_index":3407,"title":{},"content":{"97":{"position":[[3880,25],[4413,25],[4844,25]]}},"keywords":{}}],["routers/switch",{"_index":5026,"title":{},"content":{"175":{"position":[[1088,16]]}},"keywords":{}}],["row",{"_index":1000,"title":{},"content":{"23":{"position":[[272,4]]},"24":{"position":[[1181,3]]},"25":{"position":[[901,3]]},"75":{"position":[[1178,4]]},"91":{"position":[[4125,3]]},"102":{"position":[[1038,4]]}},"keywords":{}}],["row[1][0",{"_index":1060,"title":{},"content":{"24":{"position":[[1238,9]]},"25":{"position":[[958,9]]}},"keywords":{}}],["row[1][1",{"_index":1058,"title":{},"content":{"24":{"position":[[1216,9]]},"25":{"position":[[936,9]]}},"keywords":{}}],["row_dt",{"_index":1057,"title":{},"content":{"24":{"position":[[1207,6]]},"25":{"position":[[927,6]]}},"keywords":{}}],["row_dt.day",{"_index":1064,"title":{},"content":{"24":{"position":[[1295,11]]},"25":{"position":[[1015,11]]}},"keywords":{}}],["row_dt.month",{"_index":1063,"title":{},"content":{"24":{"position":[[1281,13]]},"25":{"position":[[1001,13]]}},"keywords":{}}],["row_valu",{"_index":1059,"title":{},"content":{"24":{"position":[[1226,9],[1364,10],[1411,10],[1458,10]]},"25":{"position":[[946,9],[1084,10],[1131,10],[1178,10]]}},"keywords":{}}],["rs",{"_index":4043,"title":{},"content":{"125":{"position":[[1322,3]]}},"keywords":{}}],["rsi",{"_index":4287,"title":{},"content":{"129":{"position":[[586,4]]},"193":{"position":[[1272,5]]},"197":{"position":[[1036,5]]}},"keywords":{}}],["rsp",{"_index":4258,"title":{},"content":{"128":{"position":[[465,3],[473,4],[777,3],[1530,4],[1598,6],[1613,4]]},"129":{"position":[[531,4],[548,3],[685,3],[723,4]]},"192":{"position":[[283,5],[688,4]]},"193":{"position":[[501,4],[1135,5],[1661,5]]}},"keywords":{}}],["rss",{"_index":3437,"title":{},"content":{"98":{"position":[[159,3]]}},"keywords":{}}],["rubbl",{"_index":3859,"title":{},"content":{"120":{"position":[[717,6]]}},"keywords":{}}],["rule",{"_index":173,"title":{},"content":{"3":{"position":[[777,6]]},"90":{"position":[[385,6],[454,5]]},"98":{"position":[[662,5]]},"121":{"position":[[2273,4]]},"159":{"position":[[363,5]]},"193":{"position":[[379,5]]},"196":{"position":[[1,5]]}},"keywords":{}}],["run",{"_index":289,"title":{"24":{"position":[[0,7]]},"34":{"position":[[0,7]]},"39":{"position":[[0,7]]},"103":{"position":[[0,7]]},"112":{"position":[[8,7]]},"134":{"position":[[0,7]]}},"content":{"4":{"position":[[1326,7]]},"8":{"position":[[20,3]]},"12":{"position":[[610,3],[656,3]]},"34":{"position":[[1382,3],[3040,3]]},"38":{"position":[[1291,3]]},"41":{"position":[[240,3]]},"43":{"position":[[387,3]]},"45":{"position":[[1802,7]]},"46":{"position":[[668,7]]},"57":{"position":[[472,7]]},"86":{"position":[[293,7]]},"91":{"position":[[4004,7]]},"98":{"position":[[971,3]]},"102":{"position":[[1082,3]]},"103":{"position":[[157,3],[1561,7]]},"106":{"position":[[263,3]]},"112":{"position":[[127,3],[562,7],[632,7]]},"123":{"position":[[668,7]]},"125":{"position":[[746,8],[1068,3],[2769,7],[2937,7],[2985,7],[6847,4],[7192,4],[8149,3],[8325,7],[8378,7],[8932,8],[11212,7]]},"127":{"position":[[1444,3]]},"129":{"position":[[2570,3],[2796,3]]},"147":{"position":[[399,3]]},"153":{"position":[[459,7]]},"160":{"position":[[2054,7],[3088,4],[3186,8],[3608,3],[3686,3],[3746,3]]},"167":{"position":[[112,3],[206,4]]},"172":{"position":[[819,7],[1264,3]]},"173":{"position":[[54,7],[576,3],[753,3],[1908,7]]},"174":{"position":[[833,7]]},"176":{"position":[[1268,3]]},"188":{"position":[[607,4],[1219,7],[1402,7],[1821,4],[1836,7],[1918,3],[2053,3],[2403,3],[2804,7],[3217,8],[3325,7],[3875,3],[4521,3]]},"189":{"position":[[310,8],[683,8],[1213,3],[1730,4],[1901,3],[1987,7],[2347,3]]},"190":{"position":[[146,7],[561,7]]},"196":{"position":[[773,3],[1112,7]]}},"keywords":{}}],["run().expect("compil",{"_index":3705,"title":{},"content":{"111":{"position":[[449,29]]}},"keywords":{}}],["runtim",{"_index":3693,"title":{},"content":{"109":{"position":[[547,7],[574,8]]},"125":{"position":[[4974,7]]},"188":{"position":[[3290,7]]},"189":{"position":[[177,8]]},"190":{"position":[[802,8]]}},"keywords":{}}],["russ",{"_index":1009,"title":{},"content":{"23":{"position":[[498,4]]},"24":{"position":[[2513,4],[2665,4]]},"25":{"position":[[2236,4],[2388,4]]}},"keywords":{}}],["russ_close_ret",{"_index":1144,"title":{},"content":{"25":{"position":[[557,14],[1469,15]]}},"keywords":{}}],["russ_open_ret",{"_index":1042,"title":{},"content":{"24":{"position":[[839,13],[1747,14]]}},"keywords":{}}],["russel",{"_index":995,"title":{},"content":{"23":{"position":[[133,7]]},"24":{"position":[[3059,7],[3370,7],[3503,7]]},"26":{"position":[[605,7]]},"93":{"position":[[1215,7],[2935,7],[3074,7]]}},"keywords":{}}],["rust",{"_index":3308,"title":{"109":{"position":[[31,4]]},"119":{"position":[[35,4]]},"125":{"position":[[29,4]]},"126":{"position":[[14,4]]},"151":{"position":[[15,5]]},"154":{"position":[[15,5]]},"159":{"position":[[15,5]]},"160":{"position":[[15,5]]},"177":{"position":[[15,5]]},"191":{"position":[[15,5]]}},"content":{"95":{"position":[[246,5]]},"96":{"position":[[12,4],[214,4],[572,4],[1818,4]]},"97":{"position":[[133,5],[306,4],[367,4],[455,4],[970,4],[2563,4],[2723,4],[4163,4],[5254,4]]},"98":{"position":[[325,4],[338,4],[736,5],[1066,4],[1158,4]]},"109":{"position":[[68,4],[491,4]]},"111":{"position":[[96,4]]},"112":{"position":[[1347,4]]},"115":{"position":[[48,4],[518,4],[852,4],[3029,4]]},"116":{"position":[[656,4],[2848,4]]},"117":{"position":[[61,4],[1904,4]]},"120":{"position":[[1128,5]]},"121":{"position":[[162,5],[183,4],[271,5],[849,4],[1992,4],[2529,5]]},"122":{"position":[[6,4],[164,4],[581,5],[1187,5]]},"124":{"position":[[307,4]]},"125":{"position":[[3771,4],[6116,4],[6537,4],[7229,4],[7312,5],[7322,4],[7752,4],[7868,4],[9697,5],[9931,4],[11327,4],[11695,4]]},"127":{"position":[[516,4],[1517,4]]},"128":{"position":[[1036,4],[1099,5],[1640,4],[1840,5]]},"129":{"position":[[87,4],[319,4],[1648,4],[2767,5]]},"130":{"position":[[66,4],[387,4]]},"132":{"position":[[526,4]]},"133":{"position":[[47,4],[135,4]]},"139":{"position":[[176,4],[836,5]]},"140":{"position":[[63,4]]},"148":{"position":[[244,4],[454,4]]},"152":{"position":[[356,4],[1684,4]]},"153":{"position":[[268,5],[1055,4]]},"156":{"position":[[201,4],[1744,4]]},"157":{"position":[[144,4]]},"158":{"position":[[275,4]]},"159":{"position":[[300,4]]},"160":{"position":[[269,4],[350,4],[646,4],[827,5],[957,4],[1237,4],[1333,4],[1538,4],[1755,5],[2257,4],[2424,4],[3438,4],[3573,4],[3756,4],[4417,4],[4458,4]]},"164":{"position":[[134,4],[179,4]]},"165":{"position":[[538,5],[1139,4]]},"166":{"position":[[597,4]]},"172":{"position":[[1038,4],[1189,6],[1503,4]]},"179":{"position":[[69,4],[229,4],[749,4],[1173,4],[1613,4]]},"184":{"position":[[385,4],[734,4],[1167,4]]},"185":{"position":[[529,4],[863,4]]},"186":{"position":[[115,5],[670,4]]},"193":{"position":[[706,4]]},"194":{"position":[[109,4]]},"195":{"position":[[152,4],[848,4],[974,4]]},"196":{"position":[[394,5],[1290,4]]},"197":{"position":[[11,4]]},"198":{"position":[[52,4],[80,4]]},"199":{"position":[[806,5]]}},"keywords":{}}],["rust"",{"_index":3342,"title":{},"content":{"96":{"position":[[1415,11]]}},"keywords":{}}],["rust'",{"_index":3356,"title":{},"content":{"97":{"position":[[1,6],[5475,6],[6448,6]]},"130":{"position":[[449,6]]},"160":{"position":[[833,6]]},"164":{"position":[[710,6]]}},"keywords":{}}],["rust.git",{"_index":4075,"title":{},"content":{"125":{"position":[[3099,8]]}},"keywords":{}}],["rustdoesn't",{"_index":4669,"title":{},"content":{"160":{"position":[[1045,11]]}},"keywords":{}}],["rusti",{"_index":38,"title":{},"content":{"1":{"position":[[432,6]]}},"keywords":{}}],["rustic",{"_index":3297,"title":{"94":{"position":[[2,6]]}},"content":{},"keywords":{}}],["rv:46.0",{"_index":3227,"title":{},"content":{"93":{"position":[[2395,8]]}},"keywords":{}}],["rwlock",{"_index":4607,"title":{},"content":{"157":{"position":[[373,7]]}},"keywords":{}}],["rwlockmutex",{"_index":4564,"title":{},"content":{"155":{"position":[[719,11]]}},"keywords":{}}],["r−qr",{"_index":331,"title":{},"content":{"6":{"position":[[441,4]]}},"keywords":{}}],["r−rmσ{r",{"_index":736,"title":{},"content":{"19":{"position":[[9,7]]}},"keywords":{}}],["s",{"_index":784,"title":{},"content":{"20":{"position":[[675,3]]},"93":{"position":[[2575,1]]},"188":{"position":[[2591,3]]},"189":{"position":[[1795,3]]},"195":{"position":[[572,2]]},"199":{"position":[[1280,1],[1356,1],[1423,1],[1512,1],[1581,1],[1692,1]]}},"keywords":{}}],["s&p",{"_index":991,"title":{},"content":{"23":{"position":[[92,7]]},"24":{"position":[[2608,7],[2840,7],[3076,7],[3354,7],[3491,7]]},"25":{"position":[[2331,7],[2563,7]]},"26":{"position":[[593,7]]}},"keywords":{}}],["s.d."",{"_index":3001,"title":{},"content":{"90":{"position":[[1629,11],[1778,11],[2922,11]]}},"keywords":{}}],["s.mount('http",{"_index":3236,"title":{},"content":{"93":{"position":[[2647,18]]}},"keywords":{}}],["s.t",{"_index":776,"title":{},"content":{"20":{"position":[[537,7],[615,5],[768,4]]}},"keywords":{}}],["s/.*instantiatestreaming.*//g",{"_index":4126,"title":{},"content":{"125":{"position":[[5634,31]]}},"keywords":{}}],["s0",{"_index":351,"title":{},"content":{"6":{"position":[[766,2],[902,2]]},"7":{"position":[[386,2]]},"8":{"position":[[99,2]]},"11":{"position":[[360,2]]},"12":{"position":[[313,2],[361,2]]},"13":{"position":[[534,2],[546,2],[570,2]]},"14":{"position":[[1351,2],[1371,2],[1400,2]]},"15":{"position":[[720,2],[740,2],[769,2]]}},"keywords":{}}],["s0s_0s0",{"_index":318,"title":{},"content":{"6":{"position":[[287,8]]}},"keywords":{}}],["sa",{"_index":912,"title":{},"content":{"22":{"position":[[856,2],[2348,2]]}},"keywords":{}}],["sacrif",{"_index":3650,"title":{},"content":{"106":{"position":[[366,11]]}},"keywords":{}}],["sacrific",{"_index":3485,"title":{},"content":{"101":{"position":[[823,10]]},"104":{"position":[[1014,10]]}},"keywords":{}}],["safe",{"_index":2363,"title":{},"content":{"61":{"position":[[1111,5]]},"97":{"position":[[5787,4]]},"115":{"position":[[530,6],[681,5],[1232,6],[1612,6],[1889,6],[2437,6],[2690,7]]},"116":{"position":[[1184,6],[1517,6],[1794,6],[2295,6],[2700,4],[2938,4],[3001,4],[3150,5],[3189,5]]},"117":{"position":[[349,4],[970,4],[1565,4]]},"143":{"position":[[115,5]]},"155":{"position":[[1090,4]]},"178":{"position":[[177,4]]},"182":{"position":[[650,4]]},"184":{"position":[[1103,6]]},"185":{"position":[[134,4],[784,6]]},"186":{"position":[[110,4]]},"188":{"position":[[406,4],[899,4],[4336,6],[4432,4]]},"189":{"position":[[3008,5]]},"195":{"position":[[147,4]]}},"keywords":{}}],["safe_cover(cary_forecast[x]['curr",{"_index":1358,"title":{},"content":{"30":{"position":[[1771,42],[3120,42]]}},"keywords":{}}],["safe_cover(forecasts_df[city][x]['curr",{"_index":1246,"title":{},"content":{"28":{"position":[[1405,47]]}},"keywords":{}}],["safe_cover(fram",{"_index":1236,"title":{},"content":{"28":{"position":[[1094,18]]},"30":{"position":[[1466,18]]}},"keywords":{}}],["safe_float(self",{"_index":946,"title":{},"content":{"22":{"position":[[1629,16]]}},"keywords":{}}],["safe_precip(cary_forecast[x]['curr",{"_index":1405,"title":{},"content":{"30":{"position":[[5039,43],[6188,43]]}},"keywords":{}}],["safe_precip(forecasts_df[city][x]['curr",{"_index":1300,"title":{},"content":{"28":{"position":[[3200,48]]}},"keywords":{}}],["safe_precip(fram",{"_index":1295,"title":{},"content":{"28":{"position":[[2883,19]]},"30":{"position":[[4728,19]]}},"keywords":{}}],["safeguard",{"_index":1608,"title":{},"content":{"34":{"position":[[1157,9]]}},"keywords":{}}],["safeti",{"_index":3358,"title":{},"content":{"97":{"position":[[65,6],[157,7]]},"117":{"position":[[649,6]]}},"keywords":{}}],["saltiel",{"_index":2959,"title":{},"content":{"89":{"position":[[928,7]]}},"keywords":{}}],["same",{"_index":153,"title":{},"content":{"3":{"position":[[425,4]]},"12":{"position":[[149,5]]},"14":{"position":[[1196,4]]},"15":{"position":[[622,5]]},"28":{"position":[[131,4],[4001,4]]},"34":{"position":[[3619,4]]},"38":{"position":[[956,4]]},"40":{"position":[[2478,4]]},"45":{"position":[[3345,5]]},"53":{"position":[[791,4]]},"69":{"position":[[356,4]]},"71":{"position":[[1104,4]]},"89":{"position":[[353,4]]},"91":{"position":[[4959,4],[5403,4],[5931,4]]},"96":{"position":[[856,4]]},"97":{"position":[[1820,4]]},"101":{"position":[[513,4],[750,5]]},"102":{"position":[[200,4]]},"103":{"position":[[1670,4]]},"105":{"position":[[3063,4]]},"111":{"position":[[219,4]]},"112":{"position":[[1338,4]]},"116":{"position":[[898,4]]},"121":{"position":[[339,4],[494,4],[515,4],[1208,4]]},"125":{"position":[[725,4]]},"129":{"position":[[1588,4],[1779,4]]},"136":{"position":[[869,4]]},"156":{"position":[[1801,4]]},"160":{"position":[[2611,4]]},"163":{"position":[[2307,4]]},"165":{"position":[[147,4]]},"169":{"position":[[168,4]]},"172":{"position":[[813,5]]},"176":{"position":[[1348,4]]},"178":{"position":[[348,4]]},"182":{"position":[[521,4]]},"188":{"position":[[1798,4],[3317,4]]},"189":{"position":[[912,4],[1657,4]]},"196":{"position":[[430,4],[682,4]]}},"keywords":{}}],["sampl",{"_index":444,"title":{},"content":{"8":{"position":[[26,6]]},"12":{"position":[[180,6]]},"30":{"position":[[3783,9],[4208,7],[6862,9]]},"103":{"position":[[400,6],[999,7]]},"105":{"position":[[609,6]]},"199":{"position":[[92,8]]}},"keywords":{}}],["sampler",{"_index":3514,"title":{},"content":{"103":{"position":[[505,11],[565,10],[611,10]]}},"keywords":{}}],["sandwich",{"_index":4758,"title":{},"content":{"161":{"position":[[1735,9]]}},"keywords":{}}],["saniti",{"_index":3544,"title":{},"content":{"103":{"position":[[1985,6]]},"125":{"position":[[6889,6]]}},"keywords":{}}],["santand",{"_index":1858,"title":{"42":{"position":[[11,9]]}},"content":{},"keywords":{}}],["satisfact",{"_index":1909,"title":{},"content":{"44":{"position":[[442,13]]},"46":{"position":[[199,13]]}},"keywords":{}}],["satisfi",{"_index":1880,"title":{},"content":{"43":{"position":[[763,9]]},"44":{"position":[[1161,9],[1568,9]]},"46":{"position":[[547,10]]},"97":{"position":[[2045,9]]},"115":{"position":[[995,9],[1342,9],[1714,9],[2083,9]]},"116":{"position":[[994,9],[1294,9],[1619,9],[1988,9]]}},"keywords":{}}],["satisfied"",{"_index":1951,"title":{},"content":{"44":{"position":[[1725,15]]}},"keywords":{}}],["save",{"_index":273,"title":{},"content":{"4":{"position":[[999,5]]},"74":{"position":[[899,4]]},"97":{"position":[[2178,4]]},"101":{"position":[[881,4]]},"102":{"position":[[293,4]]},"106":{"position":[[207,4],[347,4]]},"121":{"position":[[2711,4]]}},"keywords":{}}],["saw",{"_index":119,"title":{},"content":{"2":{"position":[[685,3]]},"28":{"position":[[4152,3]]},"40":{"position":[[1408,3]]},"88":{"position":[[12,3]]}},"keywords":{}}],["say",{"_index":1967,"title":{},"content":{"45":{"position":[[419,6]]},"104":{"position":[[1146,6]]},"160":{"position":[[4156,6]]}},"keywords":{}}],["sayher",{"_index":4066,"title":{},"content":{"125":{"position":[[2654,7]]}},"keywords":{}}],["sbe",{"_index":4836,"title":{},"content":{"166":{"position":[[13,3],[244,3],[466,3],[610,3]]},"168":{"position":[[327,3]]},"169":{"position":[[438,3]]},"170":{"position":[[160,3],[196,3]]}},"keywords":{}}],["sbe'",{"_index":4849,"title":{},"content":{"166":{"position":[[769,5]]}},"keywords":{}}],["scalar",{"_index":4460,"title":{},"content":{"145":{"position":[[343,7]]},"184":{"position":[[103,6]]}},"keywords":{}}],["scalars,struct",{"_index":5058,"title":{},"content":{"178":{"position":[[93,16]]}},"keywords":{}}],["scale",{"_index":11,"title":{},"content":{"1":{"position":[[93,6]]},"20":{"position":[[2436,6]]},"33":{"position":[[1010,5],[1232,5]]},"82":{"position":[[88,5]]},"98":{"position":[[117,5]]},"170":{"position":[[391,6]]}},"keywords":{}}],["scari",{"_index":2550,"title":{},"content":{"66":{"position":[[634,5]]}},"keywords":{}}],["scatter",{"_index":1885,"title":{},"content":{"43":{"position":[[1051,7]]}},"keywords":{}}],["scenario",{"_index":1585,"title":{},"content":{"33":{"position":[[1049,9]]},"69":{"position":[[288,9]]},"77":{"position":[[30,9],[116,8]]}},"keywords":{}}],["schedul",{"_index":4941,"title":{},"content":{"173":{"position":[[319,11],[362,8],[607,10],[862,10]]}},"keywords":{}}],["schema",{"_index":3661,"title":{"110":{"position":[[24,7]]}},"content":{"108":{"position":[[50,6]]},"110":{"position":[[57,6],[250,6],[354,6],[364,6]]},"111":{"position":[[194,6],[570,6],[618,6],[764,6]]},"112":{"position":[[1145,6]]},"113":{"position":[[73,6],[2165,7]]},"163":{"position":[[128,6]]},"166":{"position":[[718,7]]},"168":{"position":[[153,6]]},"169":{"position":[[267,6]]}},"keywords":{}}],["schema"",{"_index":3706,"title":{},"content":{"111":{"position":[[479,14]]}},"keywords":{}}],["scheme",{"_index":3456,"title":{"100":{"position":[[44,7]]},"102":{"position":[[24,7]]}},"content":{"100":{"position":[[445,6]]},"102":{"position":[[700,6],[1489,6]]},"104":{"position":[[1705,7]]}},"keywords":{}}],["scienc",{"_index":2313,"title":{},"content":{"57":{"position":[[299,7]]}},"keywords":{}}],["scientist",{"_index":2032,"title":{},"content":{"46":{"position":[[382,10]]}},"keywords":{}}],["scientist"",{"_index":4503,"title":{},"content":{"150":{"position":[[778,15]]}},"keywords":{}}],["scikit",{"_index":3503,"title":{},"content":{"103":{"position":[[132,6]]}},"keywords":{}}],["scipy.io",{"_index":3512,"title":{},"content":{"103":{"position":[[481,8]]}},"keywords":{}}],["scipy.optim",{"_index":803,"title":{},"content":{"20":{"position":[[1026,14]]}},"keywords":{}}],["scope",{"_index":2355,"title":{},"content":{"61":{"position":[[416,7],[1607,6],[1635,8]]},"97":{"position":[[1417,5],[1730,6]]},"98":{"position":[[654,7]]},"155":{"position":[[107,5],[1148,5]]}},"keywords":{}}],["score",{"_index":1693,"title":{},"content":{"38":{"position":[[515,5],[699,7],[1235,7]]},"40":{"position":[[517,5],[855,5],[987,6],[2053,5],[2407,5],[2997,5],[3107,6]]},"76":{"position":[[26,5],[2532,5],[2967,6]]},"78":{"position":[[906,5]]},"82":{"position":[[281,5],[351,5],[421,5],[491,5],[561,5],[631,5],[701,5],[771,5],[841,5],[912,5]]}},"keywords":{}}],["score(data",{"_index":2727,"title":{},"content":{"76":{"position":[[2069,11],[2647,11]]}},"keywords":{}}],["score(x",{"_index":2686,"title":{},"content":{"76":{"position":[[468,8]]}},"keywords":{}}],["scratch",{"_index":4191,"title":{},"content":{"125":{"position":[[9758,8]]}},"keywords":{}}],["screen",{"_index":4033,"title":{},"content":{"125":{"position":[[952,6]]}},"keywords":{}}],["script",{"_index":4112,"title":{},"content":{"125":{"position":[[5196,7],[6678,6],[6840,6]]},"167":{"position":[[102,6]]}},"keywords":{}}],["scriptprestart",{"_index":4139,"title":{},"content":{"125":{"position":[[6436,14]]}},"keywords":{}}],["scriptto",{"_index":4134,"title":{},"content":{"125":{"position":[[6307,8]]}},"keywords":{}}],["search",{"_index":97,"title":{},"content":{"2":{"position":[[354,9]]},"76":{"position":[[1234,6]]},"190":{"position":[[868,6]]},"199":{"position":[[1150,6]]}},"keywords":{}}],["season",{"_index":2312,"title":{},"content":{"57":{"position":[[215,7]]}},"keywords":{}}],["seattl",{"_index":1192,"title":{"27":{"position":[[10,7]]}},"content":{"28":{"position":[[254,7],[506,7],[791,7],[1020,10],[2537,8],[4175,8]]},"29":{"position":[[66,7],[185,7]]},"30":{"position":[[8657,10],[10219,7]]}},"keywords":{}}],["seattle_loc",{"_index":1456,"title":{},"content":{"30":{"position":[[8535,11],[8668,12]]}},"keywords":{}}],["second",{"_index":134,"title":{},"content":{"3":{"position":[[15,6]]},"38":{"position":[[800,6]]},"40":{"position":[[2459,7]]},"52":{"position":[[193,6],[414,7]]},"57":{"position":[[89,6]]},"83":{"position":[[295,7]]},"85":{"position":[[116,6]]},"88":{"position":[[1713,6]]},"91":{"position":[[2729,6]]},"92":{"position":[[541,6]]},"97":{"position":[[5960,6]]},"103":{"position":[[586,7],[631,6],[1259,7]]},"106":{"position":[[517,7]]},"121":{"position":[[2183,8]]},"123":{"position":[[475,6],[682,7],[772,7]]},"125":{"position":[[7207,7]]},"127":{"position":[[460,7]]},"139":{"position":[[584,7]]},"161":{"position":[[1268,6]]},"165":{"position":[[1036,7]]},"173":{"position":[[719,7]]},"176":{"position":[[1094,7]]},"179":{"position":[[1092,6],[1196,6]]},"188":{"position":[[2363,6],[3180,6],[4144,7]]},"189":{"position":[[342,6]]},"190":{"position":[[440,7]]}},"keywords":{}}],["secret",{"_index":1464,"title":{},"content":{"30":{"position":[[8735,6]]},"60":{"position":[[115,6],[159,6],[201,7]]},"88":{"position":[[256,7]]},"93":{"position":[[3805,7]]}},"keywords":{}}],["section",{"_index":2455,"title":{},"content":{"64":{"position":[[377,7]]},"104":{"position":[[1526,8]]},"172":{"position":[[2662,9]]},"197":{"position":[[363,7],[509,7]]}},"keywords":{}}],["sector",{"_index":3194,"title":{},"content":{"93":{"position":[[825,7]]}},"keywords":{}}],["secur",{"_index":2366,"title":{},"content":{"61":{"position":[[1240,7]]},"195":{"position":[[882,8]]}},"keywords":{}}],["sed",{"_index":4125,"title":{},"content":{"125":{"position":[[5627,3]]}},"keywords":{}}],["see",{"_index":167,"title":{},"content":{"3":{"position":[[647,6]]},"4":{"position":[[479,6]]},"8":{"position":[[47,3]]},"22":{"position":[[1264,3]]},"25":{"position":[[129,3]]},"30":{"position":[[2270,3],[5534,3],[7111,3],[9229,4],[9261,3]]},"39":{"position":[[63,3],[1803,3]]},"40":{"position":[[88,3],[625,6],[2470,3],[3064,3]]},"41":{"position":[[356,3],[605,3]]},"43":{"position":[[230,3]]},"44":{"position":[[130,3],[390,3]]},"57":{"position":[[647,4]]},"69":{"position":[[82,3]]},"70":{"position":[[1269,3]]},"71":{"position":[[1041,3]]},"73":{"position":[[44,3],[470,3]]},"74":{"position":[[80,6],[809,6]]},"77":{"position":[[44,3]]},"83":{"position":[[33,3]]},"88":{"position":[[2220,4],[2406,3],[3568,3]]},"90":{"position":[[4955,3]]},"91":{"position":[[1417,3]]},"92":{"position":[[1479,3]]},"95":{"position":[[290,3]]},"96":{"position":[[992,3]]},"105":{"position":[[2535,4]]},"106":{"position":[[1000,6]]},"112":{"position":[[98,3],[171,3],[326,3],[873,3]]},"116":{"position":[[2627,6]]},"125":{"position":[[244,4],[8836,3],[11232,4]]},"127":{"position":[[1615,3]]},"134":{"position":[[225,3],[357,3]]},"135":{"position":[[329,3],[565,4]]},"136":{"position":[[1,4],[187,3]]},"152":{"position":[[602,3]]},"160":{"position":[[115,3]]},"173":{"position":[[1286,4]]},"176":{"position":[[252,6]]},"181":{"position":[[141,3],[263,3]]},"193":{"position":[[862,3]]}},"keywords":{}}],["seek",{"_index":875,"title":{"22":{"position":[[30,7]]}},"content":{},"keywords":{}}],["seem",{"_index":1283,"title":{},"content":{"28":{"position":[[2429,5],[2788,5],[4042,5],[4121,5]]},"30":{"position":[[2450,5],[2654,5],[4008,5],[7598,5]]},"41":{"position":[[131,4]]},"45":{"position":[[3484,5]]},"46":{"position":[[56,5]]},"50":{"position":[[81,5]]},"58":{"position":[[406,5]]},"97":{"position":[[6467,5]]},"165":{"position":[[1077,5]]},"170":{"position":[[352,5]]}},"keywords":{}}],["seen",{"_index":1290,"title":{},"content":{"28":{"position":[[2693,4]]},"58":{"position":[[217,4],[459,4],[496,4]]},"71":{"position":[[59,4]]},"72":{"position":[[479,4]]},"83":{"position":[[182,4],[326,4]]},"91":{"position":[[5950,4]]},"105":{"position":[[10,4]]},"106":{"position":[[1052,4]]}},"keywords":{}}],["seethi",{"_index":3923,"title":{},"content":{"121":{"position":[[2483,7]]}},"keywords":{}}],["segment",{"_index":4817,"title":{},"content":{"164":{"position":[[1413,7]]}},"keywords":{}}],["select",{"_index":1861,"title":{},"content":{"43":{"position":[[118,9]]},"45":{"position":[[1715,8]]},"51":{"position":[[2847,6],[2891,6],[2946,6],[3150,9]]},"76":{"position":[[2847,6]]}},"keywords":{}}],["self.articles.append(href",{"_index":900,"title":{},"content":{"22":{"position":[[569,26]]}},"keywords":{}}],["self.count",{"_index":955,"title":{},"content":{"22":{"position":[[1906,12],[1974,12],[2046,12],[2117,12],[2187,12],[2251,12]]}},"keywords":{}}],["self.dat",{"_index":3205,"title":{},"content":{"93":{"position":[[1616,10]]}},"keywords":{}}],["self.data",{"_index":936,"title":{},"content":{"22":{"position":[[1348,9]]}},"keywords":{}}],["self.data['crud",{"_index":961,"title":{},"content":{"22":{"position":[[2136,18]]}},"keywords":{}}],["self.data['d",{"_index":943,"title":{},"content":{"22":{"position":[[1567,17]]}},"keywords":{}}],["self.data['dow",{"_index":956,"title":{},"content":{"22":{"position":[[1925,16]]}},"keywords":{}}],["self.data['gold",{"_index":962,"title":{},"content":{"22":{"position":[[2206,17]]}},"keywords":{}}],["self.data['nasdaq",{"_index":960,"title":{},"content":{"22":{"position":[[2065,19]]}},"keywords":{}}],["self.data['s&p",{"_index":959,"title":{},"content":{"22":{"position":[[1993,20]]}},"keywords":{}}],["self.dates.append(match.group(0",{"_index":3209,"title":{},"content":{"93":{"position":[[1813,33]]}},"keywords":{}}],["self.earnings_offset",{"_index":3215,"title":{},"content":{"93":{"position":[[2072,20],[2141,20]]}},"keywords":{}}],["self.fetch_link",{"_index":893,"title":{},"content":{"22":{"position":[[422,16]]}},"keywords":{}}],["self.in_font_tag",{"_index":944,"title":{},"content":{"22":{"position":[[1592,16],[1885,17],[2299,16]]}},"keywords":{}}],["self.messag",{"_index":3404,"title":{},"content":{"97":{"position":[[3743,15],[5091,15],[5349,12],[5690,13]]}},"keywords":{}}],["self.message.clon",{"_index":3432,"title":{},"content":{"97":{"position":[[6087,23]]}},"keywords":{}}],["self.record_font_tag",{"_index":952,"title":{},"content":{"22":{"position":[[1764,21],[1827,21],[1859,21]]}},"keywords":{}}],["self.safe_float(cont",{"_index":957,"title":{},"content":{"22":{"position":[[1944,24],[2016,24],[2087,24],[2157,24],[2226,24]]}},"keywords":{}}],["self.store_d",{"_index":3207,"title":{},"content":{"93":{"position":[[1690,16],[1746,17],[2232,16]]}},"keywords":{}}],["self.x",{"_index":5343,"title":{},"content":{"197":{"position":[[471,6],[620,6]]}},"keywords":{}}],["self.x.to_str",{"_index":4298,"title":{},"content":{"129":{"position":[[1503,18]]}},"keywords":{}}],["sell",{"_index":1569,"title":{},"content":{"33":{"position":[[231,8]]},"40":{"position":[[1293,7]]},"164":{"position":[[1221,7]]}},"keywords":{}}],["semant",{"_index":3425,"title":{},"content":{"97":{"position":[[5482,9]]},"198":{"position":[[20,9],[39,9],[369,9],[885,10]]}},"keywords":{}}],["semest",{"_index":2245,"title":{},"content":{"53":{"position":[[1085,8]]},"88":{"position":[[102,8]]},"100":{"position":[[100,9]]}},"keywords":{}}],["send",{"_index":2384,"title":{},"content":{"61":{"position":[[1922,5]]},"96":{"position":[[910,4]]},"116":{"position":[[143,4],[2525,4],[2708,4],[3009,4],[3062,4]]},"117":{"position":[[357,4],[2121,4]]},"175":{"position":[[1222,4]]}},"keywords":{}}],["sens",{"_index":1169,"title":{},"content":{"26":{"position":[[149,5]]},"43":{"position":[[1190,5]]},"51":{"position":[[1597,5]]},"53":{"position":[[2041,6]]},"68":{"position":[[687,6]]},"106":{"position":[[918,5]]},"120":{"position":[[1047,5]]},"132":{"position":[[1026,5]]},"135":{"position":[[9,5]]},"175":{"position":[[720,5],[946,5]]}},"keywords":{}}],["sensit",{"_index":2385,"title":{},"content":{"61":{"position":[[1962,9]]},"158":{"position":[[26,9]]}},"keywords":{}}],["sent",{"_index":2388,"title":{},"content":{"61":{"position":[[2215,4]]},"115":{"position":[[1211,4],[1591,4],[2416,4],[2669,4]]},"116":{"position":[[1163,4],[1496,4],[2274,4]]}},"keywords":{}}],["sentenc",{"_index":2057,"title":{},"content":{"49":{"position":[[308,9]]},"51":{"position":[[3409,8]]},"52":{"position":[[63,8]]}},"keywords":{}}],["sentiment",{"_index":1167,"title":{"26":{"position":[[6,11]]}},"content":{"30":{"position":[[2878,9]]}},"keywords":{}}],["separ",{"_index":111,"title":{},"content":{"2":{"position":[[561,8],[652,8]]},"49":{"position":[[680,8]]},"100":{"position":[[166,10]]},"112":{"position":[[1352,9]]},"125":{"position":[[2289,8]]},"132":{"position":[[997,8]]},"188":{"position":[[643,8],[1876,8]]},"189":{"position":[[724,8]]}},"keywords":{}}],["septemb",{"_index":1262,"title":{},"content":{"28":{"position":[[1918,13]]},"30":{"position":[[1426,12]]}},"keywords":{}}],["sequenc",{"_index":4240,"title":{},"content":{"127":{"position":[[1107,8]]}},"keywords":{}}],["sequenti",{"_index":3742,"title":{},"content":{"113":{"position":[[1108,10]]}},"keywords":{}}],["seri",{"_index":4626,"title":{},"content":{"159":{"position":[[59,7]]},"160":{"position":[[427,6],[3200,6]]}},"keywords":{}}],["serial",{"_index":3751,"title":{"168":{"position":[[0,14]]}},"content":{"113":{"position":[[1525,9]]},"163":{"position":[[96,9]]},"164":{"position":[[276,9]]},"165":{"position":[[1008,13]]},"168":{"position":[[65,9]]},"169":{"position":[[85,10]]}},"keywords":{}}],["seriou",{"_index":1564,"title":{},"content":{"33":{"position":[[11,7]]},"40":{"position":[[2428,7]]}},"keywords":{}}],["serious",{"_index":3994,"title":{},"content":{"124":{"position":[[259,10]]},"129":{"position":[[1398,9]]}},"keywords":{}}],["serv",{"_index":129,"title":{},"content":{"2":{"position":[[849,6]]}},"keywords":{}}],["server",{"_index":2853,"title":{"94":{"position":[[23,6]]}},"content":{"88":{"position":[[692,6]]},"93":{"position":[[4107,6]]},"95":{"position":[[47,7]]},"97":{"position":[[6238,6]]},"125":{"position":[[4577,6],[4837,6]]}},"keywords":{}}],["server!"",{"_index":3333,"title":{},"content":{"96":{"position":[[777,16]]}},"keywords":{}}],["servic",{"_index":2364,"title":{},"content":{"61":{"position":[[1149,7]]}},"keywords":{}}],["session",{"_index":2403,"title":{},"content":{"62":{"position":[[458,7]]}},"keywords":{}}],["session.get(url.format(d.strftime(format_str",{"_index":2414,"title":{},"content":{"62":{"position":[[772,48]]}},"keywords":{}}],["set",{"_index":104,"title":{"111":{"position":[[8,7]]}},"content":{"2":{"position":[[426,9]]},"3":{"position":[[273,7],[763,7]]},"6":{"position":[[105,3]]},"7":{"position":[[304,3]]},"9":{"position":[[37,3]]},"11":{"position":[[37,3]]},"15":{"position":[[572,3]]},"32":{"position":[[1281,3]]},"33":{"position":[[850,3]]},"39":{"position":[[108,3]]},"44":{"position":[[1950,4]]},"45":{"position":[[2788,4]]},"61":{"position":[[1446,3]]},"62":{"position":[[25,3]]},"65":{"position":[[1658,3]]},"73":{"position":[[436,3]]},"74":{"position":[[1022,4]]},"75":{"position":[[420,3],[529,3],[610,3],[678,3],[756,3],[816,3],[894,3],[1017,3]]},"97":{"position":[[1363,3],[1646,3],[3792,3]]},"98":{"position":[[69,3]]},"102":{"position":[[1161,9]]},"103":{"position":[[1534,3]]},"109":{"position":[[27,3],[477,4]]},"111":{"position":[[27,3],[503,4]]},"112":{"position":[[1678,3]]},"113":{"position":[[48,3],[501,3],[1295,3],[1564,3]]},"125":{"position":[[4508,4],[4588,3]]},"173":{"position":[[662,7],[727,3],[782,7],[1855,3]]},"197":{"position":[[1072,3]]}},"keywords":{}}],["set([x",{"_index":2101,"title":{},"content":{"51":{"position":[[1209,6]]}},"keywords":{}}],["set(all_word",{"_index":2099,"title":{},"content":{"51":{"position":[[1179,14]]}},"keywords":{}}],["set_i",{"_index":3728,"title":{},"content":{"112":{"position":[[1544,7]]}},"keywords":{}}],["set_x",{"_index":3726,"title":{},"content":{"112":{"position":[[1522,8]]}},"keywords":{}}],["settl",{"_index":105,"title":{},"content":{"2":{"position":[[438,7]]}},"keywords":{}}],["setup",{"_index":3299,"title":{"95":{"position":[[4,6]]},"107":{"position":[[28,5]]}},"content":{"175":{"position":[[841,5]]}},"keywords":{}}],["sever",{"_index":3369,"title":{},"content":{"97":{"position":[[1035,6]]}},"keywords":{}}],["sexi",{"_index":2820,"title":{},"content":{"85":{"position":[[110,5]]}},"keywords":{}}],["shade",{"_index":3066,"title":{},"content":{"90":{"position":[[5016,6]]}},"keywords":{}}],["shaki",{"_index":4202,"title":{},"content":{"125":{"position":[[10659,5]]}},"keywords":{}}],["shape",{"_index":2606,"title":{},"content":{"70":{"position":[[1369,6]]},"161":{"position":[[895,7]]},"172":{"position":[[1538,5]]}},"keywords":{}}],["share",{"_index":1522,"title":{},"content":{"32":{"position":[[490,5],[542,5],[1095,5],[1127,6]]},"33":{"position":[[1267,6]]},"34":{"position":[[1480,6],[2515,6],[2632,6]]},"39":{"position":[[668,6],[740,6],[1727,6],[2080,6]]},"61":{"position":[[2049,5]]},"115":{"position":[[1866,6]]},"116":{"position":[[1771,6]]},"124":{"position":[[543,5]]},"125":{"position":[[367,5]]},"161":{"position":[[1664,7]]},"184":{"position":[[1080,6]]},"185":{"position":[[761,6]]}},"keywords":{}}],["sharp",{"_index":703,"title":{"19":{"position":[[16,6]]}},"content":{"17":{"position":[[32,6]]},"19":{"position":[[1,7],[182,7],[224,6],[279,6],[356,7]]},"20":{"position":[[871,6],[2761,6]]},"161":{"position":[[1401,5]]}},"keywords":{}}],["sharpe(returns[tick",{"_index":753,"title":{},"content":{"19":{"position":[[373,21]]}},"keywords":{}}],["sharpe_a",{"_index":812,"title":{},"content":{"20":{"position":[[1211,8],[1485,9]]}},"keywords":{}}],["sharpe_limit",{"_index":805,"title":{},"content":{"20":{"position":[[1057,13],[1497,12]]}},"keywords":{}}],["sharpes[tick",{"_index":814,"title":{},"content":{"20":{"position":[[1253,14]]}},"keywords":{}}],["shebang",{"_index":3881,"title":{},"content":{"121":{"position":[[547,8]]}},"keywords":{}}],["shell",{"_index":3678,"title":{},"content":{"108":{"position":[[863,6]]}},"keywords":{}}],["shift",{"_index":2689,"title":{},"content":{"76":{"position":[[568,5]]},"90":{"position":[[3609,5]]},"91":{"position":[[2910,5]]},"92":{"position":[[722,5]]}},"keywords":{}}],["shine",{"_index":4798,"title":{},"content":{"163":{"position":[[2240,7]]},"164":{"position":[[1204,7]]}},"keywords":{}}],["ship",{"_index":3312,"title":{},"content":{"95":{"position":[[472,4]]},"108":{"position":[[380,7]]}},"keywords":{}}],["shoot",{"_index":3888,"title":{},"content":{"121":{"position":[[930,5]]}},"keywords":{}}],["shootout",{"_index":4759,"title":{"162":{"position":[[14,8]]}},"content":{"163":{"position":[[2290,8]]}},"keywords":{}}],["short",{"_index":743,"title":{},"content":{"19":{"position":[[190,8]]},"20":{"position":[[110,5]]},"33":{"position":[[225,5]]},"103":{"position":[[771,6]]},"112":{"position":[[443,5]]},"118":{"position":[[32,6]]},"127":{"position":[[220,5]]},"152":{"position":[[98,5]]}},"keywords":{}}],["shortest",{"_index":5004,"title":{},"content":{"175":{"position":[[212,8]]}},"keywords":{}}],["shortwav",{"_index":5009,"title":{},"content":{"175":{"position":[[439,9]]}},"keywords":{}}],["shot",{"_index":2903,"title":{},"content":{"88":{"position":[[2379,4]]}},"keywords":{}}],["shouldn't",{"_index":1340,"title":{},"content":{"30":{"position":[[641,9]]},"96":{"position":[[391,9]]},"120":{"position":[[523,9]]},"188":{"position":[[4108,9]]}},"keywords":{}}],["shout",{"_index":213,"title":{},"content":{"3":{"position":[[1474,6]]}},"keywords":{}}],["show",{"_index":25,"title":{},"content":{"1":{"position":[[284,4]]},"2":{"position":[[305,7]]},"29":{"position":[[74,6]]},"30":{"position":[[146,4],[7880,4]]},"53":{"position":[[941,5]]},"83":{"position":[[436,5]]},"89":{"position":[[148,5]]},"116":{"position":[[916,4]]},"125":{"position":[[3420,7]]},"128":{"position":[[129,7],[349,7],[1019,4]]},"129":{"position":[[38,4]]},"135":{"position":[[152,4],[241,4]]},"156":{"position":[[572,5]]},"190":{"position":[[67,4]]},"194":{"position":[[747,4]]},"197":{"position":[[777,5]]}},"keywords":{}}],["show(f",{"_index":1279,"title":{},"content":{"28":{"position":[[2312,7],[3985,7]]},"30":{"position":[[2252,7],[3737,7],[3960,7],[5516,7],[6817,7],[7040,7]]}},"keywords":{}}],["shrink",{"_index":3056,"title":{},"content":{"90":{"position":[[4456,9],[4573,9],[4679,9]]}},"keywords":{}}],["shrink=0.05",{"_index":3050,"title":{},"content":{"90":{"position":[[4366,13]]}},"keywords":{}}],["side",{"_index":1676,"title":{"36":{"position":[[0,4]]}},"content":{"41":{"position":[[193,4]]},"88":{"position":[[699,5],[738,5]]},"93":{"position":[[4114,5],[4153,5]]},"118":{"position":[[177,4]]},"121":{"position":[[1064,5]]},"125":{"position":[[9936,4]]},"150":{"position":[[210,4]]}},"keywords":{}}],["sidenot",{"_index":3435,"title":{},"content":{"97":{"position":[[6301,9]]}},"keywords":{}}],["sigh",{"_index":2016,"title":{},"content":{"45":{"position":[[2491,7]]}},"keywords":{}}],["sigma}σr−rm",{"_index":738,"title":{},"content":{"19":{"position":[[29,14]]}},"keywords":{}}],["sign",{"_index":90,"title":{},"content":{"2":{"position":[[239,4]]},"40":{"position":[[1144,4],[1473,4]]}},"keywords":{}}],["signal",{"_index":3460,"title":{},"content":{"100":{"position":[[243,6]]},"102":{"position":[[735,7],[908,6],[985,7],[1296,7]]},"103":{"position":[[105,6],[950,6],[1159,6],[1675,6]]},"104":{"position":[[693,7],[706,6],[773,6],[987,7],[1270,6],[1348,6]]},"106":{"position":[[655,7],[1020,6],[1154,6]]},"173":{"position":[[1382,6],[1435,7]]}},"keywords":{}}],["signal_byt",{"_index":3582,"title":{},"content":{"105":{"position":[[616,12]]}},"keywords":{}}],["signalsif",{"_index":4965,"title":{},"content":{"173":{"position":[[1577,9]]}},"keywords":{}}],["signatur",{"_index":3399,"title":{},"content":{"97":{"position":[[3301,9]]}},"keywords":{}}],["signific",{"_index":1675,"title":{},"content":{"35":{"position":[[427,11]]},"164":{"position":[[1450,11]]}},"keywords":{}}],["significantli",{"_index":1287,"title":{},"content":{"28":{"position":[[2610,13]]},"40":{"position":[[3278,13]]},"73":{"position":[[122,13]]},"160":{"position":[[1885,13]]},"165":{"position":[[1437,13]]}},"keywords":{}}],["signs_match(article_df[[futur",{"_index":1081,"title":{},"content":{"24":{"position":[[2042,31]]},"25":{"position":[[1766,31]]}},"keywords":{}}],["signs_match(list_1",{"_index":1046,"title":{},"content":{"24":{"position":[[935,19]]},"25":{"position":[[655,19]]}},"keywords":{}}],["sim",{"_index":1756,"title":{},"content":{"39":{"position":[[2474,3]]}},"keywords":{}}],["sim_first_word(first_word_dist",{"_index":2159,"title":{},"content":{"51":{"position":[[3932,32]]},"52":{"position":[[161,31],[759,31]]}},"keywords":{}}],["sim_hashtags(1",{"_index":2177,"title":{},"content":{"52":{"position":[[367,15]]}},"keywords":{}}],["sim_hashtags(n",{"_index":2156,"title":{},"content":{"51":{"position":[[3832,15]]}},"keywords":{}}],["sim_hashtags(n_hash",{"_index":2188,"title":{},"content":{"52":{"position":[[831,20]]}},"keywords":{}}],["sim_n_hashtags(hashtag_freq",{"_index":2154,"title":{},"content":{"51":{"position":[[3759,29]]}},"keywords":{}}],["sim_n_hashtags(ml",{"_index":2187,"title":{},"content":{"52":{"position":[[800,19]]}},"keywords":{}}],["sim_next_word(curr",{"_index":2163,"title":{},"content":{"51":{"position":[[4082,22]]},"52":{"position":[[1051,22]]}},"keywords":{}}],["sim_next_word(first",{"_index":2171,"title":{},"content":{"52":{"position":[[202,20]]}},"keywords":{}}],["sim_next_word(fourth",{"_index":2176,"title":{},"content":{"52":{"position":[[324,21]]}},"keywords":{}}],["sim_next_word(second",{"_index":2172,"title":{},"content":{"52":{"position":[[242,21]]}},"keywords":{}}],["sim_next_word(third",{"_index":2174,"title":{},"content":{"52":{"position":[[284,20]]}},"keywords":{}}],["sim_seri",{"_index":1759,"title":{},"content":{"39":{"position":[[2605,10]]}},"keywords":{}}],["sim_series.apply(lambda",{"_index":1763,"title":{},"content":{"39":{"position":[[2686,23],[2745,23],[2810,23],[2876,23],[2989,23]]}},"keywords":{}}],["sim_summari",{"_index":1643,"title":{},"content":{"34":{"position":[[2698,11]]}},"keywords":{}}],["sim_summary(invest",{"_index":1661,"title":{},"content":{"34":{"position":[[3379,24],[3770,24]]}},"keywords":{}}],["similar",{"_index":626,"title":{},"content":{"14":{"position":[[61,7]]},"15":{"position":[[43,7]]},"30":{"position":[[7885,7]]},"92":{"position":[[1308,8]]},"104":{"position":[[1964,8]]},"112":{"position":[[935,8]]},"117":{"position":[[2044,7]]},"128":{"position":[[1028,7]]},"129":{"position":[[2756,7]]},"160":{"position":[[408,7]]},"186":{"position":[[166,7]]}},"keywords":{}}],["similarli",{"_index":4569,"title":{},"content":{"155":{"position":[[815,10]]},"158":{"position":[[233,10]]}},"keywords":{}}],["simpl",{"_index":1686,"title":{"166":{"position":[[0,6]]}},"content":{"38":{"position":[[38,6]]},"93":{"position":[[1097,6]]},"96":{"position":[[327,7],[586,7]]},"103":{"position":[[807,7]]},"109":{"position":[[120,6]]},"125":{"position":[[216,6],[3918,7]]},"160":{"position":[[4034,7]]},"163":{"position":[[32,6]]},"188":{"position":[[4068,7]]},"193":{"position":[[889,6]]}},"keywords":{}}],["simple_refer",{"_index":5335,"title":{},"content":{"196":{"position":[[1530,18]]}},"keywords":{}}],["simpler",{"_index":375,"title":{},"content":{"7":{"position":[[16,8]]},"97":{"position":[[2326,7]]},"125":{"position":[[5743,8]]},"165":{"position":[[275,7]]},"190":{"position":[[690,7]]}},"keywords":{}}],["simplest",{"_index":4841,"title":{},"content":{"166":{"position":[[263,8]]},"184":{"position":[[44,8]]},"192":{"position":[[5,8]]},"196":{"position":[[743,8]]}},"keywords":{}}],["simpli",{"_index":1981,"title":{},"content":{"45":{"position":[[1311,6]]},"68":{"position":[[22,7]]},"86":{"position":[[206,6]]},"97":{"position":[[1639,6]]},"102":{"position":[[176,7]]},"139":{"position":[[688,6]]},"160":{"position":[[3070,7]]},"188":{"position":[[5,7]]},"193":{"position":[[722,7]]},"196":{"position":[[481,6]]}},"keywords":{}}],["simplifi",{"_index":4217,"title":{},"content":{"125":{"position":[[11549,8]]}},"keywords":{}}],["simul",{"_index":304,"title":{"6":{"position":[[11,11]]},"7":{"position":[[13,11]]},"8":{"position":[[8,11]]},"11":{"position":[[20,11]]},"12":{"position":[[6,11]]},"13":{"position":[[7,11]]},"14":{"position":[[23,11]]},"15":{"position":[[20,11]]},"34":{"position":[[12,11]]},"39":{"position":[[10,11]]},"73":{"position":[[0,9]]},"75":{"position":[[15,9]]},"84":{"position":[[17,9]]},"85":{"position":[[4,9]]}},"content":{"6":{"position":[[54,8],[116,10],[235,11],[639,11],[746,8],[941,10],[1013,11],[1076,10]]},"7":{"position":[[28,8],[156,10],[235,10]]},"8":{"position":[[33,10]]},"11":{"position":[[83,11],[187,8],[305,11]]},"12":{"position":[[201,11],[614,11],[660,11]]},"13":{"position":[[39,11],[1573,10],[1596,10],[1731,12],[1929,10],[1954,10],[1985,10],[2010,10],[2041,10],[2066,10],[2097,10],[2122,10],[2153,10],[2178,10],[2213,12]]},"14":{"position":[[1201,11],[2656,10],[2679,10],[2814,12],[3001,10],[3026,10],[3057,10],[3082,10],[3113,10],[3138,10],[3169,10],[3194,10],[3225,10],[3250,10],[3285,12]]},"15":{"position":[[583,11],[2330,10],[2353,10],[2488,12],[2672,10],[2697,10],[2728,10],[2753,10],[2784,10],[2809,10],[2840,10],[2865,10],[2896,10],[2921,10],[2956,12]]},"34":{"position":[[787,9],[1386,11],[1586,8],[1824,10],[3046,11],[3252,10]]},"39":{"position":[[119,10]]},"41":{"position":[[617,11]]},"51":{"position":[[2164,8],[3512,8]]},"52":{"position":[[52,8],[563,8],[586,8],[618,8]]},"73":{"position":[[275,9],[512,9],[620,9]]},"75":{"position":[[63,9]]},"78":{"position":[[952,9]]},"79":{"position":[[156,9]]},"80":{"position":[[178,9]]},"81":{"position":[[157,9]]},"82":{"position":[[956,9]]},"85":{"position":[[54,9],[473,9]]},"86":{"position":[[381,9],[478,9]]}},"keywords":{}}],["simulate("yahoo/lmt"",{"_index":1657,"title":{},"content":{"34":{"position":[[3312,31],[3703,31]]}},"keywords":{}}],["simulate_casino([1/3",{"_index":2781,"title":{},"content":{"79":{"position":[[65,21]]},"80":{"position":[[87,21]]}},"keywords":{}}],["simulate_casino([1/9",{"_index":2788,"title":{},"content":{"82":{"position":[[166,21]]}},"keywords":{}}],["simulate_casino([2/9",{"_index":2774,"title":{},"content":{"78":{"position":[[798,21]]}},"keywords":{}}],["simulate_casino(d1_dist",{"_index":2747,"title":{},"content":{"78":{"position":[[115,24]]}},"keywords":{}}],["simulate_casino(np.repeat(1/6",{"_index":2785,"title":{},"content":{"81":{"position":[[100,30]]}},"keywords":{}}],["simulate_day(open_v",{"_index":1729,"title":{},"content":{"39":{"position":[[994,23]]}},"keywords":{}}],["simulate_day(ticker_info[d:]["open"",{"_index":1757,"title":{},"content":{"39":{"position":[[2484,47]]}},"keywords":{}}],["simulate_gbm",{"_index":387,"title":{},"content":{"7":{"position":[[262,12]]}},"keywords":{}}],["simulate_gbm(final_motion[:,end",{"_index":532,"title":{},"content":{"12":{"position":[[413,33]]}},"keywords":{}}],["simulate_gbm(full_motion[:,end",{"_index":521,"title":{},"content":{"11":{"position":[[455,32]]}},"keywords":{}}],["simulate_gbm(initi",{"_index":450,"title":{},"content":{"8":{"position":[[173,21]]}},"keywords":{}}],["simulate_tickers(["yahoo/fb"",{"_index":1786,"title":{},"content":{"40":{"position":[[118,39]]}},"keywords":{}}],["simulate_tickers(["yahoo/x"",{"_index":1815,"title":{},"content":{"40":{"position":[[1652,38]]}},"keywords":{}}],["simulate_tickers(['yahoo/regn",{"_index":1826,"title":{},"content":{"40":{"position":[[2620,31]]}},"keywords":{}}],["simulate_tickers(tick",{"_index":1773,"title":{},"content":{"39":{"position":[[3040,26]]}},"keywords":{}}],["simulate_ts(nam",{"_index":1743,"title":{},"content":{"39":{"position":[[2146,17]]}},"keywords":{}}],["simulate_ts(tick",{"_index":1776,"title":{},"content":{"39":{"position":[[3175,19]]}},"keywords":{}}],["simulate_tweet",{"_index":2184,"title":{},"content":{"52":{"position":[[711,17]]}},"keywords":{}}],["simulatem",{"_index":348,"title":{},"content":{"6":{"position":[[678,10]]}},"keywords":{}}],["simulaten",{"_index":349,"title":{},"content":{"6":{"position":[[712,10]]}},"keywords":{}}],["simultan",{"_index":5196,"title":{},"content":{"188":{"position":[[2812,15]]}},"keywords":{}}],["sin",{"_index":2265,"title":{},"content":{"53":{"position":[[1343,3]]}},"keywords":{}}],["since2014",{"_index":4803,"title":{},"content":{"164":{"position":[[189,12]]}},"keywords":{}}],["sine",{"_index":59,"title":{},"content":{"1":{"position":[[673,4]]}},"keywords":{}}],["singer",{"_index":3556,"title":{},"content":{"104":{"position":[[535,8]]}},"keywords":{}}],["singl",{"_index":376,"title":{},"content":{"7":{"position":[[39,6]]},"32":{"position":[[263,6]]},"33":{"position":[[602,6]]},"52":{"position":[[136,6]]},"65":{"position":[[344,6]]},"97":{"position":[[8,6]]},"120":{"position":[[823,6],[846,6]]},"164":{"position":[[499,6]]},"167":{"position":[[216,6]]},"183":{"position":[[5,6]]}},"keywords":{}}],["site",{"_index":4728,"title":{},"content":{"161":{"position":[[317,4]]}},"keywords":{}}],["situat",{"_index":4427,"title":{},"content":{"139":{"position":[[672,10]]},"160":{"position":[[1524,10],[2702,10]]},"197":{"position":[[1471,10]]}},"keywords":{}}],["size",{"_index":3483,"title":{},"content":{"101":{"position":[[676,4]]},"105":{"position":[[299,5],[3097,5],[3295,4],[3381,4]]},"141":{"position":[[148,5],[350,5]]},"146":{"position":[[345,4],[432,5]]},"153":{"position":[[810,4]]},"155":{"position":[[176,5]]},"156":{"position":[[70,5]]},"160":{"position":[[1869,4]]},"163":{"position":[[177,4]]},"165":{"position":[[1278,5],[1336,4]]},"170":{"position":[[411,5]]},"175":{"position":[[1336,4],[1697,5]]},"194":{"position":[[467,4],[490,4]]},"195":{"position":[[76,4],[552,4]]}},"keywords":{}}],["skew",{"_index":1378,"title":{},"content":{"30":{"position":[[2742,4]]},"71":{"position":[[1201,7]]}},"keywords":{}}],["skill",{"_index":37,"title":{},"content":{"1":{"position":[[420,6]]}},"keywords":{}}],["skip",{"_index":1710,"title":{},"content":{"39":{"position":[[228,4]]},"59":{"position":[[236,4]]},"61":{"position":[[2078,7]]},"104":{"position":[[1539,4]]},"121":{"position":[[1303,4],[1523,8]]},"125":{"position":[[1702,4],[2535,4]]},"174":{"position":[[898,4],[1173,4]]}},"keywords":{}}],["sklearn.cross_valid",{"_index":2040,"title":{},"content":{"47":{"position":[[53,24]]}},"keywords":{}}],["sklearn.decomposit",{"_index":1991,"title":{},"content":{"45":{"position":[[1949,21]]},"103":{"position":[[821,21]]}},"keywords":{}}],["sklearn.naive_bay",{"_index":1989,"title":{},"content":{"45":{"position":[[1906,19]]}},"keywords":{}}],["sklearn.preprocess",{"_index":1912,"title":{},"content":{"44":{"position":[[564,21]]}},"keywords":{}}],["slack",{"_index":3999,"title":{},"content":{"124":{"position":[[509,5]]}},"keywords":{}}],["slb",{"_index":714,"title":{},"content":{"17":{"position":[[183,6]]},"18":{"position":[[300,6]]},"19":{"position":[[524,6]]},"20":{"position":[[444,6],[2932,7]]}},"keywords":{}}],["sleep",{"_index":3980,"title":{},"content":{"123":{"position":[[693,5]]}},"keywords":{}}],["slice",{"_index":2852,"title":{},"content":{"88":{"position":[[684,7]]},"93":{"position":[[4099,7]]}},"keywords":{}}],["slightli",{"_index":1175,"title":{},"content":{"26":{"position":[[650,8]]},"30":{"position":[[7572,8]]},"45":{"position":[[966,8]]},"75":{"position":[[477,8]]},"182":{"position":[[61,8]]},"193":{"position":[[3075,8]]}},"keywords":{}}],["slow",{"_index":3847,"title":{"120":{"position":[[0,4]]}},"content":{"176":{"position":[[1071,4]]}},"keywords":{}}],["slowit'",{"_index":4414,"title":{},"content":{"139":{"position":[[136,8]]}},"keywords":{}}],["small",{"_index":826,"title":{"63":{"position":[[25,5]]}},"content":{"20":{"position":[[1687,5]]},"40":{"position":[[1136,7]]},"61":{"position":[[1271,5]]},"63":{"position":[[54,6]]},"74":{"position":[[1346,5]]},"83":{"position":[[536,5]]},"89":{"position":[[799,5]]},"97":{"position":[[6232,5]]},"103":{"position":[[394,5]]},"104":{"position":[[871,5],[1440,5]]},"105":{"position":[[130,5]]},"106":{"position":[[773,5],[800,5]]},"113":{"position":[[202,6]]},"150":{"position":[[29,5],[677,5],[736,5]]},"160":{"position":[[2840,6]]},"175":{"position":[[94,5]]},"181":{"position":[[577,5]]}},"keywords":{}}],["small(u8",{"_index":5312,"title":{},"content":{"194":{"position":[[233,10]]}},"keywords":{}}],["smaller",{"_index":1703,"title":{},"content":{"38":{"position":[[1076,7]]},"93":{"position":[[709,7]]},"102":{"position":[[1315,7]]},"105":{"position":[[3281,7]]},"163":{"position":[[689,7]]}},"keywords":{}}],["smallvec",{"_index":4832,"title":{},"content":{"165":{"position":[[895,8]]}},"keywords":{}}],["smart",{"_index":4556,"title":{"155":{"position":[[0,5]]}},"content":{"155":{"position":[[224,5],[496,5],[622,5],[911,5],[1032,5],[1056,5]]},"156":{"position":[[274,5]]},"157":{"position":[[358,5]]},"159":{"position":[[597,5],[747,5],[963,5],[1125,5]]}},"keywords":{}}],["smarter",{"_index":3809,"title":{},"content":{"116":{"position":[[2369,7]]}},"keywords":{}}],["smell",{"_index":5106,"title":{},"content":{"181":{"position":[[1037,6]]}},"keywords":{}}],["smooth",{"_index":1847,"title":{},"content":{"40":{"position":[[3735,7]]}},"keywords":{}}],["smoother",{"_index":1820,"title":{},"content":{"40":{"position":[[2183,8]]}},"keywords":{}}],["snippet",{"_index":4438,"title":{},"content":{"141":{"position":[[223,7]]}},"keywords":{}}],["socket",{"_index":4956,"title":{},"content":{"173":{"position":[[975,7]]}},"keywords":{}}],["sole",{"_index":5,"title":{},"content":{"1":{"position":[[5,4]]},"169":{"position":[[229,6]]}},"keywords":{}}],["solut",{"_index":161,"title":{},"content":{"3":{"position":[[544,8]]},"74":{"position":[[257,8]]},"125":{"position":[[1305,9],[1850,9],[4747,9],[5011,9]]},"190":{"position":[[856,8]]}},"keywords":{}}],["solv",{"_index":253,"title":{},"content":{"4":{"position":[[713,6]]},"85":{"position":[[191,6]]},"86":{"position":[[87,5],[776,5]]},"125":{"position":[[883,7],[1128,7]]},"143":{"position":[[29,5]]}},"keywords":{}}],["solver",{"_index":2829,"title":{},"content":{"86":{"position":[[571,6]]}},"keywords":{}}],["someon",{"_index":1434,"title":{},"content":{"30":{"position":[[7639,7]]},"65":{"position":[[1437,7]]},"120":{"position":[[43,7]]},"125":{"position":[[1115,7],[2110,7],[10778,7]]}},"keywords":{}}],["somesuch",{"_index":4504,"title":{},"content":{"150":{"position":[[803,8]]}},"keywords":{}}],["someth",{"_index":91,"title":{"86":{"position":[[8,9]]}},"content":{"2":{"position":[[244,9]]},"4":{"position":[[1067,9]]},"20":{"position":[[1677,9]]},"30":{"position":[[9568,9]]},"43":{"position":[[818,9]]},"49":{"position":[[537,9]]},"53":{"position":[[13,9]]},"54":{"position":[[172,9]]},"76":{"position":[[851,9],[1165,9]]},"96":{"position":[[443,9]]},"97":{"position":[[383,9],[716,9],[2713,9],[3255,9],[3523,9]]},"103":{"position":[[1569,10],[2244,9]]},"104":{"position":[[1954,9]]},"105":{"position":[[205,9],[2848,9],[3040,9]]},"112":{"position":[[780,9]]},"115":{"position":[[92,9],[3059,9]]},"116":{"position":[[187,9]]},"117":{"position":[[951,9]]},"120":{"position":[[388,9]]},"125":{"position":[[3342,9],[6382,9],[6801,9],[7157,9]]},"134":{"position":[[361,9]]},"160":{"position":[[4248,9]]},"165":{"position":[[1089,9]]},"173":{"position":[[1696,9]]},"179":{"position":[[1776,9]]}},"keywords":{}}],["sometim",{"_index":3150,"title":{},"content":{"91":{"position":[[3737,9]]},"152":{"position":[[318,9]]}},"keywords":{}}],["somewher",{"_index":3564,"title":{},"content":{"104":{"position":[[1025,10]]},"112":{"position":[[485,9]]},"115":{"position":[[218,9]]},"116":{"position":[[318,9]]},"117":{"position":[[1107,9]]},"128":{"position":[[845,9]]}},"keywords":{}}],["song",{"_index":3500,"title":{},"content":{"103":{"position":[[42,4]]}},"keywords":{}}],["soon",{"_index":1190,"title":{},"content":{"26":{"position":[[918,5]]},"29":{"position":[[448,5]]},"30":{"position":[[7991,5]]},"46":{"position":[[581,5]]},"175":{"position":[[1549,4]]}},"keywords":{}}],["sophist",{"_index":457,"title":{},"content":{"9":{"position":[[82,13]]},"45":{"position":[[1482,13]]}},"keywords":{}}],["sore",{"_index":2211,"title":{},"content":{"53":{"position":[[445,4]]}},"keywords":{}}],["sorri",{"_index":3925,"title":{},"content":{"121":{"position":[[2570,6]]}},"keywords":{}}],["sort",{"_index":999,"title":{},"content":{"23":{"position":[[236,6]]},"36":{"position":[[151,5]]},"93":{"position":[[387,4]]}},"keywords":{}}],["sound",{"_index":3541,"title":{},"content":{"103":{"position":[[1871,5],[2209,5]]},"105":{"position":[[220,6],[2673,6],[2807,6],[3386,6]]},"106":{"position":[[441,5]]},"199":{"position":[[735,6]]}},"keywords":{}}],["sourc",{"_index":4726,"title":{},"content":{"161":{"position":[[175,6]]}},"keywords":{}}],["space",{"_index":2138,"title":{},"content":{"51":{"position":[[2995,5]]},"52":{"position":[[679,5]]},"85":{"position":[[218,5]]},"101":{"position":[[282,6],[897,6],[1058,6]]},"102":{"position":[[301,6]]},"105":{"position":[[409,5],[2618,5]]},"106":{"position":[[216,6],[303,5],[352,5]]},"130":{"position":[[201,5]]},"140":{"position":[[207,5]]},"141":{"position":[[297,5]]},"142":{"position":[[108,5]]},"145":{"position":[[221,5]]},"155":{"position":[[1198,5]]},"195":{"position":[[422,5]]}},"keywords":{}}],["span",{"_index":937,"title":{},"content":{"22":{"position":[[1412,6]]},"125":{"position":[[2457,4]]}},"keywords":{}}],["sparsiti",{"_index":1932,"title":{},"content":{"44":{"position":[[1076,8]]}},"keywords":{}}],["speak",{"_index":4605,"title":{},"content":{"157":{"position":[[30,5]]}},"keywords":{}}],["speaker",{"_index":65,"title":{},"content":{"1":{"position":[[720,9]]}},"keywords":{}}],["spec",{"_index":4092,"title":{},"content":{"125":{"position":[[4204,5]]}},"keywords":{}}],["special",{"_index":665,"title":{},"content":{"15":{"position":[[98,7]]},"49":{"position":[[182,7]]},"61":{"position":[[796,7]]},"68":{"position":[[826,7],[952,7]]},"127":{"position":[[156,7]]},"160":{"position":[[388,7]]},"174":{"position":[[1263,11]]},"188":{"position":[[325,7]]},"189":{"position":[[216,7]]}},"keywords":{}}],["specif",{"_index":66,"title":{"172":{"position":[[9,9]]}},"content":{"1":{"position":[[732,12]]},"3":{"position":[[1287,8]]},"4":{"position":[[133,8]]},"20":{"position":[[886,8]]},"28":{"position":[[2546,12],[4184,12]]},"51":{"position":[[3233,8],[3468,8]]},"61":{"position":[[1984,13]]},"74":{"position":[[89,8],[821,8]]},"88":{"position":[[2067,8]]},"89":{"position":[[21,8]]},"93":{"position":[[809,8]]},"96":{"position":[[195,14]]},"97":{"position":[[333,8]]},"117":{"position":[[873,8]]},"120":{"position":[[287,12]]},"123":{"position":[[1,12]]},"125":{"position":[[4440,13]]},"127":{"position":[[178,8],[823,13]]},"133":{"position":[[215,13]]},"135":{"position":[[591,12]]},"155":{"position":[[384,12]]},"160":{"position":[[1515,8],[2225,8],[3478,8]]},"165":{"position":[[1288,12]]},"172":{"position":[[2573,8]]},"181":{"position":[[867,14]]},"196":{"position":[[82,9]]}},"keywords":{}}],["specifi",{"_index":3708,"title":{},"content":{"111":{"position":[[648,9],[752,7]]}},"keywords":{}}],["specificationdramat",{"_index":4018,"title":{},"content":{"125":{"position":[[538,25]]}},"keywords":{}}],["specificationref",{"_index":5087,"title":{},"content":{"179":{"position":[[1644,19]]}},"keywords":{}}],["spectr",{"_index":4976,"title":{},"content":{"174":{"position":[[101,8]]}},"keywords":{}}],["specul",{"_index":4974,"title":{},"content":{"174":{"position":[[29,11],[197,10]]}},"keywords":{}}],["speech",{"_index":2290,"title":{},"content":{"54":{"position":[[108,7]]}},"keywords":{}}],["speed",{"_index":2835,"title":{},"content":{"86":{"position":[[1083,5]]},"100":{"position":[[372,6]]},"132":{"position":[[963,6]]},"172":{"position":[[2447,5]]},"176":{"position":[[1651,6]]},"178":{"position":[[454,6]]},"198":{"position":[[313,5]]}},"keywords":{}}],["speic",{"_index":3688,"title":{},"content":{"109":{"position":[[339,6]]},"161":{"position":[[347,6]]}},"keywords":{}}],["spend",{"_index":244,"title":{},"content":{"4":{"position":[[544,8],[1273,8]]},"46":{"position":[[7,8]]},"97":{"position":[[2095,5]]},"121":{"position":[[751,5]]},"135":{"position":[[184,6]]},"139":{"position":[[435,5],[719,5]]},"157":{"position":[[55,8]]}},"keywords":{}}],["spent",{"_index":4000,"title":{},"content":{"124":{"position":[[652,5]]}},"keywords":{}}],["spi",{"_index":1004,"title":{},"content":{"23":{"position":[[364,3]]},"24":{"position":[[2518,3],[2670,3]]},"25":{"position":[[2241,3],[2393,3]]}},"keywords":{}}],["spin",{"_index":4852,"title":{},"content":{"167":{"position":[[85,5]]}},"keywords":{}}],["split",{"_index":1862,"title":{},"content":{"43":{"position":[[172,6]]},"47":{"position":[[14,5]]},"93":{"position":[[4557,5]]},"112":{"position":[[1258,6]]}},"keywords":{}}],["spoiler",{"_index":3805,"title":{},"content":{"116":{"position":[[863,7]]}},"keywords":{}}],["spontan",{"_index":4505,"title":{},"content":{"150":{"position":[[855,13]]}},"keywords":{}}],["sporad",{"_index":1281,"title":{},"content":{"28":{"position":[[2410,9]]}},"keywords":{}}],["spot",{"_index":4385,"title":{},"content":{"136":{"position":[[202,4]]}},"keywords":{}}],["springr",{"_index":2267,"title":{},"content":{"53":{"position":[[1359,7]]}},"keywords":{}}],["spy_close_ret",{"_index":1140,"title":{},"content":{"25":{"position":[[469,13],[1402,14]]}},"keywords":{}}],["spy_open_ret",{"_index":1038,"title":{},"content":{"24":{"position":[[753,12],[1682,13]]}},"keywords":{}}],["squar",{"_index":2019,"title":{},"content":{"45":{"position":[[2560,6]]},"193":{"position":[[1487,7],[1512,7],[1522,7],[2648,7],[2673,7],[2683,7],[3411,7],[3436,7],[3446,7],[3725,7],[3750,7],[3760,7]]}},"keywords":{}}],["src/main.r",{"_index":3730,"title":{},"content":{"113":{"position":[[273,12]]}},"keywords":{}}],["src/main.rs:18:40",{"_index":3423,"title":{},"content":{"97":{"position":[[5035,17]]}},"keywords":{}}],["src/main.rs:31:18",{"_index":3778,"title":{},"content":{"115":{"position":[[1101,17],[1448,17],[1731,17],[2189,17]]}},"keywords":{}}],["src/main.rs:33:18",{"_index":3808,"title":{},"content":{"116":{"position":[[1053,17],[1353,17],[1636,17],[2047,17]]}},"keywords":{}}],["src_prefix",{"_index":3709,"title":{},"content":{"111":{"position":[[678,12]]}},"keywords":{}}],["src_prefix("schema"",{"_index":3703,"title":{},"content":{"111":{"position":[[369,31]]}},"keywords":{}}],["stabil",{"_index":4208,"title":{},"content":{"125":{"position":[[11273,10]]}},"keywords":{}}],["stabl",{"_index":3952,"title":{},"content":{"122":{"position":[[1024,7]]},"148":{"position":[[237,6]]}},"keywords":{}}],["stack",{"_index":1198,"title":{},"content":{"28":{"position":[[69,7]]},"121":{"position":[[1308,5],[1541,5]]},"140":{"position":[[144,5]]},"152":{"position":[[197,5]]},"153":{"position":[[818,5],[941,5]]},"157":{"position":[[43,5],[154,5],[392,5]]},"159":{"position":[[556,5],[698,5],[771,5],[929,5]]},"192":{"position":[[77,5],[747,6]]},"193":{"position":[[487,5],[1215,5],[1671,5],[3141,5]]},"195":{"position":[[36,5],[455,6],[546,5],[684,5],[732,7],[781,5],[1079,6]]},"196":{"position":[[558,5],[872,5],[1333,5]]},"197":{"position":[[259,5]]},"198":{"position":[[383,5],[409,5],[436,5]]},"199":{"position":[[765,5],[843,6],[1657,5]]}},"keywords":{}}],["stack.struct",{"_index":4632,"title":{},"content":{"159":{"position":[[636,14]]}},"keywords":{}}],["stack/heap",{"_index":4678,"title":{},"content":{"160":{"position":[[1585,10]]}},"keywords":{}}],["stagger",{"_index":4649,"title":{},"content":{"160":{"position":[[208,10]]}},"keywords":{}}],["stake",{"_index":2615,"title":{},"content":{"72":{"position":[[243,6]]},"101":{"position":[[792,6]]}},"keywords":{}}],["stand",{"_index":1698,"title":{},"content":{"38":{"position":[[785,9],[899,7]]}},"keywords":{}}],["standard",{"_index":741,"title":{},"content":{"19":{"position":[[146,8]]},"22":{"position":[[870,8]]},"90":{"position":[[5043,8]]},"91":{"position":[[4843,8],[5841,8]]},"92":{"position":[[1511,8]]},"120":{"position":[[120,8]]},"155":{"position":[[587,8]]},"156":{"position":[[1767,8]]},"157":{"position":[[341,8]]},"159":{"position":[[1147,8]]}},"keywords":{}}],["start",{"_index":3,"title":{"1":{"position":[[0,8]]},"109":{"position":[[8,8]]}},"content":{"1":{"position":[[10,8],[214,5]]},"9":{"position":[[51,5],[649,6],[760,5]]},"11":{"position":[[61,5]]},"30":{"position":[[2524,5],[7714,5],[9723,8],[10173,8],[10227,8],[10277,8],[10328,8]]},"32":{"position":[[46,5]]},"34":{"position":[[1612,6]]},"38":{"position":[[681,5],[1323,5]]},"39":{"position":[[146,5],[2164,6],[3133,5],[3195,6]]},"40":{"position":[[7,5]]},"41":{"position":[[315,5],[429,5]]},"43":{"position":[[449,5],[1217,5]]},"46":{"position":[[657,7]]},"49":{"position":[[84,8]]},"50":{"position":[[245,5]]},"51":{"position":[[333,5]]},"58":{"position":[[11,8],[108,5]]},"65":{"position":[[1923,8],[2065,8]]},"75":{"position":[[127,5]]},"76":{"position":[[4,5],[1973,5]]},"77":{"position":[[128,5]]},"78":{"position":[[225,5],[410,7]]},"82":{"position":[[132,5]]},"86":{"position":[[349,8]]},"88":{"position":[[588,6],[2456,6]]},"91":{"position":[[4327,5],[5746,5]]},"93":{"position":[[4003,6]]},"96":{"position":[[600,5],[1367,5]]},"97":{"position":[[703,5],[1171,5],[2491,7]]},"98":{"position":[[311,8]]},"101":{"position":[[530,7]]},"102":{"position":[[1347,5]]},"103":{"position":[[557,5],[603,5],[1685,7]]},"110":{"position":[[16,5],[154,5],[285,8]]},"113":{"position":[[112,5],[811,5]]},"120":{"position":[[28,5]]},"125":{"position":[[2825,8],[3162,5],[3228,8],[3842,6],[6332,8],[6408,5],[6672,5],[6834,5],[6920,6],[7407,8],[7496,8],[10115,8],[11562,5]]},"129":{"position":[[2815,7]]},"132":{"position":[[14,7]]},"160":{"position":[[2758,6],[2954,5]]},"161":{"position":[[16,7]]},"164":{"position":[[254,7]]},"188":{"position":[[2144,5],[2878,7],[2952,7],[3235,5]]},"189":{"position":[[2320,6],[2589,8]]},"192":{"position":[[262,8]]},"193":{"position":[[1768,5],[2723,5]]},"196":{"position":[[1106,5]]}},"keywords":{}}],["start_dat",{"_index":1001,"title":{},"content":{"23":{"position":[[277,10]]},"62":{"position":[[570,10]]},"90":{"position":[[3715,10],[3820,11]]}},"keywords":{}}],["start_date=start.strftime(q_format",{"_index":2857,"title":{},"content":{"88":{"position":[[810,36]]},"93":{"position":[[4225,36]]}},"keywords":{}}],["started"",{"_index":200,"title":{},"content":{"3":{"position":[[1230,13]]}},"keywords":{}}],["starter",{"_index":4131,"title":{},"content":{"125":{"position":[[6255,7],[7018,7]]}},"keywords":{}}],["state",{"_index":390,"title":{},"content":{"7":{"position":[[320,5],[405,6]]},"72":{"position":[[623,6]]},"95":{"position":[[412,5]]},"97":{"position":[[5497,5]]},"175":{"position":[[1022,6]]}},"keywords":{}}],["statement",{"_index":3274,"title":{},"content":{"93":{"position":[[4575,10]]}},"keywords":{}}],["static",{"_index":3344,"title":{"182":{"position":[[0,6]]}},"content":{"96":{"position":[[1474,6]]},"97":{"position":[[1135,6],[2009,8],[2535,7],[3094,6]]},"117":{"position":[[1534,7]]},"125":{"position":[[4825,6]]},"127":{"position":[[601,6],[1251,6]]},"129":{"position":[[1254,6],[1738,7]]},"133":{"position":[[306,6]]},"144":{"position":[[135,6]]},"145":{"position":[[111,6]]},"146":{"position":[[139,6]]},"152":{"position":[[1148,6],[1191,6]]},"156":{"position":[[1231,6],[1274,6]]},"182":{"position":[[1,6],[171,6],[205,7],[285,6],[381,7],[417,6],[486,6],[574,6],[681,6]]},"183":{"position":[[49,6],[157,6],[255,7],[296,6]]},"184":{"position":[[74,6],[175,6],[247,7],[286,6],[605,6],[687,6],[837,6],[1110,6]]},"185":{"position":[[37,6],[157,6],[421,8],[791,6]]},"186":{"position":[[16,6],[301,6]]},"197":{"position":[[41,6]]},"199":{"position":[[109,6],[269,6]]}},"keywords":{}}],["static>>>",{"_index":3784,"title":{},"content":{"115":{"position":[[2036,20],[2385,20]]},"116":{"position":[[1941,20],[2243,20]]}},"keywords":{}}],["staticthat",{"_index":4713,"title":{},"content":{"160":{"position":[[3906,10]]}},"keywords":{}}],["statist",{"_index":2319,"title":{"58":{"position":[[0,11]]}},"content":{"90":{"position":[[864,10],[2249,10]]},"102":{"position":[[619,13],[882,11]]},"189":{"position":[[1556,10]]}},"keywords":{}}],["stay",{"_index":117,"title":{},"content":{"2":{"position":[[645,6]]},"30":{"position":[[5616,5]]},"121":{"position":[[415,4]]},"122":{"position":[[478,7]]},"125":{"position":[[10895,4]]},"161":{"position":[[132,4]]},"186":{"position":[[102,4]]}},"keywords":{}}],["std",{"_index":1923,"title":{},"content":{"44":{"position":[[832,3]]},"90":{"position":[[4494,4]]}},"keywords":{}}],["std::alloc::system",{"_index":4369,"title":{},"content":{"133":{"position":[[266,19]]}},"keywords":{}}],["std::alloc::{globalalloc",{"_index":4511,"title":{},"content":{"152":{"position":[[376,25]]},"156":{"position":[[826,25]]}},"keywords":{}}],["std::borrow::cow",{"_index":4577,"title":{},"content":{"155":{"position":[[1321,17]]}},"keywords":{}}],["std::cell::refcel",{"_index":5068,"title":{},"content":{"179":{"position":[[367,19],[837,19]]},"180":{"position":[[347,19]]},"184":{"position":[[1002,19]]},"185":{"position":[[633,19]]}},"keywords":{}}],["std::cell::refcell<u8>",{"_index":5130,"title":{},"content":{"184":{"position":[[1039,30]]},"185":{"position":[[720,30]]}},"keywords":{}}],["std::collections::hashmap",{"_index":5379,"title":{},"content":{"199":{"position":[[1072,26]]}},"keywords":{}}],["std::marker::s",{"_index":3388,"title":{},"content":{"97":{"position":[[2018,19]]}},"keywords":{}}],["std::marker::send",{"_index":3774,"title":{},"content":{"115":{"position":[[969,18],[1316,18],[2057,18]]},"116":{"position":[[968,18],[1268,18],[1962,18]]}},"keywords":{}}],["std::marker::sync",{"_index":3782,"title":{},"content":{"115":{"position":[[1688,18]]},"116":{"position":[[1593,18]]}},"keywords":{}}],["std::ops::fn(&'r",{"_index":3383,"title":{},"content":{"97":{"position":[[1888,20]]}},"keywords":{}}],["std::ptr::read_volatile(&equ",{"_index":4521,"title":{},"content":{"152":{"position":[[946,36]]}},"keywords":{}}],["std::rc::rc",{"_index":4575,"title":{},"content":{"155":{"position":[[1284,12]]}},"keywords":{}}],["std::result::result<iron::respons",{"_index":3386,"title":{},"content":{"97":{"position":[[1948,38]]}},"keywords":{}}],["std::sync::arc",{"_index":4576,"title":{},"content":{"155":{"position":[[1301,15]]}},"keywords":{}}],["std::sync::atomic::{atomicbool",{"_index":4512,"title":{},"content":{"152":{"position":[[423,31]]},"156":{"position":[[873,31]]}},"keywords":{}}],["std::sync::onc",{"_index":5079,"title":{},"content":{"179":{"position":[[1228,16]]},"186":{"position":[[186,16]]}},"keywords":{}}],["std::thread::spawn(mov",{"_index":3779,"title":{},"content":{"115":{"position":[[1139,23],[1486,23],[1769,23],[2227,23]]},"116":{"position":[[726,23],[1091,23],[1391,23],[1674,23],[2085,23]]},"117":{"position":[[1583,23]]}},"keywords":{}}],["std::thread:spawn(mov",{"_index":3769,"title":{},"content":{"115":{"position":[[707,22]]}},"keywords":{}}],["std::vec::vec<std::option::option<std::boxed::box<capnp::private::capability::clienthook",{"_index":3783,"title":{},"content":{"115":{"position":[[1936,97],[2285,97]]},"116":{"position":[[1841,97],[2143,97]]}},"keywords":{}}],["std::vector",{"_index":4691,"title":{},"content":{"160":{"position":[[2369,11]]}},"keywords":{}}],["std_dev",{"_index":2989,"title":{},"content":{"90":{"position":[[1182,7],[1558,8],[1590,8],[1707,8],[1739,8],[2567,7],[2851,8],[2883,8]]}},"keywords":{}}],["stdweb",{"_index":4174,"title":{},"content":{"125":{"position":[[8804,6],[8901,7],[9209,6],[11169,7],[11300,6]]}},"keywords":{}}],["steel",{"_index":1819,"title":{},"content":{"40":{"position":[[2162,5]]}},"keywords":{}}],["step",{"_index":350,"title":{"25":{"position":[[9,4]]},"108":{"position":[[0,4]]},"109":{"position":[[0,4]]},"110":{"position":[[0,4]]},"111":{"position":[[0,4]]},"112":{"position":[[0,4]]},"113":{"position":[[0,4]]}},"content":{"6":{"position":[[737,5]]},"51":{"position":[[2830,6]]},"61":{"position":[[1329,5],[1406,5],[2091,4]]},"64":{"position":[[11,4]]},"65":{"position":[[230,6],[271,5],[2189,5]]},"108":{"position":[[816,4]]},"113":{"position":[[595,5]]},"125":{"position":[[7052,6],[8465,5]]},"160":{"position":[[760,4]]},"164":{"position":[[1263,5]]},"176":{"position":[[1534,5]]},"193":{"position":[[1232,4]]}},"keywords":{}}],["stick",{"_index":1215,"title":{},"content":{"28":{"position":[[570,5]]},"66":{"position":[[809,8]]},"128":{"position":[[1209,5]]},"165":{"position":[[1220,6]]}},"keywords":{}}],["still",{"_index":1402,"title":{},"content":{"30":{"position":[[4386,5],[5808,5]]},"32":{"position":[[126,6]]},"33":{"position":[[956,5]]},"34":{"position":[[488,5]]},"45":{"position":[[2551,5]]},"58":{"position":[[878,5]]},"66":{"position":[[503,6]]},"71":{"position":[[1192,5]]},"81":{"position":[[64,5]]},"82":{"position":[[1123,5]]},"83":{"position":[[487,5]]},"92":{"position":[[1473,5]]},"93":{"position":[[972,5]]},"101":{"position":[[144,5]]},"116":{"position":[[878,5],[910,5]]},"117":{"position":[[525,5]]},"122":{"position":[[233,5]]},"123":{"position":[[629,5],[967,5]]},"125":{"position":[[6193,5],[11044,5],[11438,5]]},"129":{"position":[[2778,5]]},"130":{"position":[[249,5]]},"139":{"position":[[53,5],[542,5]]},"147":{"position":[[450,5]]},"161":{"position":[[1183,5]]},"163":{"position":[[2374,6]]},"164":{"position":[[782,5]]},"165":{"position":[[486,5]]},"166":{"position":[[750,5]]},"179":{"position":[[1104,7],[1770,5]]},"186":{"position":[[401,5]]},"192":{"position":[[724,5]]},"193":{"position":[[2404,6],[3124,5]]}},"keywords":{}}],["stillblownaway",{"_index":2272,"title":{},"content":{"53":{"position":[[1449,15]]}},"keywords":{}}],["stl",{"_index":4693,"title":{},"content":{"160":{"position":[[2407,3]]}},"keywords":{}}],["stock",{"_index":460,"title":{},"content":{"9":{"position":[[155,5]]},"14":{"position":[[715,5],[800,5],[859,5],[970,5],[1052,5],[1137,5]]},"19":{"position":[[201,5]]},"20":{"position":[[1591,6]]},"32":{"position":[[211,5],[287,5]]},"33":{"position":[[774,5],[905,5],[1084,5],[1147,5]]},"34":{"position":[[514,5],[3128,5],[3652,5]]},"35":{"position":[[118,5]]},"38":{"position":[[185,5],[457,6]]},"39":{"position":[[177,7]]},"40":{"position":[[41,6],[695,5],[916,6],[1401,6],[2361,5],[3308,6],[3611,6]]},"88":{"position":[[32,5]]},"89":{"position":[[550,5],[696,5]]},"90":{"position":[[4910,5],[5174,5],[5358,5]]},"91":{"position":[[48,6],[1768,6],[3133,5],[4515,5],[5033,5],[5343,6],[5441,5],[5786,6]]},"92":{"position":[[104,6],[187,6],[945,5],[1351,6],[1572,6]]},"93":{"position":[[91,5],[270,5],[698,7],[877,6],[3272,5],[3747,5]]},"163":{"position":[[185,5]]}},"keywords":{}}],["stock'",{"_index":1562,"title":{},"content":{"32":{"position":[[2299,7]]},"93":{"position":[[160,7]]}},"keywords":{}}],["stocks?how",{"_index":2956,"title":{},"content":{"89":{"position":[[809,10]]}},"keywords":{}}],["stole",{"_index":4410,"title":{},"content":{"137":{"position":[[262,6]]}},"keywords":{}}],["stop",{"_index":1630,"title":{},"content":{"34":{"position":[[1835,5]]},"61":{"position":[[1165,4]]},"76":{"position":[[2231,5]]},"102":{"position":[[943,4]]},"115":{"position":[[2885,4]]},"125":{"position":[[10126,7]]},"172":{"position":[[2001,5]]}},"keywords":{}}],["storag",{"_index":3467,"title":{},"content":{"101":{"position":[[104,7],[889,7]]},"105":{"position":[[2610,7]]},"153":{"position":[[947,7]]}},"keywords":{}}],["store",{"_index":3579,"title":{},"content":{"105":{"position":[[426,5],[555,7],[659,6]]},"110":{"position":[[238,7]]},"117":{"position":[[763,7]]},"121":{"position":[[987,6]]},"156":{"position":[[416,5]]},"174":{"position":[[662,6]]},"178":{"position":[[553,6]]},"180":{"position":[[469,6]]},"192":{"position":[[220,6]]},"193":{"position":[[1558,6]]},"194":{"position":[[628,6]]},"196":{"position":[[834,5],[895,5],[1252,5]]},"197":{"position":[[205,6],[353,6],[499,6]]}},"keywords":{}}],["store_d",{"_index":3203,"title":{},"content":{"93":{"position":[[1491,11]]}},"keywords":{}}],["stori",{"_index":259,"title":{},"content":{"4":{"position":[[768,7]]},"164":{"position":[[49,6]]}},"keywords":{}}],["storm",{"_index":2241,"title":{},"content":{"53":{"position":[[998,7]]}},"keywords":{}}],["str",{"_index":3318,"title":{},"content":{"96":{"position":[[175,3],[1326,4]]}},"keywords":{}}],["strace",{"_index":4963,"title":{},"content":{"173":{"position":[[1309,6]]}},"keywords":{}}],["straight",{"_index":3184,"title":{},"content":{"92":{"position":[[1610,9]]},"121":{"position":[[1981,9]]},"125":{"position":[[1019,8]]},"175":{"position":[[124,8]]}},"keywords":{}}],["strang",{"_index":3350,"title":{},"content":{"96":{"position":[[1959,8]]},"97":{"position":[[4967,8]]},"106":{"position":[[57,9]]},"143":{"position":[[209,7]]},"157":{"position":[[19,7]]},"179":{"position":[[26,7]]}},"keywords":{}}],["strategi",{"_index":1509,"title":{"32":{"position":[[24,9]]}},"content":{"32":{"position":[[156,8]]},"34":{"position":[[114,8],[771,8],[822,8]]},"35":{"position":[[29,8],[150,8],[341,8],[364,8]]},"40":{"position":[[769,8],[1153,8],[1487,8]]},"41":{"position":[[46,8],[373,8]]},"46":{"position":[[427,8]]}},"keywords":{}}],["stream",{"_index":3653,"title":{},"content":{"106":{"position":[[552,10],[683,6],[710,6],[758,6],[898,6]]},"165":{"position":[[1044,9],[1176,6]]},"166":{"position":[[803,9]]}},"keywords":{}}],["street",{"_index":903,"title":{},"content":{"22":{"position":[[649,6]]}},"keywords":{}}],["stress",{"_index":5046,"title":{},"content":{"176":{"position":[[648,9]]}},"keywords":{}}],["strictli",{"_index":762,"title":{},"content":{"20":{"position":[[148,8]]}},"keywords":{}}],["strike",{"_index":559,"title":{},"content":{"13":{"position":[[537,6],[1026,7],[1056,6]]},"14":{"position":[[2060,7],[2090,6]]},"15":{"position":[[1728,7],[1758,6]]}},"keywords":{}}],["string",{"_index":947,"title":{"96":{"position":[[9,8]]}},"content":{"22":{"position":[[1646,8]]},"30":{"position":[[7665,6]]},"61":{"position":[[1628,6]]},"96":{"position":[[1,7],[88,7],[922,6],[1404,7],[1481,6],[2138,8]]},"97":{"position":[[1486,7],[3595,6]]},"98":{"position":[[224,7]]},"120":{"position":[[947,7]]},"129":{"position":[[1494,6]]},"136":{"position":[[632,7]]},"159":{"position":[[1067,7]]},"165":{"position":[[648,7],[819,6]]}},"keywords":{}}],["string::new",{"_index":4604,"title":{},"content":{"156":{"position":[[1858,14]]}},"keywords":{}}],["strip",{"_index":4443,"title":{},"content":{"143":{"position":[[389,5]]},"152":{"position":[[848,5]]},"153":{"position":[[89,9]]}},"keywords":{}}],["strong",{"_index":4,"title":{"1":{"position":[[9,7]]}},"content":{},"keywords":{}}],["struct",{"_index":3396,"title":{"192":{"position":[[0,8]]}},"content":{"97":{"position":[[2756,6],[3440,6],[3565,6],[3963,7]]},"110":{"position":[[457,6]]},"112":{"position":[[1299,8]]},"129":{"position":[[179,7],[1427,6]]},"152":{"position":[[1245,6]]},"153":{"position":[[527,6],[583,6],[642,6],[702,6],[844,7]]},"156":{"position":[[1328,6]]},"166":{"position":[[490,8]]},"184":{"position":[[113,6],[148,6],[507,6]]},"185":{"position":[[609,6],[653,6]]},"192":{"position":[[54,6],[115,6],[148,6]]},"193":{"position":[[906,6],[2211,6],[3177,6]]},"194":{"position":[[257,6]]},"195":{"position":[[209,6],[280,6],[356,6],[594,6]]},"197":{"position":[[384,6],[530,6]]},"198":{"position":[[442,9],[990,6],[1123,6]]}},"keywords":{}}],["structur",{"_index":143,"title":{"9":{"position":[[19,10]]},"10":{"position":[[22,10]]}},"content":{"3":{"position":[[200,11]]},"6":{"position":[[379,9]]},"7":{"position":[[196,10]]},"9":{"position":[[274,10],[348,10],[368,9],[624,9],[771,9]]},"10":{"position":[[29,10],[183,9]]},"11":{"position":[[27,9]]},"15":{"position":[[25,9]]},"53":{"position":[[2208,9]]},"110":{"position":[[529,9]]},"163":{"position":[[750,10]]},"190":{"position":[[215,11]]}},"keywords":{}}],["structure[1",{"_index":488,"title":{},"content":{"10":{"position":[[153,12]]}},"keywords":{}}],["structurethat",{"_index":4616,"title":{},"content":{"157":{"position":[[695,13]]}},"keywords":{}}],["struggl",{"_index":4690,"title":{},"content":{"160":{"position":[[2342,8],[2446,8]]}},"keywords":{}}],["stuck",{"_index":139,"title":{},"content":{"3":{"position":[[127,5]]},"135":{"position":[[609,5]]}},"keywords":{}}],["studi",{"_index":1292,"title":{"87":{"position":[[6,7]]},"90":{"position":[[6,8]]},"131":{"position":[[7,5]]}},"content":{"28":{"position":[[2742,8]]},"90":{"position":[[69,6]]},"91":{"position":[[35,5],[1635,6],[4346,5],[4964,6],[5151,5],[5528,5]]},"93":{"position":[[3785,8]]}},"keywords":{}}],["study_trend(3",{"_index":3173,"title":{},"content":{"91":{"position":[[5545,14]]},"92":{"position":[[1844,14]]}},"keywords":{}}],["study_trend(5",{"_index":3157,"title":{},"content":{"91":{"position":[[4352,14]]},"92":{"position":[[1127,14]]}},"keywords":{}}],["study_trend(8",{"_index":3169,"title":{},"content":{"91":{"position":[[5162,14]]},"92":{"position":[[1685,14]]}},"keywords":{}}],["study_trend(horizon",{"_index":3140,"title":{},"content":{"91":{"position":[[3319,20]]}},"keywords":{}}],["stuff",{"_index":3311,"title":{},"content":{"95":{"position":[[456,5]]},"106":{"position":[[1172,5]]},"113":{"position":[[1425,5]]},"129":{"position":[[602,5]]}},"keywords":{}}],["stump",{"_index":3367,"title":{},"content":{"97":{"position":[[874,7]]}},"keywords":{}}],["stun",{"_index":4004,"title":{},"content":{"125":{"position":[[33,7]]}},"keywords":{}}],["stunningli",{"_index":4030,"title":{},"content":{"125":{"position":[[860,10]]}},"keywords":{}}],["style",{"_index":3491,"title":{},"content":{"102":{"position":[[389,5]]},"125":{"position":[[1417,8]]}},"keywords":{}}],["sub",{"_index":4259,"title":{},"content":{"128":{"position":[[469,3],[1526,3]]},"129":{"position":[[527,3]]}},"keywords":{}}],["subject",{"_index":793,"title":{},"content":{"20":{"position":[[835,7]]},"176":{"position":[[1333,7]]}},"keywords":{}}],["substant",{"_index":3932,"title":{},"content":{"122":{"position":[[79,11]]}},"keywords":{}}],["subtl",{"_index":2612,"title":{},"content":{"71":{"position":[[1433,6]]},"199":{"position":[[51,6]]}},"keywords":{}}],["subtract",{"_index":2519,"title":{},"content":{"65":{"position":[[1490,8]]},"91":{"position":[[2954,8]]},"92":{"position":[[766,8]]},"193":{"position":[[1121,8]]}},"keywords":{}}],["success",{"_index":4005,"title":{},"content":{"125":{"position":[[48,7]]}},"keywords":{}}],["successfulli",{"_index":862,"title":{},"content":{"20":{"position":[[2796,14]]},"30":{"position":[[306,12]]},"153":{"position":[[984,13]]}},"keywords":{}}],["such",{"_index":3816,"title":{},"content":{"117":{"position":[[281,4]]},"150":{"position":[[697,4]]},"160":{"position":[[3836,5]]}},"keywords":{}}],["suck",{"_index":3854,"title":{},"content":{"120":{"position":[[610,4]]}},"keywords":{}}],["sudden",{"_index":3883,"title":{},"content":{"121":{"position":[[614,6]]}},"keywords":{}}],["suddenli",{"_index":1435,"title":{},"content":{"30":{"position":[[7701,8]]},"172":{"position":[[2438,8]]}},"keywords":{}}],["suffer",{"_index":2653,"title":{},"content":{"74":{"position":[[1423,7]]}},"keywords":{}}],["suffic",{"_index":3787,"title":{},"content":{"115":{"position":[[2539,7]]}},"keywords":{}}],["suffici",{"_index":2577,"title":{},"content":{"69":{"position":[[219,10]]},"152":{"position":[[85,12]]}},"keywords":{}}],["sum",{"_index":2570,"title":{},"content":{"68":{"position":[[864,3]]},"69":{"position":[[330,3],[390,3]]},"72":{"position":[[105,3],[167,3],[315,3],[368,3]]},"74":{"position":[[361,3],[459,3]]},"188":{"position":[[2661,3]]},"199":{"position":[[158,3],[230,3],[255,4],[322,3],[398,3],[417,4]]}},"keywords":{}}],["sum(abs(optimal.x",{"_index":858,"title":{},"content":{"20":{"position":[[2600,18],[2629,19]]}},"keywords":{}}],["sum(abs(x",{"_index":819,"title":{},"content":{"20":{"position":[[1472,10],[1539,11],[1751,10],[1772,11],[1862,11]]}},"keywords":{}}],["sum(invest",{"_index":1640,"title":{},"content":{"34":{"position":[[2278,12],[2327,13],[2524,12],[2654,13]]},"39":{"position":[[2104,13]]}},"keywords":{}}],["sum(investments[1:i",{"_index":1645,"title":{},"content":{"34":{"position":[[2754,22]]}},"keywords":{}}],["sum(purchase_histori",{"_index":1616,"title":{},"content":{"34":{"position":[[1265,20],[1489,20],[1560,21]]},"39":{"position":[[752,21]]}},"keywords":{}}],["sum(x",{"_index":831,"title":{},"content":{"20":{"position":[[1809,6],[1896,5]]}},"keywords":{}}],["sum_enumerate(x",{"_index":5382,"title":{},"content":{"199":{"position":[[1375,16]]}},"keywords":{}}],["sum_for",{"_index":5376,"title":{},"content":{"199":{"position":[[433,7]]}},"keywords":{}}],["sum_for(list<long>",{"_index":5371,"title":{},"content":{"199":{"position":[[120,24]]}},"keywords":{}}],["sum_foreach",{"_index":5377,"title":{},"content":{"199":{"position":[[492,12]]}},"keywords":{}}],["sum_foreach(list<long>",{"_index":5374,"title":{},"content":{"199":{"position":[[280,28]]}},"keywords":{}}],["sum_hm(x",{"_index":5384,"title":{},"content":{"199":{"position":[[1531,9]]}},"keywords":{}}],["sum_vec(x",{"_index":5380,"title":{},"content":{"199":{"position":[[1238,10]]}},"keywords":{}}],["sum_{i=1}^n",{"_index":1530,"title":{},"content":{"32":{"position":[[825,12]]},"74":{"position":[[1706,12]]}},"keywords":{}}],["sum_{i=1}^{n",{"_index":1532,"title":{},"content":{"32":{"position":[[859,14],[1576,13],[1640,13],[1703,13],[1786,13],[1866,13]]}},"keywords":{}}],["summar",{"_index":3187,"title":{},"content":{"93":{"position":[[37,9]]},"122":{"position":[[612,10]]}},"keywords":{}}],["summari",{"_index":1172,"title":{"35":{"position":[[0,8]]},"41":{"position":[[0,7]]},"46":{"position":[[0,7]]},"66":{"position":[[0,8]]},"93":{"position":[[15,8]]},"159":{"position":[[21,7]]}},"content":{"26":{"position":[[412,8]]},"30":{"position":[[7379,7]]},"90":{"position":[[856,7],[2241,7]]}},"keywords":{}}],["sun",{"_index":1336,"title":{},"content":{"30":{"position":[[490,4]]}},"keywords":{}}],["sunni",{"_index":1393,"title":{},"content":{"30":{"position":[[4090,5],[7586,6]]}},"keywords":{}}],["super",{"_index":1463,"title":{},"content":{"30":{"position":[[8729,5]]},"95":{"position":[[431,5]]},"96":{"position":[[96,5]]},"98":{"position":[[1182,5]]},"120":{"position":[[324,5]]},"121":{"position":[[2732,5]]},"130":{"position":[[12,5]]}},"keywords":{}}],["super().__init__(*arg",{"_index":935,"title":{},"content":{"22":{"position":[[1314,23]]},"93":{"position":[[1582,23]]}},"keywords":{}}],["supplier",{"_index":2949,"title":{},"content":{"89":{"position":[[283,9],[358,10]]}},"keywords":{}}],["support",{"_index":1715,"title":{"150":{"position":[[33,9]]}},"content":{"39":{"position":[[356,7]]},"120":{"position":[[137,7]]},"125":{"position":[[11204,7]]},"160":{"position":[[3799,9]]},"164":{"position":[[124,9]]},"165":{"position":[[81,7],[1054,7]]},"166":{"position":[[1,7],[523,10],[813,7]]},"172":{"position":[[2108,7]]}},"keywords":{}}],["supportsprofil",{"_index":4933,"title":{},"content":{"172":{"position":[[2234,15]]}},"keywords":{}}],["suppos",{"_index":5081,"title":{},"content":{"179":{"position":[[1318,8]]}},"keywords":{}}],["sure",{"_index":430,"title":{},"content":{"7":{"position":[[1073,4]]},"22":{"position":[[2710,4]]},"32":{"position":[[2172,4]]},"39":{"position":[[1789,4]]},"46":{"position":[[325,4]]},"61":{"position":[[500,4]]},"76":{"position":[[1372,4]]},"81":{"position":[[47,4]]},"85":{"position":[[499,4]]},"90":{"position":[[491,4]]},"91":{"position":[[3220,4]]},"92":{"position":[[1032,4]]},"108":{"position":[[228,4],[706,4]]},"110":{"position":[[120,4]]},"111":{"position":[[60,4]]},"113":{"position":[[2314,4]]},"116":{"position":[[2775,4]]},"117":{"position":[[542,4]]},"121":{"position":[[1902,4]]},"123":{"position":[[236,4]]},"125":{"position":[[11190,4]]},"156":{"position":[[1821,4]]},"158":{"position":[[453,4]]},"167":{"position":[[271,4]]},"173":{"position":[[1830,4]]},"175":{"position":[[471,4]]},"176":{"position":[[408,4]]}},"keywords":{}}],["surpris",{"_index":1313,"title":{},"content":{"29":{"position":[[29,9]]},"98":{"position":[[485,10]]},"179":{"position":[[1251,9]]}},"keywords":{}}],["surprise.call_onc",{"_index":5082,"title":{},"content":{"179":{"position":[[1338,21],[1539,21]]}},"keywords":{}}],["surprisingli",{"_index":1048,"title":{},"content":{"24":{"position":[[976,12]]},"25":{"position":[[696,12]]},"74":{"position":[[155,12]]},"82":{"position":[[1008,12]]}},"keywords":{}}],["survey",{"_index":1289,"title":{},"content":{"28":{"position":[[2679,8]]},"29":{"position":[[169,9]]},"43":{"position":[[1295,6]]}},"keywords":{}}],["surveyed.averag",{"_index":1310,"title":{},"content":{"28":{"position":[[4308,16]]}},"keywords":{}}],["surviv",{"_index":2695,"title":{},"content":{"76":{"position":[[954,9]]}},"keywords":{}}],["suspect",{"_index":2332,"title":{},"content":{"58":{"position":[[354,7]]}},"keywords":{}}],["sustain",{"_index":3983,"title":{},"content":{"123":{"position":[[745,10]]}},"keywords":{}}],["sveltekit",{"_index":214,"title":{},"content":{"3":{"position":[[1488,10]]}},"keywords":{}}],["swingdanc",{"_index":2219,"title":{},"content":{"53":{"position":[[632,11]]}},"keywords":{}}],["switch",{"_index":910,"title":{},"content":{"22":{"position":[[830,6]]},"75":{"position":[[728,6],[863,9],[1068,7]]},"76":{"position":[[2260,6],[2999,9],[3136,6]]},"97":{"position":[[2257,6]]},"173":{"position":[[1152,6],[1222,6],[1464,6],[1783,6]]},"175":{"position":[[1072,10],[1359,6],[1510,8],[1654,7]]},"176":{"position":[[271,9]]}},"keywords":{}}],["switch_failur",{"_index":2721,"title":{},"content":{"76":{"position":[[1936,15],[2386,15],[2912,15],[3221,15],[3247,15]]}},"keywords":{}}],["sy",{"_index":4175,"title":{},"content":{"125":{"position":[[8830,5],[9594,3],[9606,4],[11161,3],[11349,4],[11377,4]]},"188":{"position":[[1598,4],[1696,4],[2265,4],[2582,4],[3120,4]]},"189":{"position":[[1786,4],[2241,4],[2524,4],[2813,4]]}},"keywords":{}}],["symbol",{"_index":4827,"title":{},"content":{"165":{"position":[[640,7]]}},"keywords":{}}],["symbolsus",{"_index":4142,"title":{},"content":{"125":{"position":[[6633,11]]}},"keywords":{}}],["symmetri",{"_index":2569,"title":{},"content":{"68":{"position":[[811,9]]}},"keywords":{}}],["sync",{"_index":4154,"title":{"185":{"position":[[4,4]]}},"content":{"125":{"position":[[8054,4]]},"184":{"position":[[882,5],[954,5]]},"185":{"position":[[254,4],[327,4],[468,4],[589,4]]}},"keywords":{}}],["synchron",{"_index":4470,"title":{},"content":{"147":{"position":[[49,12]]},"157":{"position":[[552,15]]},"188":{"position":[[4235,11]]}},"keywords":{}}],["syntax",{"_index":3926,"title":{},"content":{"121":{"position":[[2660,6]]},"129":{"position":[[2540,6]]}},"keywords":{}}],["syntax"",{"_index":3898,"title":{},"content":{"121":{"position":[[1382,12]]}},"keywords":{}}],["syntaxerror",{"_index":4331,"title":{},"content":{"129":{"position":[[2519,12]]}},"keywords":{}}],["syscal",{"_index":4959,"title":{},"content":{"173":{"position":[[1103,11],[1364,8]]}},"keywords":{}}],["system",{"_index":266,"title":{"133":{"position":[[15,6]]},"171":{"position":[[29,7]]}},"content":{"4":{"position":[[874,6],[1417,7]]},"34":{"position":[[912,6]]},"59":{"position":[[76,7]]},"91":{"position":[[3905,12]]},"97":{"position":[[6460,6]]},"100":{"position":[[155,6]]},"130":{"position":[[461,7]]},"133":{"position":[[321,6],[330,7]]},"150":{"position":[[370,6],[654,7],[836,7]]},"152":{"position":[[410,8]]},"156":{"position":[[860,8]]},"160":{"position":[[532,7],[1109,6],[1381,6],[1945,6]]},"163":{"position":[[15,6]]},"166":{"position":[[154,8]]},"172":{"position":[[1294,6]]},"173":{"position":[[114,6],[169,6],[941,6],[1615,6],[1991,7]]},"174":{"position":[[415,8],[1142,7]]},"175":{"position":[[771,7]]},"176":{"position":[[18,8],[843,8],[959,6],[1431,7]]}},"keywords":{}}],["system.alloc(layout",{"_index":4534,"title":{},"content":{"152":{"position":[[1455,20]]},"156":{"position":[[1538,20]]}},"keywords":{}}],["system.dealloc(ptr",{"_index":4537,"title":{},"content":{"152":{"position":[[1624,19]]},"156":{"position":[[1707,19]]}},"keywords":{}}],["system.out.println(x.tostr",{"_index":4232,"title":{},"content":{"127":{"position":[[646,33],[777,33]]}},"keywords":{}}],["system.out.println(y.tostr",{"_index":4244,"title":{},"content":{"127":{"position":[[1328,33]]}},"keywords":{}}],["systemd",{"_index":4948,"title":{},"content":{"173":{"position":[[700,8]]}},"keywords":{}}],["t",{"_index":345,"title":{},"content":{"6":{"position":[[652,2],[963,1]]},"7":{"position":[[296,2],[341,1],[345,1],[562,2],[819,2],[842,1],[888,1]]},"9":{"position":[[428,2]]},"11":{"position":[[577,2]]},"12":{"position":[[245,2],[560,2]]},"13":{"position":[[732,1],[1341,2]]},"14":{"position":[[1589,1],[2413,2]]},"15":{"position":[[976,1],[2085,2]]},"93":{"position":[[3467,1],[3473,1]]}},"keywords":{}}],["t1",{"_index":1613,"title":{},"content":{"34":{"position":[[1222,2],[1348,2]]},"39":{"position":[[857,2],[987,2]]},"188":{"position":[[2060,2],[2428,2],[2966,2]]},"189":{"position":[[2091,2],[2372,2],[2661,2]]}},"keywords":{}}],["t1.join",{"_index":5184,"title":{},"content":{"188":{"position":[[2218,10],[2535,10],[3073,10]]},"189":{"position":[[2194,10],[2477,10],[2766,10]]}},"keywords":{}}],["t1.start",{"_index":5182,"title":{},"content":{"188":{"position":[[2162,11],[2512,11],[3050,11]]},"189":{"position":[[2171,11],[2454,11],[2743,11]]}},"keywords":{}}],["t2",{"_index":1615,"title":{},"content":{"34":{"position":[[1260,2],[1343,2]]},"39":{"position":[[895,2],[982,2]]},"188":{"position":[[2101,2],[2471,2],[3007,2]]},"189":{"position":[[2131,2],[2414,2],[2701,2]]}},"keywords":{}}],["t2.join",{"_index":5185,"title":{},"content":{"188":{"position":[[2229,9],[2546,9],[3084,9]]},"189":{"position":[[2205,9],[2488,9],[2777,9]]}},"keywords":{}}],["t2.start",{"_index":5183,"title":{},"content":{"188":{"position":[[2174,10],[2524,10],[3062,10]]},"189":{"position":[[2183,10],[2466,10],[2755,10]]}},"keywords":{}}],["t=.25",{"_index":446,"title":{},"content":{"8":{"position":[[115,5]]}},"keywords":{}}],["tabl",{"_index":3206,"title":{},"content":{"93":{"position":[[1681,8],[2223,8]]},"164":{"position":[[1421,6]]},"165":{"position":[[624,5],[658,5]]}},"keywords":{}}],["tabulasa",{"_index":3501,"title":{},"content":{"103":{"position":[[47,9],[517,8]]}},"keywords":{}}],["tabulasa.flac"",{"_index":3510,"title":{},"content":{"103":{"position":[[308,19]]}},"keywords":{}}],["tabulasa[:,0",{"_index":3538,"title":{},"content":{"103":{"position":[[1716,13]]}},"keywords":{}}],["tabulasa_left",{"_index":3537,"title":{},"content":{"103":{"position":[[1700,13]]}},"keywords":{}}],["tag",{"_index":888,"title":{},"content":{"22":{"position":[[322,4],[339,3],[449,3],[1389,4],[1405,3],[1611,3],[2293,5]]},"93":{"position":[[1658,4],[1674,3],[2207,5],[2216,3]]},"165":{"position":[[1354,3]]}},"keywords":{}}],["tag(enhanced_packet",{"_index":4791,"title":{},"content":{"163":{"position":[[1956,21]]}},"keywords":{}}],["take",{"_index":1185,"title":{},"content":{"26":{"position":[[851,6]]},"28":{"position":[[7,6]]},"30":{"position":[[7768,4]]},"32":{"position":[[1415,4]]},"34":{"position":[[3956,5]]},"38":{"position":[[250,5],[636,6]]},"40":{"position":[[3513,4]]},"41":{"position":[[176,6]]},"43":{"position":[[378,5]]},"44":{"position":[[2007,4]]},"45":{"position":[[589,4],[1027,4],[1337,4],[1391,4]]},"74":{"position":[[381,4]]},"86":{"position":[[404,4]]},"93":{"position":[[594,4]]},"96":{"position":[[235,4]]},"97":{"position":[[2695,4],[4100,4],[4697,4]]},"98":{"position":[[1213,4]]},"101":{"position":[[264,6],[1036,4]]},"106":{"position":[[285,5]]},"108":{"position":[[39,6]]},"120":{"position":[[311,4],[924,5]]},"121":{"position":[[378,4]]},"124":{"position":[[781,4]]},"125":{"position":[[1097,4],[1666,4],[9975,4],[10603,4]]},"128":{"position":[[1051,4]]},"137":{"position":[[237,4]]},"150":{"position":[[265,6]]},"161":{"position":[[464,6]]},"167":{"position":[[69,4]]},"168":{"position":[[56,5]]},"169":{"position":[[56,5]]},"172":{"position":[[871,5],[1130,4],[1557,5]]},"173":{"position":[[1056,6]]},"175":{"position":[[199,5]]},"182":{"position":[[54,4]]},"183":{"position":[[208,4]]},"188":{"position":[[1487,5],[1777,4]]},"189":{"position":[[1590,5],[1708,5],[1877,5],[2044,5]]}},"keywords":{}}],["take(captured_len)(remain",{"_index":4794,"title":{},"content":{"163":{"position":[[2069,31]]}},"keywords":{}}],["taken",{"_index":489,"title":{},"content":{"10":{"position":[[193,5]]},"51":{"position":[[3037,5]]},"52":{"position":[[662,5]]},"76":{"position":[[269,5]]},"93":{"position":[[455,5]]}},"keywords":{}}],["takeov",{"_index":3182,"title":{},"content":{"92":{"position":[[1440,8]]}},"keywords":{}}],["talk",{"_index":1319,"title":{},"content":{"29":{"position":[[437,4]]},"30":{"position":[[401,7]]},"32":{"position":[[52,7]]},"54":{"position":[[22,6]]},"97":{"position":[[2790,6],[2870,7]]},"121":{"position":[[470,7]]},"125":{"position":[[2036,7],[11292,4]]},"161":{"position":[[232,7]]},"166":{"position":[[84,6]]},"178":{"position":[[510,7]]},"184":{"position":[[13,4]]}},"keywords":{}}],["target",{"_index":3713,"title":{},"content":{"112":{"position":[[502,7],[908,6]]},"125":{"position":[[2737,7]]}},"keywords":{}}],["target/debug/build/capnp_cookbook_1",{"_index":3715,"title":{},"content":{"112":{"position":[[797,37]]}},"keywords":{}}],["target=wasm32",{"_index":4114,"title":{},"content":{"125":{"position":[[5227,13],[5775,13]]}},"keywords":{}}],["task",{"_index":1050,"title":{},"content":{"24":{"position":[[999,4]]},"25":{"position":[[719,4]]},"30":{"position":[[681,5]]}},"keywords":{}}],["taskset",{"_index":5043,"title":{},"content":{"176":{"position":[[321,7]]}},"keywords":{}}],["tcp",{"_index":5013,"title":{},"content":{"175":{"position":[[562,3]]}},"keywords":{}}],["td",{"_index":3284,"title":{},"content":{"93":{"position":[[4907,2],[4984,3],[5322,2],[5399,3]]}},"keywords":{}}],["td_back",{"_index":3029,"title":{},"content":{"90":{"position":[[3652,7],[3742,7]]}},"keywords":{}}],["td_back:event+td_forward",{"_index":3037,"title":{},"content":{"90":{"position":[[3876,26]]}},"keywords":{}}],["td_forward",{"_index":3031,"title":{},"content":{"90":{"position":[[3682,10],[3775,10]]}},"keywords":{}}],["teach",{"_index":1539,"title":{},"content":{"32":{"position":[[1367,5]]}},"keywords":{}}],["team",{"_index":4487,"title":{},"content":{"150":{"position":[[35,5],[683,5]]}},"keywords":{}}],["technic",{"_index":3823,"title":{},"content":{"117":{"position":[[730,11]]},"125":{"position":[[2967,11]]},"129":{"position":[[1176,9]]},"160":{"position":[[41,9]]},"161":{"position":[[284,10]]},"197":{"position":[[1566,11]]}},"keywords":{}}],["technician",{"_index":1573,"title":{},"content":{"33":{"position":[[418,11]]}},"keywords":{}}],["techniqu",{"_index":3490,"title":{},"content":{"102":{"position":[[69,9]]},"174":{"position":[[1207,9]]},"176":{"position":[[1483,10]]},"190":{"position":[[84,10]]}},"keywords":{}}],["technolog",{"_index":3195,"title":{},"content":{"93":{"position":[[866,10]]},"125":{"position":[[1779,10]]},"176":{"position":[[814,10]]}},"keywords":{}}],["tediou",{"_index":3738,"title":{},"content":{"113":{"position":[[796,8]]},"146":{"position":[[32,8]]},"163":{"position":[[777,7]]}},"keywords":{}}],["teeter",{"_index":2222,"title":{},"content":{"53":{"position":[[672,6]]}},"keywords":{}}],["tell",{"_index":1223,"title":{},"content":{"28":{"position":[[775,4]]},"32":{"position":[[2286,4]]},"33":{"position":[[50,5]]},"34":{"position":[[209,5],[924,5]]},"35":{"position":[[47,4]]},"44":{"position":[[1810,5]]},"73":{"position":[[778,4]]},"76":{"position":[[52,4]]},"91":{"position":[[4867,4]]},"101":{"position":[[1080,4]]},"111":{"position":[[691,5]]},"116":{"position":[[2471,7]]},"124":{"position":[[713,4]]},"153":{"position":[[343,4]]},"178":{"position":[[148,5]]}},"keywords":{}}],["temperatur",{"_index":4736,"title":{},"content":{"161":{"position":[[584,11],[712,12],[1298,11]]}},"keywords":{}}],["templat",{"_index":3988,"title":{},"content":{"123":{"position":[[1086,10]]}},"keywords":{}}],["tend",{"_index":241,"title":{},"content":{"4":{"position":[[432,4]]},"40":{"position":[[951,4]]},"82":{"position":[[1200,5]]}},"keywords":{}}],["tenth",{"_index":2813,"title":{},"content":{"83":{"position":[[284,5]]}},"keywords":{}}],["tenuou",{"_index":2326,"title":{},"content":{"58":{"position":[[195,7]]}},"keywords":{}}],["term",{"_index":328,"title":{"9":{"position":[[14,4]]},"10":{"position":[[17,4]]}},"content":{"6":{"position":[[373,5],[822,4]]},"7":{"position":[[191,4]]},"9":{"position":[[269,4],[363,4],[619,4]]},"10":{"position":[[24,4],[178,4]]},"11":{"position":[[22,4]]},"12":{"position":[[254,5],[569,5]]},"13":{"position":[[1350,5]]},"14":{"position":[[2422,5]]},"15":{"position":[[2094,5]]},"30":{"position":[[7509,5]]},"40":{"position":[[3322,5]]},"74":{"position":[[1403,6]]},"86":{"position":[[935,5],[1089,6]]},"100":{"position":[[82,4]]},"125":{"position":[[9891,5]]},"139":{"position":[[385,6]]},"155":{"position":[[219,4]]},"164":{"position":[[1580,5]]},"170":{"position":[[219,5]]},"175":{"position":[[1259,6]]}},"keywords":{}}],["term[1",{"_index":487,"title":{},"content":{"10":{"position":[[143,7],[457,7]]}},"keywords":{}}],["term[2",{"_index":486,"title":{},"content":{"10":{"position":[[132,7],[505,8],[514,11],[537,8],[583,8],[611,8]]}},"keywords":{}}],["term[i",{"_index":477,"title":{},"content":{"9":{"position":[[797,8]]}},"keywords":{}}],["term[i+1",{"_index":476,"title":{},"content":{"9":{"position":[[783,11]]}},"keywords":{}}],["termin",{"_index":861,"title":{},"content":{"20":{"position":[[2785,10]]}},"keywords":{}}],["terribl",{"_index":1163,"title":{},"content":{"25":{"position":[[2651,8]]},"40":{"position":[[2322,8]]},"45":{"position":[[2661,9],[2679,8]]},"97":{"position":[[803,8]]},"98":{"position":[[428,8]]},"106":{"position":[[152,8]]},"109":{"position":[[90,8]]},"150":{"position":[[911,8]]},"199":{"position":[[459,8]]}},"keywords":{}}],["territori",{"_index":15,"title":{},"content":{"1":{"position":[[144,10]]}},"keywords":{}}],["test",{"_index":871,"title":{"21":{"position":[[0,7]]}},"content":{"24":{"position":[[24,5]]},"34":{"position":[[3068,5]]},"35":{"position":[[350,5]]},"38":{"position":[[1307,5]]},"40":{"position":[[2567,5]]},"43":{"position":[[137,8]]},"45":{"position":[[1566,4]]},"86":{"position":[[466,7]]},"121":{"position":[[2043,4],[2218,5]]},"132":{"position":[[707,5]]},"158":{"position":[[438,5]]},"160":{"position":[[3622,5],[3710,4]]},"163":{"position":[[241,4]]},"166":{"position":[[838,7]]},"167":{"position":[[18,4]]},"168":{"position":[[6,4]]},"169":{"position":[[6,4]]},"181":{"position":[[820,7]]},"189":{"position":[[1662,5]]}},"keywords":{}}],["testingpackagingupdatesliter",{"_index":4200,"title":{},"content":{"125":{"position":[[10488,32]]}},"keywords":{}}],["text",{"_index":2072,"title":{},"content":{"51":{"position":[[156,4]]},"115":{"position":[[2517,4],[2611,4]]},"125":{"position":[[3446,4]]},"199":{"position":[[1164,5]]}},"keywords":{}}],["text.loc[~repli",{"_index":2077,"title":{},"content":{"51":{"position":[[277,18]]}},"keywords":{}}],["text.str.contain",{"_index":2075,"title":{},"content":{"51":{"position":[[241,22]]}},"keywords":{}}],["text_norep",{"_index":2076,"title":{},"content":{"51":{"position":[[264,10]]}},"keywords":{}}],["text_norep.map(tknzr.token",{"_index":2083,"title":{},"content":{"51":{"position":[[488,30]]}},"keywords":{}}],["text_norep.str.count",{"_index":2109,"title":{},"content":{"51":{"position":[[1687,25]]}},"keywords":{}}],["textual",{"_index":3062,"title":{},"content":{"90":{"position":[[4715,7]]}},"keywords":{}}],["thank",{"_index":2359,"title":{},"content":{"61":{"position":[[866,5]]},"66":{"position":[[798,6]]},"89":{"position":[[912,5]]},"118":{"position":[[329,7]]},"164":{"position":[[139,7]]}},"keywords":{}}],["thanthi",{"_index":3878,"title":{},"content":{"121":{"position":[[309,8]]}},"keywords":{}}],["that'",{"_index":1315,"title":{},"content":{"29":{"position":[[259,6]]},"34":{"position":[[1189,6]]},"40":{"position":[[1127,6]]},"43":{"position":[[985,6]]},"44":{"position":[[1968,6]]},"57":{"position":[[18,6]]},"64":{"position":[[246,6]]},"66":{"position":[[7,6]]},"96":{"position":[[1427,6]]},"101":{"position":[[137,6]]},"105":{"position":[[2858,6]]},"121":{"position":[[142,6]]},"122":{"position":[[798,6]]},"124":{"position":[[86,6],[162,6]]},"125":{"position":[[104,6],[3335,6],[3610,6]]},"128":{"position":[[385,6]]},"129":{"position":[[137,6]]},"133":{"position":[[347,6]]},"134":{"position":[[102,6]]},"160":{"position":[[1312,6],[2009,6],[3770,6]]},"161":{"position":[[1332,6]]},"176":{"position":[[1163,6],[1602,6]]},"180":{"position":[[331,6]]}},"keywords":{}}],["thatdirectli",{"_index":4840,"title":{},"content":{"166":{"position":[[208,12]]}},"keywords":{}}],["thatno",{"_index":5363,"title":{},"content":{"198":{"position":[[786,6]]}},"keywords":{}}],["thatsmp",{"_index":4967,"title":{},"content":{"173":{"position":[[1835,7]]}},"keywords":{}}],["thatstd::marker::send",{"_index":3810,"title":{},"content":{"116":{"position":[[2424,21]]}},"keywords":{}}],["the#[global_alloc",{"_index":4366,"title":{},"content":{"133":{"position":[[180,22]]}},"keywords":{}}],["the@jit",{"_index":5232,"title":{},"content":{"189":{"position":[[626,7]]}},"keywords":{}}],["thealloc",{"_index":4696,"title":{},"content":{"160":{"position":[[2534,8]]}},"keywords":{}}],["thebillion",{"_index":4227,"title":{},"content":{"127":{"position":[[395,10]]}},"keywords":{}}],["theblack_box",{"_index":4541,"title":{},"content":{"153":{"position":[[274,12]]}},"keywords":{}}],["thebox",{"_index":4652,"title":{},"content":{"160":{"position":[[290,6]]}},"keywords":{}}],["thebuild",{"_index":4111,"title":{},"content":{"125":{"position":[[5187,8],[5714,8]]}},"keywords":{}}],["thecompil",{"_index":4269,"title":{},"content":{"128":{"position":[[1221,11]]},"160":{"position":[[3812,11]]}},"keywords":{}}],["theconst",{"_index":5086,"title":{},"content":{"179":{"position":[[1635,8]]}},"keywords":{}}],["thecore::cel",{"_index":4570,"title":{},"content":{"155":{"position":[[861,13]]}},"keywords":{}}],["thecore::mem::size_ofdocument",{"_index":5319,"title":{},"content":{"194":{"position":[[799,35]]}},"keywords":{}}],["theembedonomicon",{"_index":4684,"title":{},"content":{"160":{"position":[[2075,16]]}},"keywords":{}}],["thefin",{"_index":4135,"title":{},"content":{"125":{"position":[[6358,8]]}},"keywords":{}}],["theglob",{"_index":4352,"title":{},"content":{"132":{"position":[[540,9]]}},"keywords":{}}],["theinterpret",{"_index":5201,"title":{},"content":{"188":{"position":[[3455,15]]}},"keywords":{}}],["thelanguag",{"_index":4017,"title":{},"content":{"125":{"position":[[526,11]]}},"keywords":{}}],["thelittleth",{"_index":2268,"title":{},"content":{"53":{"position":[[1367,16]]}},"keywords":{}}],["themain",{"_index":3913,"title":{},"content":{"121":{"position":[[2035,7]]}},"keywords":{}}],["themessag",{"_index":3377,"title":{},"content":{"97":{"position":[[1709,10]]}},"keywords":{}}],["themselv",{"_index":3814,"title":{},"content":{"116":{"position":[[3128,10]]},"185":{"position":[[306,10]]}},"keywords":{}}],["themultipli",{"_index":5101,"title":{},"content":{"181":{"position":[[462,11]]}},"keywords":{}}],["thenomicon",{"_index":5135,"title":{},"content":{"185":{"position":[[346,12]]}},"keywords":{}}],["theoret",{"_index":1683,"title":{"38":{"position":[[0,11]]}},"content":{"102":{"position":[[327,11]]},"129":{"position":[[2394,13]]},"172":{"position":[[2277,13]]}},"keywords":{}}],["thephantomdata",{"_index":3821,"title":{},"content":{"117":{"position":[[571,14]]}},"keywords":{}}],["theprocessor",{"_index":4950,"title":{},"content":{"173":{"position":[[790,12]]}},"keywords":{}}],["there'",{"_index":275,"title":{},"content":{"4":{"position":[[1040,7]]},"7":{"position":[[1081,7]]},"22":{"position":[[2979,7]]},"30":{"position":[[2760,7]]},"32":{"position":[[253,7]]},"41":{"position":[[57,7]]},"43":{"position":[[1152,7]]},"53":{"position":[[561,7],[1580,7]]},"68":{"position":[[48,7],[105,7]]},"101":{"position":[[1085,7]]},"103":{"position":[[2236,7],[2372,7]]},"106":{"position":[[525,7]]},"108":{"position":[[603,7]]},"115":{"position":[[2900,7]]},"118":{"position":[[39,7]]},"120":{"position":[[815,7]]},"122":{"position":[[49,7],[1089,7]]},"125":{"position":[[3368,7],[3476,7],[7572,7],[9900,7],[10383,7],[10725,7],[11284,7]]},"127":{"position":[[146,7],[1045,7]]},"128":{"position":[[1846,7]]},"135":{"position":[[574,7]]},"139":{"position":[[534,7]]},"148":{"position":[[7,7]]},"158":{"position":[[42,7],[244,7]]},"159":{"position":[[6,7]]},"160":{"position":[[0,7],[198,7],[320,7],[1924,7],[2037,7],[2830,7],[4240,7]]},"161":{"position":[[1175,7]]},"164":{"position":[[1243,7]]},"166":{"position":[[538,7]]},"172":{"position":[[1959,7]]},"174":{"position":[[219,7],[543,7]]},"175":{"position":[[10,7],[476,7],[1625,7]]},"184":{"position":[[760,7]]},"194":{"position":[[706,7]]},"199":{"position":[[41,7],[1102,7]]}},"keywords":{}}],["thereof",{"_index":4700,"title":{},"content":{"160":{"position":[[3025,8]]}},"keywords":{}}],["theseto",{"_index":4961,"title":{},"content":{"173":{"position":[[1268,7]]}},"keywords":{}}],["thestandard",{"_index":3939,"title":{},"content":{"122":{"position":[[354,11]]}},"keywords":{}}],["thesub",{"_index":5270,"title":{},"content":{"192":{"position":[[681,6]]}},"keywords":{}}],["thesync",{"_index":5113,"title":{},"content":{"182":{"position":[[606,7]]},"185":{"position":[[74,7]]}},"keywords":{}}],["they'r",{"_index":1334,"title":{},"content":{"30":{"position":[[453,7]]},"66":{"position":[[375,7]]},"121":{"position":[[2691,7]]},"127":{"position":[[1092,7]]},"135":{"position":[[220,7]]},"150":{"position":[[238,7]]},"158":{"position":[[320,7]]},"176":{"position":[[131,7]]},"185":{"position":[[98,7]]},"190":{"position":[[263,7]]}},"keywords":{}}],["they'v",{"_index":3071,"title":{},"content":{"91":{"position":[[68,7]]}},"keywords":{}}],["thing",{"_index":374,"title":{"143":{"position":[[8,6]]}},"content":{"7":{"position":[[9,6]]},"9":{"position":[[64,6]]},"12":{"position":[[324,6]]},"23":{"position":[[204,6]]},"28":{"position":[[2499,6]]},"33":{"position":[[83,7],[300,6]]},"34":{"position":[[76,6],[3624,6]]},"38":{"position":[[624,6],[1218,6],[1344,6]]},"39":{"position":[[388,6]]},"40":{"position":[[3095,7]]},"49":{"position":[[55,7]]},"59":{"position":[[178,7]]},"60":{"position":[[92,6]]},"73":{"position":[[603,5]]},"82":{"position":[[94,6]]},"91":{"position":[[4690,7]]},"93":{"position":[[28,5]]},"96":{"position":[[71,6]]},"97":{"position":[[856,5],[959,5],[1188,6],[4956,6]]},"98":{"position":[[294,6]]},"104":{"position":[[523,6],[1563,7]]},"105":{"position":[[563,6]]},"112":{"position":[[1074,6],[1265,6]]},"116":{"position":[[2446,5],[3095,6]]},"117":{"position":[[586,5],[751,5],[2005,6]]},"118":{"position":[[63,6]]},"120":{"position":[[652,7]]},"121":{"position":[[344,5],[854,6],[1974,6],[2130,6]]},"123":{"position":[[122,6],[875,6]]},"125":{"position":[[79,7],[2025,6],[2473,6],[2898,6],[3636,5],[3911,6],[4064,5],[4661,6],[9944,7],[10463,6],[10955,6],[11029,6]]},"127":{"position":[[854,6],[1540,6]]},"129":{"position":[[1418,7],[1784,5]]},"130":{"position":[[402,6]]},"132":{"position":[[687,6]]},"135":{"position":[[660,5]]},"139":{"position":[[736,6]]},"141":{"position":[[121,6]]},"142":{"position":[[242,6]]},"143":{"position":[[235,6]]},"150":{"position":[[50,6]]},"155":{"position":[[11,5]]},"160":{"position":[[1998,6],[2688,5]]},"179":{"position":[[275,6]]},"180":{"position":[[10,5]]},"184":{"position":[[402,6]]},"193":{"position":[[679,6]]},"195":{"position":[[674,6]]},"196":{"position":[[1662,6]]}},"keywords":{}}],["thing"",{"_index":3949,"title":{},"content":{"122":{"position":[[900,11]]}},"keywords":{}}],["things"",{"_index":4213,"title":{},"content":{"125":{"position":[[11477,12]]}},"keywords":{}}],["think",{"_index":68,"title":{},"content":{"1":{"position":[[754,8]]},"22":{"position":[[2731,5]]},"28":{"position":[[2477,5]]},"29":{"position":[[338,5]]},"30":{"position":[[4614,8]]},"40":{"position":[[564,5]]},"53":{"position":[[611,5]]},"58":{"position":[[79,5]]},"66":{"position":[[369,5],[512,5],[643,5]]},"69":{"position":[[279,5]]},"88":{"position":[[63,8]]},"95":{"position":[[506,5]]},"97":{"position":[[514,6]]},"98":{"position":[[1171,5]]},"104":{"position":[[196,5]]},"105":{"position":[[3358,5]]},"106":{"position":[[15,5],[1088,5]]},"112":{"position":[[269,5]]},"121":{"position":[[1693,5],[1783,5]]},"122":{"position":[[852,8]]},"123":{"position":[[490,5]]},"125":{"position":[[500,5],[3604,5],[6954,5],[10969,5],[11678,5]]},"128":{"position":[[176,6]]},"129":{"position":[[925,8],[2060,5]]},"130":{"position":[[548,8]]}},"keywords":{}}],["thinkfinance,r",{"_index":4423,"title":{},"content":{"139":{"position":[[600,17]]}},"keywords":{}}],["thinkingtoomuch",{"_index":2274,"title":{},"content":{"53":{"position":[[1471,16]]}},"keywords":{}}],["third",{"_index":2133,"title":{},"content":{"51":{"position":[[2685,5]]},"52":{"position":[[234,5],[422,6]]},"125":{"position":[[10043,6]]}},"keywords":{}}],["thirti",{"_index":291,"title":{},"content":{"4":{"position":[[1349,6]]}},"keywords":{}}],["this"virtu",{"_index":4682,"title":{},"content":{"160":{"position":[[1967,17]]}},"keywords":{}}],["this.i'v",{"_index":4718,"title":{},"content":{"160":{"position":[[4123,9]]}},"keywords":{}}],["those",{"_index":416,"title":{},"content":{"7":{"position":[[781,5]]},"11":{"position":[[243,5]]},"32":{"position":[[660,5]]},"44":{"position":[[144,5]]},"61":{"position":[[75,5]]},"74":{"position":[[111,5]]},"88":{"position":[[2148,5]]},"89":{"position":[[347,5]]},"102":{"position":[[550,5]]},"111":{"position":[[728,5]]},"112":{"position":[[1761,6]]},"123":{"position":[[801,5]]},"125":{"position":[[1365,5],[8289,6]]},"128":{"position":[[1551,5]]},"129":{"position":[[330,5]]},"135":{"position":[[283,5]]},"159":{"position":[[1244,6]]},"160":{"position":[[2389,5]]},"188":{"position":[[4525,5]]},"193":{"position":[[161,5]]}},"keywords":{}}],["though",{"_index":135,"title":{},"content":{"3":{"position":[[36,6]]},"24":{"position":[[3259,6]]},"26":{"position":[[550,7]]},"28":{"position":[[556,7]]},"30":{"position":[[2801,6],[4293,7],[5797,7]]},"33":{"position":[[24,7]]},"40":{"position":[[871,6]]},"41":{"position":[[100,6]]},"43":{"position":[[977,7]]},"51":{"position":[[2714,7]]},"53":{"position":[[2196,7]]},"66":{"position":[[66,7],[735,7]]},"68":{"position":[[204,7]]},"73":{"position":[[33,7]]},"82":{"position":[[1165,7]]},"97":{"position":[[1825,7],[4806,7]]},"105":{"position":[[2830,7]]},"108":{"position":[[333,7]]},"112":{"position":[[1104,6]]},"115":{"position":[[2647,7]]},"116":{"position":[[2408,7]]},"121":{"position":[[2588,7]]},"122":{"position":[[125,7]]},"125":{"position":[[9849,6]]},"129":{"position":[[2596,7]]},"145":{"position":[[273,6]]},"155":{"position":[[661,6]]},"160":{"position":[[2313,7]]},"179":{"position":[[441,6],[789,7]]},"181":{"position":[[17,7]]},"184":{"position":[[451,7],[1231,7]]},"185":{"position":[[435,6]]},"188":{"position":[[3169,6]]},"195":{"position":[[465,6]]},"196":{"position":[[1453,6],[1881,7]]},"197":{"position":[[1184,6]]},"198":{"position":[[203,7]]}},"keywords":{}}],["thought",{"_index":1970,"title":{"176":{"position":[[6,9]]}},"content":{"45":{"position":[[632,7]]},"98":{"position":[[1263,8]]},"112":{"position":[[1323,7]]}},"keywords":{}}],["thoughther",{"_index":3961,"title":{},"content":{"122":{"position":[[1301,11]]}},"keywords":{}}],["thread",{"_index":85,"title":{},"content":{"2":{"position":[[150,7],[212,6]]},"115":{"position":[[492,7],[622,6],[1224,7],[1604,7],[1881,7],[2429,7],[2682,7],[2875,6],[2976,6],[3006,6]]},"116":{"position":[[155,8],[698,7],[1176,7],[1509,7],[1786,7],[2287,7],[2587,6],[2720,6],[2806,6],[3021,7],[3143,6],[3182,6],[3269,8]]},"117":{"position":[[369,8],[435,8],[991,8],[1979,7]]},"143":{"position":[[139,6]]},"173":{"position":[[903,9]]},"184":{"position":[[1095,7]]},"185":{"position":[[183,6],[776,7]]},"188":{"position":[[652,7],[1885,8],[1956,6],[2001,9],[2018,6],[2042,7],[2154,7],[2200,7],[2334,6],[2370,6],[2691,8],[2866,7],[3187,6],[3348,8],[3417,6],[3484,6],[3697,6]]},"189":{"position":[[2010,8],[2313,6],[2339,7],[2613,6]]}},"keywords":{}}],["thread'",{"_index":3768,"title":{},"content":{"115":{"position":[[584,8]]}},"keywords":{}}],["thread(target=cython_gil",{"_index":5180,"title":{},"content":{"188":{"position":[[2065,25],[2106,25],[2476,25],[2971,25]]}},"keywords":{}}],["thread(target=cython_nogil",{"_index":5190,"title":{},"content":{"188":{"position":[[2433,27],[3012,27]]}},"keywords":{}}],["thread(target=numba_gil",{"_index":5244,"title":{},"content":{"189":{"position":[[2096,24],[2136,24],[2419,24],[2666,24]]}},"keywords":{}}],["thread(target=numba_nogil",{"_index":5248,"title":{},"content":{"189":{"position":[[2377,26],[2706,26]]}},"keywords":{}}],["thread::current().id",{"_index":4614,"title":{},"content":{"157":{"position":[[652,22]]}},"keywords":{}}],["thread_id",{"_index":4613,"title":{},"content":{"157":{"position":[[581,9]]}},"keywords":{}}],["three",{"_index":148,"title":{},"content":{"3":{"position":[[337,5]]},"90":{"position":[[4934,5]]},"139":{"position":[[88,5]]},"143":{"position":[[512,5]]},"160":{"position":[[840,5]]}},"keywords":{}}],["threshold",{"_index":1959,"title":{},"content":{"45":{"position":[[86,9],[2612,10]]}},"keywords":{}}],["through",{"_index":64,"title":{},"content":{"1":{"position":[[708,7]]},"4":{"position":[[629,7]]},"7":{"position":[[1129,7]]},"11":{"position":[[122,7]]},"45":{"position":[[536,7]]},"58":{"position":[[122,7]]},"61":{"position":[[1317,7]]},"62":{"position":[[150,7],[323,7],[1751,7]]},"65":{"position":[[2151,7]]},"72":{"position":[[442,7]]},"74":{"position":[[413,7]]},"77":{"position":[[10,7]]},"91":{"position":[[4012,8]]},"111":{"position":[[156,7]]},"121":{"position":[[2642,7]]},"122":{"position":[[934,7]]},"152":{"position":[[606,7]]},"160":{"position":[[2157,7]]},"164":{"position":[[621,7]]}},"keywords":{}}],["through"design",{"_index":5034,"title":{},"content":{"175":{"position":[[1488,21]]}},"keywords":{}}],["throughout",{"_index":1444,"title":{},"content":{"30":{"position":[[8169,10]]},"66":{"position":[[299,10]]},"86":{"position":[[441,10]]}},"keywords":{}}],["throw",{"_index":1965,"title":{},"content":{"45":{"position":[[293,5]]},"82":{"position":[[118,7]]}},"keywords":{}}],["thrown",{"_index":1398,"title":{},"content":{"30":{"position":[[4270,6]]},"66":{"position":[[467,6]]}},"keywords":{}}],["thu",{"_index":511,"title":{},"content":{"11":{"position":[[277,5]]},"72":{"position":[[610,4]]},"93":{"position":[[772,4]]},"122":{"position":[[532,4]]},"125":{"position":[[4691,4]]},"160":{"position":[[2554,4]]},"188":{"position":[[3272,5]]},"194":{"position":[[650,5]]},"198":{"position":[[830,5]]}},"keywords":{}}],["thumb",{"_index":3920,"title":{},"content":{"121":{"position":[[2281,5]]}},"keywords":{}}],["thursdaysgohard",{"_index":2199,"title":{},"content":{"53":{"position":[[215,16]]}},"keywords":{}}],["ti",{"_index":3721,"title":{},"content":{"112":{"position":[[1198,4]]},"129":{"position":[[63,4]]}},"keywords":{}}],["tic",{"_index":534,"title":{},"content":{"12":{"position":[[534,5]]},"13":{"position":[[1505,5]]},"14":{"position":[[2577,5]]},"15":{"position":[[2249,5]]}},"keywords":{}}],["tick",{"_index":412,"title":{"56":{"position":[[0,4]]}},"content":{"7":{"position":[[694,5],[789,5]]},"17":{"position":[[259,6],[318,4]]},"18":{"position":[[87,6],[129,4],[186,4]]},"19":{"position":[[366,6],[399,4]]},"20":{"position":[[282,6],[317,4],[1247,5],[1316,5],[1408,5]]}},"keywords":{}}],["tick_width",{"_index":424,"title":{},"content":{"7":{"position":[[927,10]]}},"keywords":{}}],["ticker",{"_index":709,"title":{},"content":{"17":{"position":[[144,7],[326,8]]},"18":{"position":[[37,6],[137,8],[194,9]]},"19":{"position":[[139,6],[407,8]]},"20":{"position":[[325,8],[1268,10],[1339,10],[1436,10]]},"39":{"position":[[3114,6],[3124,8]]},"88":{"position":[[802,7]]},"91":{"position":[[2159,8],[2297,7],[2805,7],[3428,7],[3561,7]]},"92":{"position":[[617,7]]},"93":{"position":[[2312,6],[2960,7],[4217,7],[4618,7],[4696,6],[4783,7],[5112,6],[5198,7],[5528,7]]}},"keywords":{}}],["ticker.replac",{"_index":3280,"title":{},"content":{"93":{"position":[[4799,19],[5214,19]]}},"keywords":{}}],["ticker_d",{"_index":3119,"title":{},"content":{"91":{"position":[[2275,12]]}},"keywords":{}}],["ticker_data",{"_index":2855,"title":{},"content":{"88":{"position":[[766,11],[909,11]]},"91":{"position":[[2761,11],[3517,11]]},"92":{"position":[[573,11]]},"93":{"position":[[4181,11],[4324,11]]}},"keywords":{}}],["ticker_data[ev",{"_index":3130,"title":{},"content":{"91":{"position":[[2820,17],[3582,17]]},"92":{"position":[[632,17]]}},"keywords":{}}],["ticker_dates.append((tick",{"_index":3123,"title":{},"content":{"91":{"position":[[2367,28]]}},"keywords":{}}],["ticker_info",{"_index":1624,"title":{},"content":{"34":{"position":[[1641,11]]},"39":{"position":[[2202,11]]}},"keywords":{}}],["ticker_info.column",{"_index":1753,"title":{},"content":{"39":{"position":[[2372,20]]}},"keywords":{}}],["ticker_info["close"].valu",{"_index":1629,"title":{},"content":{"34":{"position":[[1762,37]]}},"keywords":{}}],["ticker_info["open"].valu",{"_index":1628,"title":{},"content":{"34":{"position":[[1712,36]]}},"keywords":{}}],["ticker_info[:end].index",{"_index":1747,"title":{},"content":{"39":{"position":[[2281,23]]}},"keywords":{}}],["ticker_info[d:][close_column",{"_index":1758,"title":{},"content":{"39":{"position":[[2532,30]]}},"keywords":{}}],["time",{"_index":245,"title":{},"content":{"4":{"position":[[553,4]]},"6":{"position":[[312,4],[395,4],[998,4]]},"7":{"position":[[56,5]]},"11":{"position":[[146,4],[208,5],[249,5]]},"12":{"position":[[575,4],[639,5],[648,4]]},"13":{"position":[[923,4],[1538,4],[1607,5],[1648,5],[1965,5],[2021,5],[2077,5],[2133,5],[2189,5]]},"14":{"position":[[1941,4],[2621,4],[2690,5],[2731,5],[3037,5],[3093,5],[3149,5],[3205,5],[3261,5]]},"15":{"position":[[204,6],[1609,4],[2295,4],[2364,5],[2405,5],[2708,5],[2764,5],[2820,5],[2876,5],[2932,5]]},"20":{"position":[[2311,5]]},"28":{"position":[[19,4],[4406,5]]},"30":{"position":[[2379,5],[4099,4]]},"32":{"position":[[418,4],[1107,5]]},"38":{"position":[[212,5]]},"40":{"position":[[866,4],[1451,5]]},"43":{"position":[[1319,4]]},"45":{"position":[[1349,4]]},"46":{"position":[[629,5],[676,5]]},"49":{"position":[[263,4]]},"51":{"position":[[1499,4],[2612,4],[3540,4]]},"53":{"position":[[1410,4]]},"57":{"position":[[579,4],[703,4]]},"58":{"position":[[299,5]]},"61":{"position":[[447,5],[1207,4]]},"62":{"position":[[70,4],[264,5]]},"64":{"position":[[1999,5]]},"66":{"position":[[313,4],[572,4],[777,4],[886,5]]},"75":{"position":[[1167,5]]},"76":{"position":[[2282,5]]},"78":{"position":[[106,4],[376,5],[972,5]]},"79":{"position":[[176,5]]},"80":{"position":[[198,5]]},"81":{"position":[[177,5]]},"82":{"position":[[976,5]]},"86":{"position":[[1110,4]]},"88":{"position":[[146,4]]},"91":{"position":[[4476,5],[4490,5],[4982,4],[5075,4],[5286,5],[5300,5],[5669,5],[5683,5]]},"92":{"position":[[1249,5],[1263,5],[1807,5],[1821,5],[1966,5],[1980,5]]},"93":{"position":[[305,5],[1176,5]]},"96":{"position":[[1359,4],[1897,4],[2041,5]]},"97":{"position":[[2101,4],[5290,4]]},"100":{"position":[[294,4]]},"102":{"position":[[1535,5]]},"104":{"position":[[1385,5]]},"105":{"position":[[2594,5]]},"109":{"position":[[40,4]]},"111":{"position":[[10,4]]},"113":{"position":[[95,4],[1517,4]]},"116":{"position":[[2403,4]]},"120":{"position":[[149,4],[336,4],[768,4],[937,4]]},"121":{"position":[[882,4],[964,5],[2158,5]]},"123":{"position":[[922,4]]},"124":{"position":[[812,5]]},"125":{"position":[[455,4],[9985,4]]},"127":{"position":[[1448,4]]},"129":{"position":[[10,4]]},"135":{"position":[[166,4]]},"136":{"position":[[613,4],[806,4]]},"139":{"position":[[466,4],[618,4],[725,4]]},"145":{"position":[[5,5]]},"156":{"position":[[311,5]]},"157":{"position":[[64,4]]},"160":{"position":[[310,5],[3887,4]]},"161":{"position":[[100,4],[1221,5],[1704,5]]},"164":{"position":[[10,4]]},"167":{"position":[[52,4]]},"170":{"position":[[386,4]]},"172":{"position":[[877,4],[1135,4],[1739,4],[2125,4]]},"175":{"position":[[1270,4]]},"176":{"position":[[1088,5],[1272,5]]},"178":{"position":[[353,4]]},"179":{"position":[[1494,5]]},"180":{"position":[[202,5]]},"182":{"position":[[526,4]]},"184":{"position":[[991,5]]},"185":{"position":[[197,5]]},"188":{"position":[[1470,4],[1546,6],[1578,6],[1628,5],[1642,6],[1676,6],[1726,5],[1813,4],[1922,4],[1982,5],[1989,6],[2245,6],[2298,5],[2421,6],[2562,6],[2614,5],[2641,4],[2679,4],[2907,6],[3100,6],[3150,5]]},"189":{"position":[[349,4],[934,4],[1549,6],[1736,6],[1766,6],[1818,5],[1893,4],[2084,6],[2221,6],[2274,5],[2365,6],[2504,6],[2557,5],[2654,6],[2793,6],[2843,5]]}},"keywords":{}}],["time"",{"_index":1799,"title":{},"content":{"40":{"position":[[528,11],[2064,11],[3008,11]]},"188":{"position":[[2739,10]]}},"keywords":{}}],["time.perf_count",{"_index":2754,"title":{},"content":{"78":{"position":[[233,19],[324,19]]}},"keywords":{}}],["time.th",{"_index":5061,"title":{},"content":{"178":{"position":[[677,8]]}},"keywords":{}}],["timedelta",{"_index":708,"title":{},"content":{"17":{"position":[[134,9]]},"65":{"position":[[2308,9]]},"90":{"position":[[359,9]]},"93":{"position":[[1331,9],[3918,9]]}},"keywords":{}}],["timedelta(day",{"_index":3217,"title":{},"content":{"93":{"position":[[2164,15]]}},"keywords":{}}],["timedelta(days=0",{"_index":3216,"title":{},"content":{"93":{"position":[[2095,17]]}},"keywords":{}}],["timedelta(days=1",{"_index":3042,"title":{},"content":{"90":{"position":[[4066,17]]}},"keywords":{}}],["timedelta(days=20",{"_index":3285,"title":{},"content":{"93":{"position":[[4912,18],[5327,18]]}},"keywords":{}}],["timedelta(minutes=minutes_left",{"_index":2532,"title":{},"content":{"65":{"position":[[2399,31]]}},"keywords":{}}],["timestamp",{"_index":4772,"title":{},"content":{"163":{"position":[[1253,9],[1343,9]]},"173":{"position":[[1291,9]]}},"keywords":{}}],["timestamp_high",{"_index":4786,"title":{},"content":{"163":{"position":[[1884,15]]}},"keywords":{}}],["timestamp_low",{"_index":4787,"title":{},"content":{"163":{"position":[[1900,14]]}},"keywords":{}}],["timestr",{"_index":4391,"title":{},"content":{"136":{"position":[[400,8]]}},"keywords":{}}],["titl",{"_index":2819,"title":{},"content":{"85":{"position":[[43,5],[101,5]]},"161":{"position":[[322,5]]}},"keywords":{}}],["tknzr",{"_index":2082,"title":{},"content":{"51":{"position":[[454,5]]}},"keywords":{}}],["tlb",{"_index":4987,"title":{},"content":{"174":{"position":[[654,3],[807,3]]},"176":{"position":[[662,4]]}},"keywords":{}}],["tldr",{"_index":3664,"title":{},"content":{"108":{"position":[[328,4]]}},"keywords":{}}],["to:router.get("/"",{"_index":3436,"title":{},"content":{"97":{"position":[[6393,28]]}},"keywords":{}}],["to_str",{"_index":4273,"title":{},"content":{"128":{"position":[[1919,12]]}},"keywords":{}}],["to_string(&self",{"_index":4297,"title":{},"content":{"129":{"position":[[1467,20]]}},"keywords":{}}],["to_string()i",{"_index":4294,"title":{},"content":{"129":{"position":[[1238,13]]}},"keywords":{}}],["tock",{"_index":2304,"title":{"56":{"position":[[5,7]]}},"content":{},"keywords":{}}],["today",{"_index":2253,"title":{},"content":{"53":{"position":[[1174,6],[2117,6]]},"98":{"position":[[330,6]]},"148":{"position":[[342,6]]}},"keywords":{}}],["today'",{"_index":1739,"title":{},"content":{"39":{"position":[[1840,7]]}},"keywords":{}}],["todays_purchas",{"_index":1636,"title":{},"content":{"34":{"position":[[2098,15],[2217,15]]},"39":{"position":[[1311,15],[1437,15]]}},"keywords":{}}],["todo",{"_index":860,"title":{},"content":{"20":{"position":[[2736,5]]}},"keywords":{}}],["togeth",{"_index":514,"title":{"52":{"position":[[15,9]]}},"content":{"11":{"position":[[325,9]]},"40":{"position":[[3135,8]]},"52":{"position":[[538,9]]},"74":{"position":[[1360,8]]},"76":{"position":[[1876,9]]},"95":{"position":[[462,9]]},"125":{"position":[[10179,8]]},"129":{"position":[[77,9]]},"130":{"position":[[355,9]]}},"keywords":{}}],["token",{"_index":2079,"title":{},"content":{"51":{"position":[[357,8],[479,6],[1152,7]]},"61":{"position":[[1674,8],[2269,5]]}},"keywords":{}}],["token_typ",{"_index":2405,"title":{},"content":{"62":{"position":[[520,13]]}},"keywords":{}}],["tokens.map(lambda",{"_index":2085,"title":{},"content":{"51":{"position":[[533,17]]}},"keywords":{}}],["told",{"_index":1205,"title":{},"content":{"28":{"position":[[219,4]]},"34":{"position":[[831,4]]},"43":{"position":[[1245,4]]},"121":{"position":[[1342,4]]},"125":{"position":[[2572,5]]}},"keywords":{}}],["tomak",{"_index":4400,"title":{},"content":{"136":{"position":[[814,6]]}},"keywords":{}}],["tomorrow",{"_index":1587,"title":{},"content":{"33":{"position":[[1124,8]]},"34":{"position":[[614,9]]}},"keywords":{}}],["tomorrow'",{"_index":1740,"title":{},"content":{"39":{"position":[[1857,10]]}},"keywords":{}}],["ton",{"_index":4799,"title":{},"content":{"163":{"position":[[2481,4]]},"164":{"position":[[219,3]]},"188":{"position":[[261,4]]}},"keywords":{}}],["tongu",{"_index":4026,"title":{},"content":{"125":{"position":[[780,6]]}},"keywords":{}}],["too.mi",{"_index":2337,"title":{},"content":{"58":{"position":[[650,6]]}},"keywords":{}}],["took",{"_index":2808,"title":{},"content":{"82":{"position":[[1065,4]]},"97":{"position":[[2387,4],[5162,4],[6159,4]]},"121":{"position":[[2089,4]]},"132":{"position":[[1013,4]]}},"keywords":{}}],["tool",{"_index":149,"title":{},"content":{"3":{"position":[[357,5]]},"4":{"position":[[142,4],[252,8],[674,6],[1123,5],[1448,5]]},"125":{"position":[[2364,4],[6470,5],[7070,4],[7220,5],[7279,7],[9338,5],[9503,5],[10645,5]]},"137":{"position":[[91,5]]},"139":{"position":[[270,5]]},"158":{"position":[[467,5]]},"160":{"position":[[123,5],[4195,5]]},"165":{"position":[[364,7]]},"174":{"position":[[720,5]]},"176":{"position":[[203,5],[1188,5]]},"190":{"position":[[919,5]]}},"keywords":{}}],["toolchain",{"_index":4084,"title":{},"content":{"125":{"position":[[3683,10]]}},"keywords":{}}],["toolchainlook",{"_index":4136,"title":{},"content":{"125":{"position":[[6367,14]]}},"keywords":{}}],["toopen",{"_index":4107,"title":{},"content":{"125":{"position":[[5105,6]]}},"keywords":{}}],["top",{"_index":2541,"title":{},"content":{"66":{"position":[[62,3]]},"105":{"position":[[948,3]]},"110":{"position":[[214,3]]},"125":{"position":[[11338,3]]}},"keywords":{}}],["topic",{"_index":4486,"title":{},"content":{"148":{"position":[[534,6]]},"160":{"position":[[51,6]]}},"keywords":{}}],["toq",{"_index":536,"title":{},"content":{"12":{"position":[[582,5]]},"13":{"position":[[1545,5]]},"14":{"position":[[2628,5]]},"15":{"position":[[2302,5]]}},"keywords":{}}],["tostr",{"_index":4245,"title":{},"content":{"127":{"position":[[1484,10]]}},"keywords":{}}],["total",{"_index":512,"title":{},"content":{"11":{"position":[[299,5]]},"57":{"position":[[29,5]]},"66":{"position":[[89,7]]},"85":{"position":[[336,5]]},"97":{"position":[[231,7]]},"100":{"position":[[205,5]]},"125":{"position":[[1800,5],[1893,7]]},"129":{"position":[[1656,7]]},"136":{"position":[[88,7],[929,6]]},"163":{"position":[[171,5],[1082,5]]},"188":{"position":[[1609,6],[1707,6],[2279,6],[2595,6],[3131,6]]},"189":{"position":[[1799,6],[2255,6],[2538,6],[2824,6]]},"193":{"position":[[2324,5]]},"196":{"position":[[1217,5],[1628,5],[1830,5]]}},"keywords":{}}],["total_coupon",{"_index":567,"title":{},"content":{"13":{"position":[[714,13]]},"14":{"position":[[1571,13],[1788,13],[1804,13],[1862,13],[2035,13]]},"15":{"position":[[958,13],[1379,13],[1395,13],[1530,13],[1703,13]]}},"keywords":{}}],["total_coupons)*exp((prod(forward_structure[i:end",{"_index":647,"title":{},"content":{"14":{"position":[[1697,50]]},"15":{"position":[[1087,50]]}},"keywords":{}}],["total_data",{"_index":3034,"title":{},"content":{"90":{"position":[[3786,10]]}},"keywords":{}}],["total_data.ix[ev",{"_index":3036,"title":{},"content":{"90":{"position":[[3855,20]]}},"keywords":{}}],["total_dist",{"_index":5291,"title":{},"content":{"193":{"position":[[1745,16],[2700,16]]}},"keywords":{}}],["total_heartbeat",{"_index":2309,"title":{},"content":{"57":{"position":[[148,16]]},"64":{"position":[[1700,16]]}},"keywords":{}}],["totalcap'n",{"_index":4860,"title":{},"content":{"168":{"position":[[189,10]]},"169":{"position":[[303,10]]}},"keywords":{}}],["touch",{"_index":4193,"title":{},"content":{"125":{"position":[[9820,5]]}},"keywords":{}}],["toward",{"_index":2780,"title":{"100":{"position":[[0,7]]}},"content":{"79":{"position":[[47,7]]},"80":{"position":[[40,7],[69,7]]}},"keywords":{}}],["trace",{"_index":4617,"title":{"158":{"position":[[0,7]]}},"content":{},"keywords":{}}],["track",{"_index":2728,"title":{},"content":{"76":{"position":[[2104,5]]},"132":{"position":[[638,5]]},"158":{"position":[[306,5],[373,8]]},"175":{"position":[[1005,5]]}},"keywords":{}}],["tracker",{"_index":3244,"title":{},"content":{"93":{"position":[[2952,7]]}},"keywords":{}}],["trade",{"_index":698,"title":{"17":{"position":[[0,7]]}},"content":{"40":{"position":[[806,5]]},"41":{"position":[[212,6]]},"163":{"position":[[191,6]]}},"keywords":{}}],["trade_calendar",{"_index":2970,"title":{},"content":{"90":{"position":[[521,14]]}},"keywords":{}}],["trade_calendar.rules.pop(6",{"_index":2971,"title":{},"content":{"90":{"position":[[565,27]]}},"keywords":{}}],["trade_calendar.rules.pop(7",{"_index":2973,"title":{},"content":{"90":{"position":[[615,27]]}},"keywords":{}}],["tradeday",{"_index":2975,"title":{},"content":{"90":{"position":[[666,8]]}},"keywords":{}}],["tradeday(horizon):ev",{"_index":3131,"title":{},"content":{"91":{"position":[[2838,24]]},"92":{"position":[[650,24]]}},"keywords":{}}],["tradeday(horizon):event+tradeday(horizon)]['clos",{"_index":3148,"title":{},"content":{"91":{"position":[[3600,51]]}},"keywords":{}}],["tradeday(horizon+1",{"_index":3030,"title":{},"content":{"90":{"position":[[3662,19],[3695,19]]}},"keywords":{}}],["tradeday(x*20",{"_index":3043,"title":{},"content":{"90":{"position":[[4086,14]]}},"keywords":{}}],["tradeoff",{"_index":3482,"title":{},"content":{"101":{"position":[[643,9],[780,8],[1006,9]]},"104":{"position":[[1420,8]]},"166":{"position":[[309,10]]},"198":{"position":[[319,9]]}},"keywords":{}}],["traffic",{"_index":5038,"title":{},"content":{"175":{"position":[[1674,8]]}},"keywords":{}}],["trail",{"_index":1840,"title":{},"content":{"40":{"position":[[3581,6]]}},"keywords":{}}],["train",{"_index":2039,"title":{},"content":{"47":{"position":[[32,8]]}},"keywords":{}}],["train_size=.7",{"_index":2047,"title":{},"content":{"47":{"position":[[207,14]]}},"keywords":{}}],["train_test_split",{"_index":2041,"title":{},"content":{"47":{"position":[[85,16],[183,17]]}},"keywords":{}}],["trait",{"_index":3379,"title":{},"content":{"97":{"position":[[1853,5],[3240,5]]},"115":{"position":[[945,5],[1259,5],[1639,5],[1916,5]]},"116":{"position":[[944,5],[1211,5],[1544,5],[1821,5],[3067,6]]},"129":{"position":[[191,7]]},"132":{"position":[[560,6]]},"185":{"position":[[259,5]]},"197":{"position":[[1,6],[81,6],[109,6],[129,7],[185,5],[293,5]]},"198":{"position":[[676,6],[1050,5]]}},"keywords":{}}],["trait.interior",{"_index":5115,"title":{},"content":{"182":{"position":[[621,14]]}},"keywords":{}}],["transcrib",{"_index":3880,"title":{},"content":{"121":{"position":[[396,12]]}},"keywords":{}}],["transfer",{"_index":3428,"title":{},"content":{"97":{"position":[[5715,12]]},"116":{"position":[[2568,11],[3223,8]]},"117":{"position":[[403,8]]}},"keywords":{}}],["transform",{"_index":3533,"title":{},"content":{"103":{"position":[[1348,11],[1472,12]]},"105":{"position":[[1392,12]]}},"keywords":{}}],["transformed.tobyt",{"_index":3583,"title":{},"content":{"105":{"position":[[631,21],[782,21],[1024,21]]}},"keywords":{}}],["transient",{"_index":4672,"title":{},"content":{"160":{"position":[[1226,10]]},"199":{"position":[[645,9]]}},"keywords":{}}],["transit",{"_index":2674,"title":{},"content":{"75":{"position":[[1152,10]]}},"keywords":{}}],["translat",{"_index":3868,"title":{"121":{"position":[[8,12]]}},"content":{"128":{"position":[[1078,10]]},"150":{"position":[[1,12]]},"172":{"position":[[2035,11]]}},"keywords":{}}],["transpar",{"_index":4969,"title":{},"content":{"173":{"position":[[1999,12]]}},"keywords":{}}],["transpil",{"_index":5146,"title":{},"content":{"188":{"position":[[81,10]]}},"keywords":{}}],["trap",{"_index":2828,"title":{},"content":{"86":{"position":[[254,4]]},"129":{"position":[[28,4]]}},"keywords":{}}],["treat",{"_index":1179,"title":{},"content":{"26":{"position":[[749,5]]},"49":{"position":[[166,5],[662,5]]},"98":{"position":[[211,7]]},"178":{"position":[[185,5]]},"179":{"position":[[1737,5]]}},"keywords":{}}],["treatment",{"_index":2839,"title":{},"content":{"88":{"position":[[192,9]]}},"keywords":{}}],["trebl",{"_index":3550,"title":{"104":{"position":[[9,9]]}},"content":{"103":{"position":[[2395,7]]}},"keywords":{}}],["trend",{"_index":1293,"title":{"91":{"position":[[14,8]]},"92":{"position":[[14,8]]}},"content":{"28":{"position":[[2782,5],[4142,6],[4387,8]]},"30":{"position":[[2360,8],[2681,6],[4029,5]]},"38":{"position":[[469,5],[608,6]]},"40":{"position":[[2483,5]]},"88":{"position":[[2415,5],[2761,5],[3164,5],[3609,5],[3737,5]]},"89":{"position":[[570,8],[702,8],[856,5]]},"91":{"position":[[81,8],[1433,8],[1510,8],[2984,5],[3176,8],[4530,8],[5355,7]]},"92":{"position":[[126,8],[209,8],[796,5],[988,8]]},"93":{"position":[[285,8]]}},"keywords":{}}],["trend_funct",{"_index":3141,"title":{},"content":{"91":{"position":[[3340,16]]}},"keywords":{}}],["trend_function(tick",{"_index":3147,"title":{},"content":{"91":{"position":[[3477,22]]}},"keywords":{}}],["tri",{"_index":141,"title":{},"content":{"3":{"position":[[176,5],[331,5],[702,5],[1049,5]]},"6":{"position":[[177,6]]},"13":{"position":[[66,3]]},"22":{"position":[[1655,4]]},"26":{"position":[[333,6]]},"28":{"position":[[441,3],[581,6]]},"30":{"position":[[7054,6],[9828,4]]},"34":{"position":[[604,3],[3611,3]]},"38":{"position":[[287,6]]},"39":{"position":[[399,6]]},"40":{"position":[[2579,3]]},"45":{"position":[[878,3],[928,3],[2739,3]]},"52":{"position":[[93,3]]},"53":{"position":[[332,6]]},"54":{"position":[[56,6]]},"57":{"position":[[271,6]]},"64":{"position":[[104,3]]},"73":{"position":[[721,6]]},"75":{"position":[[179,6],[218,6]]},"76":{"position":[[1224,6]]},"77":{"position":[[176,3]]},"85":{"position":[[183,3],[375,6],[453,6]]},"86":{"position":[[898,6]]},"91":{"position":[[2756,4],[3652,4]]},"92":{"position":[[568,4]]},"93":{"position":[[4738,4],[5153,4]]},"95":{"position":[[553,6]]},"96":{"position":[[278,6],[1046,3],[1587,3],[2123,3]]},"97":{"position":[[905,6],[1267,4],[2106,6],[2593,6],[4283,3],[4368,3],[5426,6]]},"102":{"position":[[16,3],[436,3]]},"103":{"position":[[1548,3]]},"104":{"position":[[48,6],[116,5],[754,6]]},"105":{"position":[[2844,3],[3036,3]]},"112":{"position":[[1086,3]]},"113":{"position":[[1327,6]]},"115":{"position":[[36,3]]},"120":{"position":[[568,3],[676,3]]},"121":{"position":[[65,3],[149,6],[1185,6],[1372,3],[1563,3]]},"123":{"position":[[85,3],[851,3]]},"125":{"position":[[172,6],[277,6],[1934,3],[2378,5],[3028,3],[3556,3],[4461,3],[10268,6]]},"129":{"position":[[2042,5]]},"160":{"position":[[2960,6],[4133,5]]},"161":{"position":[[1382,6]]},"164":{"position":[[91,5]]}},"keywords":{}}],["trial",{"_index":3964,"title":{"123":{"position":[[0,5]]}},"content":{},"keywords":{}}],["triangl",{"_index":2573,"title":{},"content":{"68":{"position":[[911,8]]}},"keywords":{}}],["trick",{"_index":4935,"title":{},"content":{"172":{"position":[[2505,7]]}},"keywords":{}}],["tricki",{"_index":2500,"title":{},"content":{"65":{"position":[[15,6]]},"190":{"position":[[760,6]]}},"keywords":{}}],["triedan",{"_index":4176,"title":{},"content":{"125":{"position":[[8880,7]]}},"keywords":{}}],["trigger",{"_index":4137,"title":{},"content":{"125":{"position":[[6414,8]]},"127":{"position":[[683,8]]},"143":{"position":[[128,8]]},"144":{"position":[[223,8],[342,7],[391,7]]},"145":{"position":[[310,7],[401,8]]},"146":{"position":[[186,8],[300,7],[387,8]]},"147":{"position":[[342,7]]},"166":{"position":[[858,7]]},"172":{"position":[[74,10]]},"173":{"position":[[1073,7],[1446,7]]},"176":{"position":[[486,8]]},"180":{"position":[[227,7]]}},"keywords":{}}],["trim",{"_index":4281,"title":{},"content":{"129":{"position":[[498,7]]}},"keywords":{}}],["trim_start=start",{"_index":1745,"title":{},"content":{"39":{"position":[[2227,17]]}},"keywords":{}}],["trim_start=start_d",{"_index":1006,"title":{},"content":{"23":{"position":[[408,22],[475,22],[543,22],[612,22]]}},"keywords":{}}],["triumph",{"_index":2817,"title":{},"content":{"83":{"position":[[611,9]]}},"keywords":{}}],["trivia",{"_index":4429,"title":{},"content":{"139":{"position":[[944,6]]}},"keywords":{}}],["trivial",{"_index":2555,"title":{},"content":{"68":{"position":[[65,7]]},"72":{"position":[[16,7]]},"74":{"position":[[1035,8]]},"96":{"position":[[615,7]]},"97":{"position":[[1054,7],[2817,7]]},"110":{"position":[[44,7]]},"163":{"position":[[557,7]]},"190":{"position":[[202,7]]}},"keywords":{}}],["true",{"_index":894,"title":{},"content":{"22":{"position":[[441,4],[1851,4]]},"32":{"position":[[997,5]]},"75":{"position":[[1264,4]]},"93":{"position":[[1709,4]]},"121":{"position":[[1038,5],[1095,6]]},"190":{"position":[[983,4]]}},"keywords":{}}],["truli",{"_index":3361,"title":{},"content":{"97":{"position":[[180,5]]},"150":{"position":[[178,5]]}},"keywords":{}}],["truth",{"_index":4052,"title":{},"content":{"125":{"position":[[1736,5],[2563,5]]}},"keywords":{}}],["tsconfig",{"_index":103,"title":{},"content":{"2":{"position":[[416,9]]}},"keywords":{}}],["tstate",{"_index":5207,"title":{},"content":{"188":{"position":[[3690,6]]}},"keywords":{}}],["tune",{"_index":4993,"title":{},"content":{"174":{"position":[[1083,6]]}},"keywords":{}}],["tupl",{"_index":4790,"title":{},"content":{"163":{"position":[[1948,7]]}},"keywords":{}}],["turn",{"_index":744,"title":{"133":{"position":[[0,7]]}},"content":{"19":{"position":[[207,5]]},"33":{"position":[[295,4]]},"34":{"position":[[297,4],[3223,6],[3973,4]]},"51":{"position":[[2557,5]]},"53":{"position":[[239,5]]},"90":{"position":[[3541,4]]},"96":{"position":[[1808,5]]},"108":{"position":[[77,7]]},"118":{"position":[[281,7]]},"120":{"position":[[373,4],[438,5]]},"121":{"position":[[1419,5],[2192,5]]},"125":{"position":[[11313,6]]},"127":{"position":[[1152,4]]},"129":{"position":[[324,5]]},"150":{"position":[[338,7]]},"152":{"position":[[490,4],[989,4]]},"156":{"position":[[931,4],[1095,4]]},"161":{"position":[[1563,6]]},"170":{"position":[[22,6]]},"173":{"position":[[885,7]]},"181":{"position":[[412,6]]}},"keywords":{}}],["tweak",{"_index":102,"title":{},"content":{"2":{"position":[[403,8]]},"34":{"position":[[61,5]]},"35":{"position":[[140,5]]}},"keywords":{}}],["tweet",{"_index":2050,"title":{"48":{"position":[[0,5]]}},"content":{"49":{"position":[[24,7],[711,6]]},"50":{"position":[[23,5],[222,6]]},"51":{"position":[[121,6],[191,6],[1473,5],[1574,6],[1954,5],[2200,6],[2691,6],[2789,7],[2930,6],[3051,7]]},"52":{"position":[[912,5],[1085,5],[1108,5],[1116,7],[1129,6]]},"53":{"position":[[59,6],[1810,6]]}},"keywords":{}}],["tweets.text",{"_index":2073,"title":{},"content":{"51":{"position":[[163,11]]}},"keywords":{}}],["tweettoken",{"_index":2081,"title":{},"content":{"51":{"position":[[439,14],[462,16]]}},"keywords":{}}],["twenti",{"_index":2195,"title":{},"content":{"53":{"position":[[45,6]]}},"keywords":{}}],["twice",{"_index":1599,"title":{},"content":{"34":{"position":[[847,5]]},"189":{"position":[[2057,5]]}},"keywords":{}}],["twice!"",{"_index":5144,"title":{},"content":{"186":{"position":[[648,15]]}},"keywords":{}}],["twitter",{"_index":2063,"title":{},"content":{"50":{"position":[[57,7],[193,7]]},"51":{"position":[[2620,8]]},"53":{"position":[[99,7],[2163,7]]}},"keywords":{}}],["two",{"_index":877,"title":{},"content":{"22":{"position":[[23,3]]},"24":{"position":[[11,3]]},"28":{"position":[[2495,3]]},"34":{"position":[[160,3]]},"38":{"position":[[428,3]]},"40":{"position":[[997,3]]},"43":{"position":[[698,3]]},"49":{"position":[[517,4]]},"68":{"position":[[871,3]]},"69":{"position":[[45,3]]},"71":{"position":[[103,3]]},"72":{"position":[[112,3],[174,3],[518,3]]},"74":{"position":[[368,3]]},"75":{"position":[[254,3]]},"78":{"position":[[21,3]]},"82":{"position":[[143,3]]},"83":{"position":[[125,3]]},"86":{"position":[[36,3]]},"88":{"position":[[16,3],[2035,3],[2058,3]]},"89":{"position":[[17,3]]},"91":{"position":[[4676,3]]},"93":{"position":[[4571,3]]},"97":{"position":[[2392,3],[5606,3],[5835,3]]},"98":{"position":[[280,3],[514,3]]},"101":{"position":[[307,3]]},"105":{"position":[[595,3]]},"106":{"position":[[577,3]]},"113":{"position":[[2032,3]]},"116":{"position":[[2657,3]]},"117":{"position":[[104,3]]},"121":{"position":[[2094,3]]},"122":{"position":[[1230,3]]},"123":{"position":[[382,3]]},"125":{"position":[[2237,3],[7970,3],[8030,3],[8200,3],[9538,3]]},"127":{"position":[[336,3]]},"135":{"position":[[506,3]]},"161":{"position":[[539,3],[923,3]]},"164":{"position":[[816,3]]},"175":{"position":[[1303,3]]},"176":{"position":[[733,3]]},"188":{"position":[[321,3],[2038,3],[3333,3]]},"189":{"position":[[1995,3]]},"193":{"position":[[3480,3]]},"197":{"position":[[24,3]]},"199":{"position":[[83,3]]}},"keywords":{}}],["twoexampl",{"_index":4161,"title":{},"content":{"125":{"position":[[8313,11]]}},"keywords":{}}],["twofiftysix",{"_index":4547,"title":{},"content":{"153":{"position":[[534,11],[603,13]]},"195":{"position":[[216,11],[300,13]]}},"keywords":{}}],["twofiftysixk",{"_index":4551,"title":{},"content":{"153":{"position":[[649,12],[722,14]]},"195":{"position":[[363,12],[614,14]]}},"keywords":{}}],["type",{"_index":131,"title":{"91":{"position":[[6,4]]},"92":{"position":[[6,4]]},"198":{"position":[[5,6]]}},"content":{"2":{"position":[[869,5]]},"3":{"position":[[1385,5]]},"20":{"position":[[2032,7],[2071,7],[2118,7],[2161,7]]},"24":{"position":[[15,5]]},"91":{"position":[[11,4]]},"96":{"position":[[1307,4]]},"97":{"position":[[4133,4],[6455,4]]},"111":{"position":[[642,5]]},"116":{"position":[[9,4],[2550,5],[2982,4]]},"117":{"position":[[456,4],[644,4]]},"121":{"position":[[2716,7]]},"122":{"position":[[331,6]]},"125":{"position":[[4335,5],[4503,4],[4597,5],[4719,5]]},"127":{"position":[[187,5],[1021,5],[1399,4]]},"129":{"position":[[130,6]]},"130":{"position":[[456,4]]},"140":{"position":[[90,4]]},"141":{"position":[[356,4]]},"145":{"position":[[379,5]]},"153":{"position":[[156,4]]},"155":{"position":[[59,6],[207,6],[1237,5]]},"156":{"position":[[12,5],[324,5],[1784,5]]},"159":{"position":[[385,5],[719,5]]},"160":{"position":[[297,4]]},"163":{"position":[[986,4]]},"165":{"position":[[826,6]]},"166":{"position":[[555,5],[691,6]]},"170":{"position":[[108,4]]},"172":{"position":[[1481,5]]},"184":{"position":[[857,5]]},"185":{"position":[[53,5]]},"189":{"position":[[400,5],[983,4]]},"190":{"position":[[370,5]]},"194":{"position":[[43,5],[185,5]]},"195":{"position":[[11,4]]},"197":{"position":[[897,4]]},"198":{"position":[[249,4],[808,5],[863,5],[1095,4]]},"199":{"position":[[1618,5]]}},"keywords":{}}],["typecan",{"_index":5361,"title":{},"content":{"198":{"position":[[712,7]]}},"keywords":{}}],["typecopi",{"_index":5305,"title":{},"content":{"193":{"position":[[2984,9]]}},"keywords":{}}],["typedread",{"_index":3815,"title":{"117":{"position":[[15,12]]}},"content":{"117":{"position":[[5,11],[314,11]]}},"keywords":{}}],["typedreaderi",{"_index":3819,"title":{},"content":{"117":{"position":[[474,13]]}},"keywords":{}}],["typeerror",{"_index":4096,"title":{},"content":{"125":{"position":[[4386,10]]}},"keywords":{}}],["typeiteratori",{"_index":5378,"title":{},"content":{"199":{"position":[[518,14]]}},"keywords":{}}],["types(lik",{"_index":4567,"title":{},"content":{"155":{"position":[[779,10]]}},"keywords":{}}],["typescript",{"_index":9,"title":{},"content":{"1":{"position":[[58,11],[272,11]]},"2":{"position":[[278,10]]},"3":{"position":[[149,10]]},"125":{"position":[[5363,10],[5911,10]]}},"keywords":{}}],["typescript/javascript",{"_index":36,"title":{},"content":{"1":{"position":[[398,21]]}},"keywords":{}}],["typescriptthan",{"_index":4196,"title":{},"content":{"125":{"position":[[10248,14]]}},"keywords":{}}],["typic",{"_index":1477,"title":{},"content":{"30":{"position":[[9251,9]]},"74":{"position":[[1169,9]]},"93":{"position":[[645,9]]},"104":{"position":[[1730,9],[1801,9]]},"111":{"position":[[141,9]]},"135":{"position":[[134,9]]},"157":{"position":[[284,9]]},"160":{"position":[[1761,9]]},"161":{"position":[[1099,9]]},"173":{"position":[[277,9]]},"174":{"position":[[1244,9]]},"176":{"position":[[552,9]]},"179":{"position":[[216,9]]},"182":{"position":[[324,7]]},"195":{"position":[[428,9]]},"196":{"position":[[63,9]]}},"keywords":{}}],["typo",{"_index":3882,"title":{},"content":{"121":{"position":[[594,6],[820,6]]}},"keywords":{}}],["tz",{"_index":3959,"title":{},"content":{"122":{"position":[[1261,2]]}},"keywords":{}}],["u.",{"_index":1443,"title":{},"content":{"30":{"position":[[8078,5]]}},"keywords":{}}],["u.get_int",{"_index":5349,"title":{},"content":{"197":{"position":[[1132,12]]}},"keywords":{}}],["u32",{"_index":4292,"title":{},"content":{"129":{"position":[[967,3],[1445,3]]},"152":{"position":[[480,4]]},"165":{"position":[[1229,3]]},"180":{"position":[[441,4],[452,3]]},"181":{"position":[[86,3],[121,4],[132,3],[243,4],[254,3]]},"183":{"position":[[311,3],[346,4],[357,3],[492,4],[503,3]]},"184":{"position":[[169,3],[301,3],[528,3]]},"185":{"position":[[674,4]]}},"keywords":{}}],["u32>",{"_index":5386,"title":{},"content":{"199":{"position":[[1562,8]]}},"keywords":{}}],["u64",{"_index":4549,"title":{},"content":{"153":{"position":[[552,5]]},"192":{"position":[[133,4],[141,4]]},"195":{"position":[[234,5]]},"197":{"position":[[336,4],[465,3],[481,3],[552,3],[614,3]]}},"keywords":{}}],["u8",{"_index":3773,"title":{},"content":{"115":{"position":[[965,3],[1197,3]]},"116":{"position":[[964,3],[1149,3],[2688,3]]},"152":{"position":[[1367,2],[1517,3]]},"156":{"position":[[1450,2],[1600,3]]},"163":{"position":[[1701,4]]},"197":{"position":[[405,2]]}},"keywords":{}}],["ubuntu",{"_index":3666,"title":{},"content":{"108":{"position":[[418,7]]}},"keywords":{}}],["udp",{"_index":5020,"title":{},"content":{"175":{"position":[[910,3]]}},"keywords":{}}],["ulimit",{"_index":5322,"title":{},"content":{"195":{"position":[[563,7]]}},"keywords":{}}],["ultim",{"_index":2940,"title":{},"content":{"88":{"position":[[3649,10]]},"95":{"position":[[261,10]]},"97":{"position":[[2447,10]]},"121":{"position":[[2577,10]]},"124":{"position":[[123,11]]},"125":{"position":[[3868,10]]},"163":{"position":[[2249,11]]},"165":{"position":[[1382,11]]}},"keywords":{}}],["ultimatelygot",{"_index":4063,"title":{},"content":{"125":{"position":[[2401,13]]}},"keywords":{}}],["umbrella",{"_index":4592,"title":{},"content":{"156":{"position":[[351,8]]}},"keywords":{}}],["un",{"_index":2611,"title":{},"content":{"71":{"position":[[1430,2]]}},"keywords":{}}],["un/satisfi",{"_index":1934,"title":{},"content":{"44":{"position":[[1305,12]]}},"keywords":{}}],["unabl",{"_index":4162,"title":{},"content":{"125":{"position":[[8354,6],[8915,6]]},"133":{"position":[[98,6]]},"181":{"position":[[780,6]]}},"keywords":{}}],["unaccept",{"_index":4428,"title":{},"content":{"139":{"position":[[695,12]]}},"keywords":{}}],["unawar",{"_index":4055,"title":{},"content":{"125":{"position":[[1901,7]]}},"keywords":{}}],["unblock",{"_index":5158,"title":{},"content":{"188":{"position":[[686,9]]}},"keywords":{}}],["unbound",{"_index":4295,"title":{},"content":{"129":{"position":[[1290,7],[1867,7]]}},"keywords":{}}],["uncc",{"_index":2210,"title":{},"content":{"53":{"position":[[415,5]]}},"keywords":{}}],["unchang",{"_index":5056,"title":{},"content":{"178":{"position":[[34,10]]}},"keywords":{}}],["uncommon",{"_index":2811,"title":{},"content":{"83":{"position":[[233,8]]}},"keywords":{}}],["uncompress",{"_index":3463,"title":{},"content":{"101":{"position":[[18,12],[474,10]]},"105":{"position":[[2633,12]]}},"keywords":{}}],["under",{"_index":3546,"title":{},"content":{"103":{"position":[[2290,5]]},"125":{"position":[[6734,5]]},"127":{"position":[[895,5]]},"156":{"position":[[340,5]]}},"keywords":{}}],["undergradu",{"_index":2202,"title":{},"content":{"53":{"position":[[288,13]]}},"keywords":{}}],["underli",{"_index":303,"title":{"6":{"position":[[0,10]]},"11":{"position":[[9,10]]}},"content":{"6":{"position":[[67,10]]},"7":{"position":[[211,10]]},"13":{"position":[[28,10],[167,10],[249,10]]},"14":{"position":[[183,10],[322,10],[392,10]]},"15":{"position":[[236,10],[360,10],[421,10]]},"82":{"position":[[1264,10]]},"97":{"position":[[5756,10]]},"117":{"position":[[177,10],[678,10]]}},"keywords":{}}],["understand",{"_index":137,"title":{},"content":{"3":{"position":[[52,10]]},"4":{"position":[[558,13]]},"41":{"position":[[88,11]]},"69":{"position":[[15,10]]},"90":{"position":[[150,10]]},"97":{"position":[[2603,10]]},"98":{"position":[[767,10]]},"104":{"position":[[17,10],[1661,10]]},"112":{"position":[[386,10]]},"113":{"position":[[1144,10],[1958,11]]},"128":{"position":[[53,13]]},"137":{"position":[[123,10]]},"160":{"position":[[463,10],[971,11],[3220,13]]},"170":{"position":[[459,10]]},"172":{"position":[[919,13],[1143,10],[1674,13]]},"173":{"position":[[1335,13]]},"182":{"position":[[370,10]]},"193":{"position":[[1008,13]]},"198":{"position":[[1,13]]}},"keywords":{}}],["understood",{"_index":42,"title":{},"content":{"1":{"position":[[493,10]]}},"keywords":{}}],["unfair",{"_index":2552,"title":{"67":{"position":[[4,6]]}},"content":{"72":{"position":[[522,6]]}},"keywords":{}}],["unfair_die(d1",{"_index":2600,"title":{},"content":{"70":{"position":[[1112,14]]},"71":{"position":[[1263,14]]}},"keywords":{}}],["unfair_die(d1_dist",{"_index":2751,"title":{},"content":{"78":{"position":[[169,19]]}},"keywords":{}}],["unfair_die(d2",{"_index":2602,"title":{},"content":{"70":{"position":[[1139,14]]},"71":{"position":[[1290,14]]}},"keywords":{}}],["unfair_die(d2_dist",{"_index":2753,"title":{},"content":{"78":{"position":[[202,19]]}},"keywords":{}}],["unfair_die(p_v",{"_index":2593,"title":{},"content":{"70":{"position":[[938,18]]}},"keywords":{}}],["unfamiliar",{"_index":14,"title":{},"content":{"1":{"position":[[133,10]]}},"keywords":{}}],["unfortun",{"_index":1886,"title":{},"content":{"43":{"position":[[1090,13]]},"97":{"position":[[947,11]]},"194":{"position":[[714,13]]}},"keywords":{}}],["unicast",{"_index":5021,"title":{},"content":{"175":{"position":[[914,8]]}},"keywords":{}}],["union",{"_index":4843,"title":{},"content":{"166":{"position":[[405,7],[549,5],[685,5]]},"194":{"position":[[179,5],[666,6]]}},"keywords":{}}],["uniqu",{"_index":211,"title":{"183":{"position":[[7,11]]}},"content":{"3":{"position":[[1452,6]]},"51":{"position":[[885,6],[2654,6]]},"127":{"position":[[340,6]]},"159":{"position":[[548,7]]},"181":{"position":[[717,6],[798,6]]},"182":{"position":[[126,6],[447,6]]},"183":{"position":[[89,11],[194,7]]},"185":{"position":[[115,7]]}},"keywords":{}}],["unique_hashtag",{"_index":2125,"title":{},"content":{"51":{"position":[[2333,15],[2444,16],[2511,18]]}},"keywords":{}}],["unique_word",{"_index":2098,"title":{},"content":{"51":{"position":[[1164,12],[1250,14],[2372,12]]}},"keywords":{}}],["unit",{"_index":366,"title":{},"content":{"6":{"position":[[990,4]]}},"keywords":{}}],["unix",{"_index":4955,"title":{},"content":{"173":{"position":[[970,4]]}},"keywords":{}}],["unknown",{"_index":4069,"title":{},"content":{"125":{"position":[[2721,7],[2729,7],[5241,7],[5249,7],[5789,7],[5797,7],[10056,8],[10397,7]]},"141":{"position":[[140,7]]},"155":{"position":[[157,7]]}},"keywords":{}}],["unless",{"_index":1672,"title":{},"content":{"35":{"position":[[373,7]]},"65":{"position":[[1429,7]]},"97":{"position":[[5535,6]]},"189":{"position":[[380,6]]}},"keywords":{}}],["unlik",{"_index":1809,"title":{},"content":{"40":{"position":[[1346,6]]},"160":{"position":[[997,6]]},"165":{"position":[[385,6]]},"189":{"position":[[2866,6]]}},"keywords":{}}],["unlock",{"_index":5156,"title":{},"content":{"188":{"position":[[548,7],[3395,6],[3506,7],[4465,9],[4502,6]]},"189":{"position":[[644,7],[2303,9],[2892,6]]},"190":{"position":[[827,9]]}},"keywords":{}}],["unmaintain",{"_index":4847,"title":{},"content":{"166":{"position":[[644,13]]}},"keywords":{}}],["unmodifi",{"_index":4364,"title":{},"content":{"133":{"position":[[124,10]]}},"keywords":{}}],["unnecessari",{"_index":263,"title":{},"content":{"4":{"position":[[833,11],[1016,11]]},"141":{"position":[[203,11]]},"153":{"position":[[426,11]]}},"keywords":{}}],["unpack",{"_index":4814,"title":{},"content":{"164":{"position":[[975,6],[1076,7],[1152,8]]},"168":{"position":[[252,8]]},"169":{"position":[[366,8]]}},"keywords":{}}],["unpredict",{"_index":1123,"title":{},"content":{"24":{"position":[[3044,14]]}},"keywords":{}}],["unrel",{"_index":5107,"title":{},"content":{"182":{"position":[[187,10]]}},"keywords":{}}],["unsaf",{"_index":3359,"title":{},"content":{"97":{"position":[[114,6]]},"115":{"position":[[2806,6]]},"152":{"position":[[937,6],[1268,6],[1313,6],[1478,6]]},"156":{"position":[[1351,6],[1396,6],[1561,6]]},"160":{"position":[[3449,6]]},"186":{"position":[[70,6]]},"188":{"position":[[495,6]]}},"keywords":{}}],["unsafenev",{"_index":4679,"title":{},"content":{"160":{"position":[[1627,11]]}},"keywords":{}}],["unsat",{"_index":1935,"title":{},"content":{"44":{"position":[[1330,5],[1441,6],[1448,7]]}},"keywords":{}}],["unsatisfi",{"_index":1879,"title":{},"content":{"43":{"position":[[734,11]]},"44":{"position":[[1393,11],[1596,11]]}},"keywords":{}}],["unsign",{"_index":5162,"title":{},"content":{"188":{"position":[[975,8],[1051,8]]}},"keywords":{}}],["unstabl",{"_index":4153,"title":{},"content":{"125":{"position":[[7943,8]]}},"keywords":{}}],["unsuccessfulli",{"_index":101,"title":{},"content":{"2":{"position":[[386,16]]}},"keywords":{}}],["until",{"_index":48,"title":{},"content":{"1":{"position":[[553,5]]},"13":{"position":[[414,5]]},"14":{"position":[[467,5],[1311,5]]},"38":{"position":[[716,5]]},"40":{"position":[[356,5],[1890,5],[2213,5],[2833,5]]},"52":{"position":[[643,5]]},"65":{"position":[[2159,5],[2515,5]]},"75":{"position":[[295,5]]},"93":{"position":[[1165,5]]},"120":{"position":[[558,5]]},"160":{"position":[[2944,5]]},"188":{"position":[[3241,5]]},"190":{"position":[[796,5]]}},"keywords":{}}],["untyp",{"_index":3824,"title":{},"content":{"117":{"position":[[778,7]]}},"keywords":{}}],["unus",{"_index":4698,"title":{},"content":{"160":{"position":[[2594,8]]}},"keywords":{}}],["unwrap",{"_index":3760,"title":{},"content":{"113":{"position":[[1894,11]]},"115":{"position":[[349,11]]},"116":{"position":[[449,11]]},"117":{"position":[[1238,11]]},"147":{"position":[[558,8]]}},"keywords":{}}],["up",{"_index":145,"title":{"92":{"position":[[23,2]]},"111":{"position":[[16,2]]},"143":{"position":[[15,3]]}},"content":{"3":{"position":[[281,2],[1042,3]]},"4":{"position":[[9,2]]},"6":{"position":[[109,2]]},"9":{"position":[[41,3]]},"11":{"position":[[41,3]]},"13":{"position":[[411,2]]},"14":{"position":[[464,2]]},"15":{"position":[[576,2],[669,2]]},"22":{"position":[[2839,2]]},"24":{"position":[[1025,2]]},"25":{"position":[[745,2]]},"28":{"position":[[77,2],[171,2]]},"30":{"position":[[971,3]]},"32":{"position":[[298,3],[1158,2],[1285,2]]},"33":{"position":[[854,2],[916,2],[943,2],[1159,2]]},"34":{"position":[[3145,2],[3665,2],[3915,2]]},"38":{"position":[[201,2],[391,3]]},"39":{"position":[[112,2]]},"40":{"position":[[706,2],[1590,2],[2373,3]]},"43":{"position":[[7,3]]},"44":{"position":[[1153,2]]},"45":{"position":[[957,2],[2647,2]]},"49":{"position":[[38,2]]},"52":{"position":[[668,2]]},"53":{"position":[[74,2],[1141,2],[1332,2],[1633,2],[2086,3]]},"54":{"position":[[280,2]]},"57":{"position":[[480,2]]},"58":{"position":[[603,3],[647,2]]},"61":{"position":[[1450,2]]},"62":{"position":[[29,2]]},"65":{"position":[[124,2]]},"66":{"position":[[428,2],[690,3]]},"69":{"position":[[131,3]]},"73":{"position":[[440,2]]},"76":{"position":[[1462,3]]},"83":{"position":[[62,2]]},"88":{"position":[[2767,2],[3179,2]]},"89":{"position":[[711,3]]},"90":{"position":[[4286,2]]},"91":{"position":[[3260,2],[5829,3]]},"92":{"position":[[218,3],[1072,2],[1585,2]]},"93":{"position":[[2309,2],[4563,2]]},"95":{"position":[[529,2]]},"96":{"position":[[955,2],[1838,2]]},"97":{"position":[[1367,2],[1650,2],[2587,2],[3796,2]]},"98":{"position":[[73,2]]},"100":{"position":[[366,2]]},"101":{"position":[[271,2],[1041,2]]},"103":{"position":[[1538,3],[1658,2]]},"104":{"position":[[1945,2]]},"106":{"position":[[291,2],[765,2]]},"109":{"position":[[31,3],[482,3]]},"111":{"position":[[31,2],[508,2]]},"112":{"position":[[1272,2]]},"113":{"position":[[52,3],[1299,2],[1568,2],[2522,2]]},"116":{"position":[[921,3],[3112,2]]},"118":{"position":[[278,2]]},"120":{"position":[[361,2]]},"121":{"position":[[637,2],[1025,2],[2060,2]]},"122":{"position":[[1461,2]]},"124":{"position":[[484,2]]},"125":{"position":[[1028,3],[9542,2],[10433,2],[11568,2]]},"128":{"position":[[571,2]]},"134":{"position":[[125,2],[329,2]]},"153":{"position":[[456,2],[782,2]]},"160":{"position":[[379,2]]},"172":{"position":[[2453,2]]},"174":{"position":[[1066,2]]},"178":{"position":[[461,2]]},"190":{"position":[[72,2]]},"192":{"position":[[341,2]]},"196":{"position":[[1445,2]]},"197":{"position":[[783,2],[1076,2]]}},"keywords":{}}],["up?i",{"_index":2954,"title":{},"content":{"89":{"position":[[743,5]]}},"keywords":{}}],["upcom",{"_index":4710,"title":{},"content":{"160":{"position":[[3854,8]]}},"keywords":{}}],["updat",{"_index":384,"title":{},"content":{"7":{"position":[[145,6]]},"123":{"position":[[196,7]]},"125":{"position":[[2415,8],[8069,8],[11061,8]]}},"keywords":{}}],["upon",{"_index":2325,"title":{},"content":{"58":{"position":[[180,4]]}},"keywords":{}}],["upper",{"_index":810,"title":{},"content":{"20":{"position":[[1197,5]]},"45":{"position":[[1699,5]]}},"keywords":{}}],["upstream",{"_index":4061,"title":{},"content":{"125":{"position":[[2335,8]]}},"keywords":{}}],["uptick",{"_index":1811,"title":{},"content":{"40":{"position":[[1415,6]]}},"keywords":{}}],["uptrend",{"_index":3177,"title":{},"content":{"92":{"position":[[55,8],[306,7]]}},"keywords":{}}],["upward",{"_index":1692,"title":{},"content":{"38":{"position":[[475,6]]}},"keywords":{}}],["url",{"_index":968,"title":{},"content":{"22":{"position":[[2422,4],[2585,5],[2953,3]]},"30":{"position":[[8869,3],[8963,3]]},"61":{"position":[[1457,3],[1875,4],[1910,3],[2197,3]]},"62":{"position":[[678,3]]},"96":{"position":[[373,4],[998,3],[1196,4],[1496,4],[1734,4],[2280,4]]},"125":{"position":[[4683,3]]}},"keywords":{}}],["url'",{"_index":882,"title":{},"content":{"22":{"position":[[73,5]]}},"keywords":{}}],["url(<loc",{"_index":121,"title":{},"content":{"2":{"position":[[716,13]]}},"keywords":{}}],["urllib",{"_index":2372,"title":{},"content":{"61":{"position":[[1507,6]]}},"keywords":{}}],["urllib.parse.urlencode(param",{"_index":2383,"title":{},"content":{"61":{"position":[[1800,30]]}},"keywords":{}}],["us",{"_index":86,"title":{"37":{"position":[[14,5]]},"122":{"position":[[0,5]]},"144":{"position":[[0,5]]},"145":{"position":[[0,5]]},"146":{"position":[[0,5]]}},"content":{"2":{"position":[[166,3],[522,5],[708,3]]},"3":{"position":[[108,3],[744,5],[1312,4]]},"4":{"position":[[12,5]]},"6":{"position":[[206,3],[971,5]]},"7":{"position":[[222,4],[715,4],[1036,3]]},"8":{"position":[[104,5],[136,3]]},"10":{"position":[[334,4]]},"11":{"position":[[218,3]]},"12":{"position":[[66,3],[167,3]]},"14":{"position":[[1188,3]]},"19":{"position":[[48,3]]},"20":{"position":[[1114,3]]},"25":{"position":[[98,3]]},"30":{"position":[[779,3],[944,4],[8164,4],[8252,3],[8298,4],[9499,3],[9515,3]]},"32":{"position":[[443,3]]},"33":{"position":[[430,3]]},"34":{"position":[[1011,5]]},"43":{"position":[[92,5]]},"45":{"position":[[675,3],[1226,3],[1469,5],[1645,5],[2766,5]]},"46":{"position":[[279,4]]},"47":{"position":[[6,4]]},"49":{"position":[[270,3],[503,3]]},"50":{"position":[[5,5],[53,3],[98,3],[201,5]]},"51":{"position":[[9,5],[2250,5],[2574,4],[2646,5]]},"53":{"position":[[1817,3]]},"58":{"position":[[375,5],[841,6]]},"61":{"position":[[277,3],[787,3],[1350,5]]},"62":{"position":[[118,5],[298,5]]},"63":{"position":[[65,5]]},"64":{"position":[[76,4],[1130,4],[1271,3],[1423,6]]},"65":{"position":[[60,4],[302,3],[2195,5]]},"73":{"position":[[265,5]]},"76":{"position":[[600,3]]},"78":{"position":[[15,5]]},"79":{"position":[[16,4]]},"80":{"position":[[21,3]]},"85":{"position":[[13,3]]},"86":{"position":[[79,4],[178,3],[377,3],[751,4],[1179,5]]},"88":{"position":[[979,4]]},"90":{"position":[[3226,3],[3393,5]]},"91":{"position":[[240,3],[1623,3],[1798,5]]},"93":{"position":[[2929,3]]},"95":{"position":[[10,5]]},"97":{"position":[[110,3],[1072,5],[2751,4],[3090,3],[4760,3],[5345,3],[6503,3]]},"98":{"position":[[551,4],[782,3],[851,6],[941,3],[1118,3],[1152,5]]},"101":{"position":[[799,5]]},"102":{"position":[[120,4],[574,5],[1234,3],[1277,5],[1309,3]]},"103":{"position":[[21,5],[126,5],[744,5],[1593,3]]},"104":{"position":[[166,5],[1432,5]]},"105":{"position":[[38,5],[122,5],[276,3],[311,3]]},"106":{"position":[[45,5],[622,4],[1011,4]]},"108":{"position":[[116,4],[472,3],[585,5]]},"111":{"position":[[126,6],[638,3]]},"113":{"position":[[303,3]]},"115":{"position":[[456,5],[637,3]]},"116":{"position":[[2533,4],[2922,5]]},"117":{"position":[[326,5],[1654,3],[2001,3]]},"120":{"position":[[232,6],[407,7]]},"121":{"position":[[484,5],[840,3],[1685,4],[1911,3],[2074,5]]},"122":{"position":[[297,3],[423,4]]},"125":{"position":[[1190,3],[2387,4],[2705,4],[2813,3],[3961,5],[5047,5],[5134,3],[5397,3],[6248,4],[6511,4],[6723,4],[7765,4],[8333,5],[10557,3]]},"127":{"position":[[16,5],[992,5]]},"128":{"position":[[862,3],[970,5]]},"133":{"position":[[173,3],[262,3]]},"135":{"position":[[144,4],[228,4]]},"136":{"position":[[246,5],[711,5],[861,3]]},"137":{"position":[[163,3]]},"139":{"position":[[220,5]]},"140":{"position":[[213,6]]},"144":{"position":[[73,3],[95,3]]},"145":{"position":[[42,3],[71,3]]},"146":{"position":[[42,3],[71,3],[99,3]]},"147":{"position":[[123,3],[152,3]]},"148":{"position":[[128,3]]},"152":{"position":[[372,3],[419,3]]},"155":{"position":[[194,3],[372,3],[1243,3],[1280,3],[1297,3],[1317,3]]},"156":{"position":[[18,3],[822,3],[869,3]]},"157":{"position":[[675,4]]},"159":{"position":[[589,5],[1240,3]]},"160":{"position":[[286,3],[488,5],[1092,4],[1251,3],[1623,3],[1639,3],[1718,3],[1747,4],[2873,4],[2996,4],[3060,5],[3465,3],[3750,5],[4185,5]]},"161":{"position":[[830,4]]},"163":{"position":[[423,5]]},"164":{"position":[[262,5],[312,4],[450,5],[581,3],[1013,3],[1566,5]]},"165":{"position":[[341,5],[1404,5]]},"166":{"position":[[354,3],[762,6]]},"172":{"position":[[914,4],[1894,5],[1944,5],[2563,6]]},"174":{"position":[[779,5]]},"175":{"position":[[904,5],[1120,5]]},"176":{"position":[[188,5],[395,4],[667,3],[1112,5]]},"179":{"position":[[111,5],[363,3],[833,3],[1211,5],[1224,3],[1333,4]]},"180":{"position":[[343,3],[581,4]]},"181":{"position":[[834,5]]},"182":{"position":[[675,5]]},"183":{"position":[[441,4],[587,4]]},"184":{"position":[[436,5],[810,3],[998,3]]},"185":{"position":[[629,3]]},"186":{"position":[[128,3],[182,3]]},"188":{"position":[[414,3],[4227,4],[4373,3]]},"189":{"position":[[357,4],[939,5],[1217,5]]},"190":{"position":[[99,4],[253,6],[497,3]]},"192":{"position":[[73,3],[635,4]]},"193":{"position":[[308,5],[881,5],[945,3],[1253,4],[1711,4],[2032,5],[2084,5],[3130,3]]},"194":{"position":[[125,3],[197,3],[575,4]]},"195":{"position":[[133,4],[557,5]]},"196":{"position":[[1073,3]]},"197":{"position":[[249,4],[670,3],[818,4],[1514,4]]},"199":{"position":[[361,4],[962,3],[1046,3],[1068,3]]}},"keywords":{}}],["usabl",{"_index":4083,"title":{},"content":{"125":{"position":[[3498,9]]},"148":{"position":[[222,6]]}},"keywords":{}}],["usag",{"_index":3765,"title":{"114":{"position":[[30,5]]}},"content":{"115":{"position":[[593,6]]},"132":{"position":[[200,5],[757,6],[1045,6]]},"135":{"position":[[29,6]]},"148":{"position":[[78,5]]},"160":{"position":[[990,6],[2787,5]]}},"keywords":{}}],["usedstd::mem::transmut",{"_index":4809,"title":{},"content":{"164":{"position":[[676,23]]}},"keywords":{}}],["usedthi",{"_index":4853,"title":{},"content":{"167":{"position":[[93,8]]}},"keywords":{}}],["useful.stat",{"_index":4631,"title":{},"content":{"159":{"position":[[478,13]]}},"keywords":{}}],["useinterior",{"_index":5066,"title":{},"content":{"179":{"position":[[242,11]]}},"keywords":{}}],["useless",{"_index":2542,"title":{},"content":{"66":{"position":[[97,7]]}},"keywords":{}}],["useno_hz",{"_index":4952,"title":{},"content":{"173":{"position":[[835,8]]}},"keywords":{}}],["usenumactl",{"_index":4971,"title":{},"content":{"173":{"position":[[2163,10]]}},"keywords":{}}],["user",{"_index":274,"title":{},"content":{"4":{"position":[[1005,5],[1171,5],[1491,5]]},"22":{"position":[[841,4]]},"44":{"position":[[436,5]]},"61":{"position":[[254,4],[487,4],[542,5],[607,5],[1127,4],[1465,4]]},"93":{"position":[[2447,6]]},"97":{"position":[[358,5]]},"108":{"position":[[348,5],[462,5],[541,5]]},"125":{"position":[[978,4]]},"188":{"position":[[1585,4],[1683,4],[2252,4],[2569,4],[2636,4],[3107,4]]},"189":{"position":[[1773,4],[2228,4],[2511,4],[2800,4]]}},"keywords":{}}],["user'",{"_index":1611,"title":{},"content":{"34":{"position":[[1200,6]]},"61":{"position":[[774,6],[965,6],[1010,6],[1082,6]]}},"keywords":{}}],["user_ag",{"_index":3221,"title":{},"content":{"93":{"position":[[2344,10],[2462,11]]}},"keywords":{}}],["usesdynam",{"_index":4675,"title":{},"content":{"160":{"position":[[1338,11]]}},"keywords":{}}],["usesit",{"_index":4362,"title":{},"content":{"133":{"position":[[52,7]]}},"keywords":{}}],["usetempl",{"_index":4936,"title":{},"content":{"172":{"position":[[2618,12]]}},"keywords":{}}],["usfederalholidaycalendar",{"_index":2964,"title":{},"content":{"90":{"position":[[250,24],[538,26]]}},"keywords":{}}],["usinghyp",{"_index":3392,"title":{},"content":{"97":{"position":[[2294,10]]}},"keywords":{}}],["usingresearch",{"_index":5007,"title":{},"content":{"175":{"position":[[404,13]]}},"keywords":{}}],["usingtaskset",{"_index":4951,"title":{},"content":{"173":{"position":[[812,13]]}},"keywords":{}}],["v",{"_index":4430,"title":{},"content":{"140":{"position":[[24,2],[158,1]]},"141":{"position":[[24,2]]},"144":{"position":[[296,1]]},"145":{"position":[[154,1]]},"146":{"position":[[237,1]]}},"keywords":{}}],["v.capac",{"_index":4453,"title":{},"content":{"144":{"position":[[254,12]]}},"keywords":{}}],["v.len",{"_index":4452,"title":{},"content":{"144":{"position":[[243,7]]}},"keywords":{}}],["v.pop().unwrap",{"_index":4463,"title":{},"content":{"145":{"position":[[429,17]]}},"keywords":{}}],["v.push(0",{"_index":4467,"title":{},"content":{"146":{"position":[[350,10]]}},"keywords":{}}],["v.push(1",{"_index":4469,"title":{},"content":{"146":{"position":[[494,10]]}},"keywords":{}}],["v.push(5",{"_index":4440,"title":{},"content":{"142":{"position":[[36,10]]},"144":{"position":[[267,10]]}},"keywords":{}}],["val",{"_index":2150,"title":{},"content":{"51":{"position":[[3626,5],[3710,4]]},"88":{"position":[[1094,4],[1183,5]]},"199":{"position":[[145,5],[309,5],[390,5]]}},"keywords":{}}],["valid",{"_index":480,"title":{},"content":{"10":{"position":[[46,8]]},"97":{"position":[[524,6]]},"130":{"position":[[495,5]]},"167":{"position":[[253,9]]},"175":{"position":[[1193,8]]}},"keywords":{}}],["vals.length",{"_index":5372,"title":{},"content":{"199":{"position":[[210,12]]}},"keywords":{}}],["vals[i",{"_index":5373,"title":{},"content":{"199":{"position":[[237,8]]}},"keywords":{}}],["valu",{"_index":449,"title":{"178":{"position":[[6,7]]},"182":{"position":[[7,7]]}},"content":{"8":{"position":[[151,6]]},"13":{"position":[[1851,5],[2253,5]]},"14":{"position":[[787,5],[1124,5],[2934,5],[3325,5]]},"15":{"position":[[655,5],[2608,5],[2996,5]]},"28":{"position":[[1592,7],[3378,7]]},"30":{"position":[[7141,5],[7185,5],[7267,5],[7334,6]]},"40":{"position":[[2268,6]]},"41":{"position":[[534,6]]},"44":{"position":[[118,7],[1107,6]]},"51":{"position":[[3221,6]]},"61":{"position":[[804,5]]},"68":{"position":[[754,6]]},"69":{"position":[[317,5],[377,5]]},"70":{"position":[[1290,5]]},"71":{"position":[[1068,5],[1472,6]]},"72":{"position":[[92,5],[153,5],[302,5],[355,5]]},"74":{"position":[[402,6]]},"75":{"position":[[561,5],[645,5],[1237,5]]},"76":{"position":[[610,6],[1609,6]]},"85":{"position":[[235,5]]},"91":{"position":[[3788,6]]},"96":{"position":[[2007,6]]},"97":{"position":[[4105,5],[5767,5]]},"113":{"position":[[2045,7],[2292,6]]},"116":{"position":[[110,6]]},"120":{"position":[[1073,6]]},"127":{"position":[[196,7],[1036,6]]},"128":{"position":[[211,6],[497,5]]},"129":{"position":[[941,5],[1144,5]]},"159":{"position":[[427,6]]},"172":{"position":[[1475,5]]},"178":{"position":[[8,5],[195,5],[321,5],[435,5],[542,6],[723,6]]},"179":{"position":[[538,6],[1431,6]]},"180":{"position":[[41,6],[130,6],[319,7],[495,5]]},"181":{"position":[[63,7],[197,5],[325,5],[403,5],[525,5],[673,5],[765,8],[932,6],[1003,6]]},"183":{"position":[[446,5],[592,5],[867,5]]},"188":{"position":[[1251,5],[1279,5]]},"193":{"position":[[2962,5],[3220,6],[3469,6]]},"196":{"position":[[348,6],[914,6],[1310,6]]}},"keywords":{}}],["valuabl",{"_index":2814,"title":{},"content":{"83":{"position":[[497,8]]}},"keywords":{}}],["valueerror",{"_index":949,"title":{},"content":{"22":{"position":[[1699,11]]},"91":{"position":[[3723,11]]}},"keywords":{}}],["vanilla",{"_index":5266,"title":{},"content":{"190":{"position":[[1044,7]]},"192":{"position":[[46,7]]}},"keywords":{}}],["vari",{"_index":155,"title":{},"content":{"3":{"position":[[448,7]]}},"keywords":{}}],["variabl",{"_index":2026,"title":{},"content":{"45":{"position":[[3383,9]]},"61":{"position":[[2170,8]]},"85":{"position":[[358,9]]},"91":{"position":[[4636,11]]},"93":{"position":[[206,11]]},"97":{"position":[[4748,11]]},"108":{"position":[[767,8]]},"113":{"position":[[481,8]]},"121":{"position":[[499,8]]},"127":{"position":[[1385,8]]},"166":{"position":[[383,8],[499,8]]},"182":{"position":[[8,9],[39,10],[178,8],[292,9],[351,10],[424,9],[493,9],[581,9],[688,10]]},"183":{"position":[[113,9],[164,9]]},"184":{"position":[[81,9],[844,9]]},"185":{"position":[[44,8],[164,9]]},"186":{"position":[[27,9]]},"193":{"position":[[82,9],[167,9]]},"194":{"position":[[640,9]]},"196":{"position":[[1674,8]]}},"keywords":{}}],["varianc",{"_index":4838,"title":{},"content":{"166":{"position":[[122,8]]},"172":{"position":[[1969,8]]},"173":{"position":[[2022,8]]},"174":{"position":[[227,8],[553,8],[1050,8]]},"175":{"position":[[1250,8]]},"176":{"position":[[1282,8],[1512,8]]}},"keywords":{}}],["variant",{"_index":5318,"title":{},"content":{"194":{"position":[[596,7]]}},"keywords":{}}],["variat",{"_index":2625,"title":{},"content":{"73":{"position":[[537,9]]}},"keywords":{}}],["variou",{"_index":4844,"title":{},"content":{"166":{"position":[[417,7]]}},"keywords":{}}],["vcat(color",{"_index":434,"title":{},"content":{"7":{"position":[[1181,12]]}},"keywords":{}}],["vcat(term[1",{"_index":517,"title":{},"content":{"11":{"position":[[375,13]]},"12":{"position":[[270,13]]}},"keywords":{}}],["vcat(x_tick",{"_index":427,"title":{},"content":{"7":{"position":[[1002,13]]}},"keywords":{}}],["vec",{"_index":4431,"title":{},"content":{"140":{"position":[[86,3]]},"159":{"position":[[1062,4]]},"199":{"position":[[1609,4]]}},"keywords":{}}],["vec<u8>",{"_index":3766,"title":{},"content":{"115":{"position":[[157,14]]},"116":{"position":[[257,14]]},"117":{"position":[[1049,14]]},"140":{"position":[[27,13]]},"142":{"position":[[19,14]]},"144":{"position":[[198,14]]},"156":{"position":[[1055,13]]}},"keywords":{}}],["vec,hashmap",{"_index":4593,"title":{},"content":{"156":{"position":[[364,12]]}},"keywords":{}}],["vec::<u8>::new",{"_index":4600,"title":{},"content":{"156":{"position":[[670,23]]}},"keywords":{}}],["vec::new",{"_index":3753,"title":{},"content":{"113":{"position":[[1607,11]]},"140":{"position":[[43,11]]},"156":{"position":[[547,11],[1071,11]]}},"keywords":{}}],["vec::with_capac",{"_index":4433,"title":{},"content":{"140":{"position":[[220,19]]}},"keywords":{}}],["vec::with_capacity(1",{"_index":4454,"title":{},"content":{"144":{"position":[[300,22]]},"145":{"position":[[158,22]]},"146":{"position":[[241,22]]}},"keywords":{}}],["vector",{"_index":3831,"title":{},"content":{"117":{"position":[[1491,8]]},"140":{"position":[[160,7]]},"142":{"position":[[83,6]]},"156":{"position":[[736,6]]},"164":{"position":[[1384,6]]},"165":{"position":[[564,8],[753,6],[807,6]]},"199":{"position":[[1311,7]]}},"keywords":{}}],["vec{",{"_index":782,"title":{},"content":{"20":{"position":[[656,7]]}},"keywords":{}}],["vec{1",{"_index":781,"title":{},"content":{"20":{"position":[[629,7]]}},"keywords":{}}],["vec{d",{"_index":785,"title":{},"content":{"20":{"position":[[685,7]]}},"keywords":{}}],["vein",{"_index":4656,"title":{},"content":{"160":{"position":[[416,5]]}},"keywords":{}}],["ventur",{"_index":4100,"title":{},"content":{"125":{"position":[[4808,8]]}},"keywords":{}}],["verbatim",{"_index":3884,"title":{},"content":{"121":{"position":[[696,8]]}},"keywords":{}}],["verbos",{"_index":1027,"title":{},"content":{"24":{"position":[[522,7]]},"25":{"position":[[247,7]]}},"keywords":{}}],["veri",{"_index":625,"title":{},"content":{"14":{"position":[[56,4]]},"15":{"position":[[38,4]]},"24":{"position":[[2899,4],[3088,4],[3425,4]]},"26":{"position":[[20,4],[564,4]]},"28":{"position":[[231,4],[295,4]]},"46":{"position":[[105,4]]},"61":{"position":[[1235,4],[1957,4]]},"68":{"position":[[765,4]]},"71":{"position":[[1425,4]]},"74":{"position":[[296,4]]},"82":{"position":[[1136,4]]},"83":{"position":[[72,4],[210,4]]},"86":{"position":[[868,4]]},"88":{"position":[[2062,4]]},"92":{"position":[[1303,4],[1661,4]]},"103":{"position":[[766,4],[802,4],[2259,4],[2352,4]]},"104":{"position":[[1231,4],[1582,4]]},"105":{"position":[[90,4]]},"106":{"position":[[329,4],[447,4]]},"121":{"position":[[1632,4]]},"125":{"position":[[133,6]]},"132":{"position":[[178,4],[793,4]]},"160":{"position":[[1260,4],[1825,4]]}},"keywords":{}}],["verifi",{"_index":2836,"title":{},"content":{"86":{"position":[[1137,6]]},"121":{"position":[[1595,7]]},"139":{"position":[[279,6]]},"142":{"position":[[230,6]]},"148":{"position":[[169,6]]}},"keywords":{}}],["versa",{"_index":1568,"title":{},"content":{"33":{"position":[[208,5]]}},"keywords":{}}],["version",{"_index":159,"title":{},"content":{"3":{"position":[[496,9]]},"96":{"position":[[875,8]]},"109":{"position":[[286,7]]},"112":{"position":[[1402,8],[1454,9]]},"122":{"position":[[1211,7]]},"125":{"position":[[675,8],[709,8],[7552,7],[7607,7],[7826,7],[7974,7],[8034,7]]},"136":{"position":[[1023,7]]},"148":{"position":[[254,7],[317,7]]},"163":{"position":[[451,7]]},"164":{"position":[[904,8]]},"172":{"position":[[2165,8]]},"188":{"position":[[1745,8],[2941,7]]}},"keywords":{}}],["veteran'",{"_index":2974,"title":{},"content":{"90":{"position":[[652,9]]}},"keywords":{}}],["via",{"_index":2393,"title":{},"content":{"62":{"position":[[43,3]]},"125":{"position":[[4168,3]]}},"keywords":{}}],["viawasm",{"_index":4130,"title":{},"content":{"125":{"position":[[6159,8]]}},"keywords":{}}],["vice",{"_index":1567,"title":{},"content":{"33":{"position":[[203,4]]}},"keywords":{}}],["video",{"_index":4647,"title":{},"content":{"160":{"position":[[76,6]]}},"keywords":{}}],["video/mp2t",{"_index":132,"title":{},"content":{"2":{"position":[[875,11]]}},"keywords":{}}],["view",{"_index":1396,"title":{},"content":{"30":{"position":[[4159,4]]},"125":{"position":[[376,6],[9522,5]]}},"keywords":{}}],["villag",{"_index":2033,"title":{},"content":{"46":{"position":[[467,7]]}},"keywords":{}}],["violent",{"_index":3167,"title":{},"content":{"91":{"position":[[4898,9],[5505,8]]},"93":{"position":[[573,10]]}},"keywords":{}}],["virtual",{"_index":4983,"title":{},"content":{"174":{"position":[[424,7],[903,7]]}},"keywords":{}}],["visit",{"_index":2371,"title":{},"content":{"61":{"position":[[1476,5],[1883,5]]},"96":{"position":[[507,9]]}},"keywords":{}}],["vite",{"_index":220,"title":{},"content":{"4":{"position":[[18,4],[27,4]]}},"keywords":{}}],["vix",{"_index":341,"title":{},"content":{"6":{"position":[[571,3]]}},"keywords":{}}],["vm",{"_index":4928,"title":{},"content":{"172":{"position":[[2052,2]]}},"keywords":{}}],["voic",{"_index":3458,"title":{},"content":{"100":{"position":[[177,6]]}},"keywords":{}}],["void",{"_index":4230,"title":{},"content":{"127":{"position":[[608,4],[1258,4]]},"128":{"position":[[230,4]]}},"keywords":{}}],["volatil",{"_index":342,"title":{},"content":{"6":{"position":[[583,11]]},"38":{"position":[[316,8]]},"40":{"position":[[937,8],[1546,11],[2536,8],[3241,8],[3460,8]]},"41":{"position":[[203,8],[306,8]]},"93":{"position":[[893,8]]},"152":{"position":[[815,8],[892,8]]}},"keywords":{}}],["vs",{"_index":1749,"title":{},"content":{"39":{"position":[[2321,3]]},"40":{"position":[[1619,3]]},"198":{"position":[[397,3],[424,3]]}},"keywords":{}}],["vtabl",{"_index":5341,"title":{},"content":{"197":{"position":[[346,6],[492,6],[1195,6]]}},"keywords":{}}],["vulner",{"_index":4975,"title":{},"content":{"174":{"position":[[80,15]]}},"keywords":{}}],["w",{"_index":3258,"title":{},"content":{"93":{"position":[[3336,4]]},"105":{"position":[[1854,2],[1960,2]]}},"keywords":{}}],["w.p",{"_index":2582,"title":{},"content":{"70":{"position":[[315,4],[334,4],[353,4],[373,4],[393,4],[413,4],[489,4],[509,4],[529,4],[549,4],[569,4],[588,4]]},"71":{"position":[[415,4],[434,4],[454,4],[474,4],[494,4],[514,4],[589,4],[608,4],[628,4],[648,4],[668,4],[688,4]]}},"keywords":{}}],["wait",{"_index":3791,"title":{},"content":{"115":{"position":[[2856,4]]},"116":{"position":[[2788,4]]},"139":{"position":[[471,7],[774,7]]},"172":{"position":[[2023,7]]},"173":{"position":[[2117,4]]},"174":{"position":[[684,4]]},"175":{"position":[[1166,4]]},"188":{"position":[[2187,4]]}},"keywords":{}}],["wake",{"_index":2248,"title":{},"content":{"53":{"position":[[1134,6],[2078,7]]}},"keywords":{}}],["walk",{"_index":4988,"title":{},"content":{"174":{"position":[[702,5]]}},"keywords":{}}],["wall",{"_index":5175,"title":{},"content":{"188":{"position":[[1623,4],[1721,4],[2293,4],[2609,4],[3145,4]]},"189":{"position":[[1813,4],[2269,4],[2552,4],[2838,4]]}},"keywords":{}}],["wanew",{"_index":1211,"title":{},"content":{"28":{"position":[[399,5]]}},"keywords":{}}],["want",{"_index":725,"title":{},"content":{"18":{"position":[[10,4]]},"20":{"position":[[803,4]]},"24":{"position":[[32,4]]},"28":{"position":[[346,4],[640,4]]},"30":{"position":[[2787,4],[4461,6],[5814,4],[9589,4]]},"32":{"position":[[187,4],[611,4]]},"33":{"position":[[801,4]]},"34":{"position":[[243,4],[289,4]]},"38":{"position":[[89,4],[170,4],[673,4],[1025,4],[1283,4]]},"39":{"position":[[55,4]]},"40":{"position":[[2354,4]]},"41":{"position":[[421,4]]},"44":{"position":[[1999,4]]},"45":{"position":[[1412,4]]},"51":{"position":[[1583,4]]},"53":{"position":[[277,4],[963,4]]},"61":{"position":[[517,4],[562,4],[1217,5]]},"65":{"position":[[384,4]]},"73":{"position":[[462,4],[753,4]]},"74":{"position":[[39,4]]},"89":{"position":[[495,4],[893,4]]},"90":{"position":[[34,4],[469,4]]},"91":{"position":[[27,4],[2656,4]]},"92":{"position":[[468,4]]},"93":{"position":[[586,4],[978,4],[1984,4]]},"96":{"position":[[341,4],[1034,5],[1442,4]]},"97":{"position":[[695,4],[1106,4],[4331,4],[6495,4]]},"100":{"position":[[400,4]]},"102":{"position":[[8,4],[745,4]]},"122":{"position":[[318,4],[444,6]]},"123":{"position":[[223,4],[843,4]]},"125":{"position":[[308,4],[3043,5],[8725,4],[10362,4],[10547,6]]},"127":{"position":[[1139,5]]},"129":{"position":[[1031,4]]},"139":{"position":[[59,4],[255,4]]},"140":{"position":[[183,6]]},"143":{"position":[[162,4],[230,4],[274,4]]},"157":{"position":[[248,4]]},"165":{"position":[[706,4]]},"172":{"position":[[2420,4]]},"176":{"position":[[610,4]]},"186":{"position":[[94,4]]},"189":{"position":[[1538,4]]},"197":{"position":[[662,4]]}},"keywords":{}}],["warm",{"_index":4741,"title":{},"content":{"161":{"position":[[842,4]]}},"keywords":{}}],["warnings.catch_warn",{"_index":1252,"title":{},"content":{"28":{"position":[[1642,26],[3428,26]]}},"keywords":{}}],["warnings.simplefilter('ignor",{"_index":1253,"title":{},"content":{"28":{"position":[[1669,31],[3455,31]]}},"keywords":{}}],["wasm",{"_index":4051,"title":{},"content":{"125":{"position":[[1600,5],[3573,4],[3721,4],[3892,4],[4199,4],[4476,4],[4931,4],[5053,4],[5270,4],[5818,4],[6126,4],[6140,4],[6476,5],[6561,4],[6586,4],[6764,4],[7142,4],[7215,4],[7618,4],[7662,4],[7785,4],[7837,4],[7873,4],[8082,4],[9352,4],[10705,4]]}},"keywords":{}}],["wasm/webassembl",{"_index":4053,"title":{},"content":{"125":{"position":[[1746,16]]}},"keywords":{}}],["wasm32",{"_index":4068,"title":{},"content":{"125":{"position":[[2714,6]]}},"keywords":{}}],["wasmus",{"_index":4141,"title":{},"content":{"125":{"position":[[6552,8]]}},"keywords":{}}],["wasn't",{"_index":113,"title":{},"content":{"2":{"position":[[598,6]]},"3":{"position":[[512,6]]},"104":{"position":[[1998,6]]},"132":{"position":[[243,6]]},"147":{"position":[[392,6]]},"161":{"position":[[679,6],[835,6],[1528,6]]},"164":{"position":[[1090,6]]}},"keywords":{}}],["wast",{"_index":3499,"title":{},"content":{"102":{"position":[[1524,7]]},"127":{"position":[[1220,9]]}},"keywords":{}}],["watch",{"_index":3871,"title":{},"content":{"121":{"position":[[39,8]]},"144":{"position":[[21,5]]},"173":{"position":[[205,5]]}},"keywords":{}}],["water",{"_index":3960,"title":{},"content":{"122":{"position":[[1290,5]]},"161":{"position":[[822,5],[1166,5],[1247,5],[1310,5]]}},"keywords":{}}],["wav",{"_index":3464,"title":{},"content":{"101":{"position":[[50,5]]},"103":{"position":[[232,4],[356,3]]},"105":{"position":[[580,4]]}},"keywords":{}}],["wave",{"_index":60,"title":{},"content":{"1":{"position":[[678,4]]}},"keywords":{}}],["wavfil",{"_index":3513,"title":{},"content":{"103":{"position":[[497,7]]}},"keywords":{}}],["wavfile.read('tabulasa.wav",{"_index":3515,"title":{},"content":{"103":{"position":[[528,28]]}},"keywords":{}}],["way",{"_index":212,"title":{},"content":{"3":{"position":[[1470,3]]},"4":{"position":[[404,3]]},"7":{"position":[[1100,3]]},"26":{"position":[[892,4]]},"34":{"position":[[1375,3]]},"40":{"position":[[1001,4],[1314,3]]},"43":{"position":[[1163,3]]},"45":{"position":[[519,3]]},"51":{"position":[[3136,3]]},"53":{"position":[[1115,3]]},"55":{"position":[[62,3]]},"61":{"position":[[1032,4]]},"65":{"position":[[1264,3]]},"68":{"position":[[709,4],[774,4]]},"71":{"position":[[1440,4]]},"73":{"position":[[64,3]]},"75":{"position":[[98,3]]},"89":{"position":[[94,3],[535,5]]},"91":{"position":[[4056,3]]},"97":{"position":[[5610,4]]},"101":{"position":[[311,4]]},"102":{"position":[[244,3],[531,3],[760,3]]},"104":{"position":[[132,3]]},"108":{"position":[[781,3]]},"112":{"position":[[1343,3]]},"117":{"position":[[919,4]]},"121":{"position":[[561,3],[660,5],[1810,3],[2686,4]]},"128":{"position":[[342,3]]},"129":{"position":[[2752,3]]},"130":{"position":[[29,3],[62,3]]},"132":{"position":[[671,4]]},"136":{"position":[[1002,3]]},"143":{"position":[[518,4]]},"152":{"position":[[216,3]]},"156":{"position":[[253,4]]},"160":{"position":[[99,3]]},"161":{"position":[[403,4]]},"164":{"position":[[1118,3]]},"172":{"position":[[739,3]]},"173":{"position":[[95,4]]},"176":{"position":[[1159,3],[1564,4]]},"194":{"position":[[740,3]]}},"keywords":{}}],["wb",{"_index":1499,"title":{},"content":{"30":{"position":[[10121,6]]}},"keywords":{}}],["we'd",{"_index":413,"title":{},"content":{"7":{"position":[[720,4]]},"45":{"position":[[523,4]]},"96":{"position":[[552,4]]},"101":{"position":[[215,4]]},"136":{"position":[[659,4]]},"173":{"position":[[1251,4]]}},"keywords":{}}],["we'll",{"_index":447,"title":{},"content":{"8":{"position":[[130,5]]},"12":{"position":[[60,5]]},"28":{"position":[[564,5],[1600,5],[3386,5]]},"30":{"position":[[773,5],[2691,5],[5892,5]]},"32":{"position":[[437,5]]},"33":{"position":[[950,5]]},"34":{"position":[[3075,5],[3162,5],[3635,5]]},"45":{"position":[[1220,5],[1833,5]]},"51":{"position":[[1026,5]]},"61":{"position":[[1341,5]]},"65":{"position":[[207,5]]},"81":{"position":[[1,5]]},"82":{"position":[[126,5]]},"88":{"position":[[719,5]]},"91":{"position":[[234,5]]},"92":{"position":[[1543,5]]},"93":{"position":[[4134,5]]},"95":{"position":[[1,5]]},"103":{"position":[[711,5],[1587,5]]},"105":{"position":[[305,5],[546,5],[700,5]]},"109":{"position":[[190,5]]},"110":{"position":[[553,5]]},"111":{"position":[[106,5]]},"113":{"position":[[889,5]]},"120":{"position":[[670,5]]},"133":{"position":[[162,5]]},"155":{"position":[[366,5]]},"160":{"position":[[3406,5],[3518,5],[3842,5],[4020,5]]},"182":{"position":[[401,5]]},"188":{"position":[[736,5]]},"189":{"position":[[1639,5]]},"198":{"position":[[694,5]]}},"keywords":{}}],["we'r",{"_index":312,"title":{},"content":{"6":{"position":[[171,5],[191,5]]},"7":{"position":[[700,5]]},"9":{"position":[[111,5],[246,5]]},"10":{"position":[[60,5]]},"12":{"position":[[1,5]]},"14":{"position":[[1170,5]]},"20":{"position":[[1930,5]]},"22":{"position":[[1,5]]},"23":{"position":[[36,5]]},"30":{"position":[[1083,5],[9150,5],[9189,5]]},"32":{"position":[[5,5]]},"34":{"position":[[1138,5]]},"40":{"position":[[2312,5]]},"43":{"position":[[74,5],[710,5],[1006,5],[1230,5],[1476,5]]},"45":{"position":[[1551,5],[2545,5]]},"52":{"position":[[548,5]]},"64":{"position":[[89,5],[482,5]]},"88":{"position":[[2204,5]]},"92":{"position":[[1,5]]},"97":{"position":[[1225,5],[2421,5],[4785,5]]},"103":{"position":[[1958,5]]},"110":{"position":[[1,5],[190,5],[279,5],[378,5]]},"111":{"position":[[776,5]]},"112":{"position":[[626,5]]},"113":{"position":[[1321,5]]},"115":{"position":[[21,5],[500,5]]},"116":{"position":[[2745,5],[2912,5]]},"117":{"position":[[72,5],[757,5],[2068,5]]},"124":{"position":[[52,5]]},"125":{"position":[[2520,5],[6079,5]]},"128":{"position":[[944,5],[1307,5],[1732,5]]},"129":{"position":[[814,5]]},"135":{"position":[[36,5]]},"146":{"position":[[467,5]]},"150":{"position":[[14,5]]},"160":{"position":[[745,5]]},"163":{"position":[[2329,5]]},"179":{"position":[[448,5]]},"186":{"position":[[395,5]]},"192":{"position":[[718,5]]}},"keywords":{}}],["we'v",{"_index":454,"title":{},"content":{"9":{"position":[[10,5]]},"10":{"position":[[10,5],[98,5]]},"13":{"position":[[10,5],[899,5]]},"14":{"position":[[1917,5]]},"15":{"position":[[1585,5]]},"34":{"position":[[13,5],[707,5],[895,5],[1846,5],[3268,5]]},"35":{"position":[[1,5]]},"44":{"position":[[927,5]]},"51":{"position":[[311,5],[1459,5]]},"52":{"position":[[649,5]]},"62":{"position":[[10,5],[1685,5]]},"71":{"position":[[53,5]]},"76":{"position":[[504,5],[1800,5]]},"82":{"position":[[1,5]]},"91":{"position":[[5944,5]]},"97":{"position":[[1633,5],[3361,5]]},"103":{"position":[[1510,5]]},"105":{"position":[[4,5]]},"109":{"position":[[584,5]]},"110":{"position":[[515,5]]},"111":{"position":[[577,5]]},"113":{"position":[[4,5],[2425,5]]},"116":{"position":[[628,5]]},"117":{"position":[[1893,5]]},"137":{"position":[[205,5]]},"146":{"position":[[330,5]]}},"keywords":{}}],["weather",{"_index":1195,"title":{"30":{"position":[[22,7]]}},"content":{"28":{"position":[[43,7]]},"29":{"position":[[274,7],[393,7]]},"30":{"position":[[67,7],[7518,7],[9131,7],[9269,7]]}},"keywords":{}}],["web",{"_index":885,"title":{},"content":{"22":{"position":[[206,3]]},"97":{"position":[[752,3]]},"125":{"position":[[4422,3],[4541,3],[8826,3],[9602,3],[11156,4],[11345,3],[11373,3]]},"139":{"position":[[410,3]]}},"keywords":{}}],["webapi",{"_index":4173,"title":{},"content":{"125":{"position":[[8793,7]]}},"keywords":{}}],["webassembl",{"_index":4097,"title":{},"content":{"125":{"position":[[4397,11]]}},"keywords":{}}],["webpack",{"_index":0,"title":{"0":{"position":[[4,7]]}},"content":{"3":{"position":[[721,7],[802,7],[945,7],[1151,7]]},"4":{"position":[[1184,8],[1300,8]]},"125":{"position":[[3967,7],[4172,7],[5122,7],[6180,9],[6645,7],[8457,7],[11036,7]]}},"keywords":{}}],["websit",{"_index":4104,"title":{},"content":{"125":{"position":[[4946,7]]}},"keywords":{}}],["week",{"_index":288,"title":{},"content":{"4":{"position":[[1284,4]]},"123":{"position":[[386,6]]},"125":{"position":[[166,5],[2467,5]]}},"keywords":{}}],["weekdayloc",{"_index":2848,"title":{},"content":{"88":{"position":[[444,16]]}},"keywords":{}}],["weekdaylocator(monday",{"_index":2868,"title":{},"content":{"88":{"position":[[1199,22]]}},"keywords":{}}],["weekend",{"_index":4356,"title":{},"content":{"132":{"position":[[862,7]]}},"keywords":{}}],["weekformatt",{"_index":2870,"title":{},"content":{"88":{"position":[[1245,13]]}},"keywords":{}}],["weekli",{"_index":3972,"title":{},"content":{"123":{"position":[[213,7]]}},"keywords":{}}],["weird",{"_index":2706,"title":{"126":{"position":[[23,5]]}},"content":{"76":{"position":[[1400,5]]},"97":{"position":[[2514,5]]},"120":{"position":[[330,5]]},"121":{"position":[[1870,5]]},"156":{"position":[[529,6]]},"196":{"position":[[536,5]]},"198":{"position":[[60,5]]}},"keywords":{}}],["weirder",{"_index":5124,"title":{},"content":{"184":{"position":[[423,7]]}},"keywords":{}}],["welcom",{"_index":696,"title":{"16":{"position":[[0,8]]}},"content":{},"keywords":{}}],["well",{"_index":125,"title":{},"content":{"2":{"position":[[772,5]]},"3":{"position":[[693,5]]},"25":{"position":[[82,5],[2609,5]]},"28":{"position":[[2324,5],[2469,5],[4101,5]]},"29":{"position":[[254,4]]},"30":{"position":[[4499,4]]},"34":{"position":[[975,5]]},"40":{"position":[[2142,5],[2528,4]]},"44":{"position":[[1753,4]]},"45":{"position":[[42,4]]},"46":{"position":[[315,5]]},"53":{"position":[[1905,5]]},"66":{"position":[[1,5]]},"76":{"position":[[64,4]]},"78":{"position":[[60,4]]},"82":{"position":[[1288,5]]},"89":{"position":[[402,4]]},"90":{"position":[[4738,5]]},"91":{"position":[[1693,4]]},"98":{"position":[[135,4],[786,4]]},"102":{"position":[[273,4],[408,5]]},"103":{"position":[[2357,5]]},"104":{"position":[[1786,5]]},"106":{"position":[[100,4]]},"115":{"position":[[842,5]]},"121":{"position":[[1500,4]]},"122":{"position":[[1127,4]]},"123":{"position":[[1069,4]]},"125":{"position":[[9245,5]]},"132":{"position":[[356,4]]},"156":{"position":[[1162,5]]},"165":{"position":[[1480,5]]},"166":{"position":[[620,5]]},"176":{"position":[[1294,5]]},"185":{"position":[[13,4]]},"188":{"position":[[117,4]]},"197":{"position":[[286,5]]}},"keywords":{}}],["went",{"_index":1803,"title":{},"content":{"40":{"position":[[701,4]]},"125":{"position":[[3410,4]]},"132":{"position":[[842,4]]},"136":{"position":[[939,4]]}},"keywords":{}}],["weren't",{"_index":1397,"title":{},"content":{"30":{"position":[[4192,7]]}},"keywords":{}}],["what'",{"_index":1810,"title":{},"content":{"40":{"position":[[1353,6]]},"44":{"position":[[1041,6]]},"61":{"position":[[51,6]]},"96":{"position":[[1337,6]]},"97":{"position":[[2127,6]]},"160":{"position":[[1906,6]]}},"keywords":{}}],["whatsoev",{"_index":3657,"title":{},"content":{"106":{"position":[[924,11]]}},"keywords":{}}],["wheel",{"_index":2296,"title":{},"content":{"55":{"position":[[45,6]]},"190":{"position":[[664,6]]}},"keywords":{}}],["whena",{"_index":4622,"title":{},"content":{"158":{"position":[[198,5]]}},"keywords":{}}],["whendtpars",{"_index":4344,"title":{},"content":{"132":{"position":[[276,11]]}},"keywords":{}}],["whenev",{"_index":2358,"title":{},"content":{"61":{"position":[[810,8]]},"72":{"position":[[70,8]]},"90":{"position":[[4897,8]]},"143":{"position":[[51,8]]},"172":{"position":[[263,8]]},"188":{"position":[[586,8]]}},"keywords":{}}],["wherenom",{"_index":4797,"title":{},"content":{"163":{"position":[[2224,8]]}},"keywords":{}}],["wherev",{"_index":4630,"title":{},"content":{"159":{"position":[[469,8]]},"178":{"position":[[730,8]]}},"keywords":{}}],["whether",{"_index":1224,"title":{},"content":{"28":{"position":[[783,7]]},"30":{"position":[[13,7]]},"41":{"position":[[360,7]]},"72":{"position":[[721,7]]},"73":{"position":[[786,7]]},"102":{"position":[[1437,7],[1512,7]]},"142":{"position":[[71,7]]},"159":{"position":[[239,7]]},"160":{"position":[[2624,7]]},"175":{"position":[[391,7]]}},"keywords":{}}],["whiledateutil",{"_index":3901,"title":{},"content":{"121":{"position":[[1476,13]]}},"keywords":{}}],["whileon",{"_index":3887,"title":{},"content":{"121":{"position":[[873,8]]}},"keywords":{}}],["whine",{"_index":3398,"title":{},"content":{"97":{"position":[[3166,8]]}},"keywords":{}}],["whip",{"_index":4038,"title":{},"content":{"125":{"position":[[1249,4]]}},"keywords":{}}],["whitacr",{"_index":2258,"title":{},"content":{"53":{"position":[[1233,8]]}},"keywords":{}}],["whitespac",{"_index":3909,"title":{},"content":{"121":{"position":[[1713,10]]}},"keywords":{}}],["whole",{"_index":1369,"title":{},"content":{"30":{"position":[[2303,5],[3975,6]]},"40":{"position":[[3070,5]]},"53":{"position":[[1644,5],[2190,5]]},"93":{"position":[[537,5]]},"117":{"position":[[556,5]]},"121":{"position":[[541,5]]},"165":{"position":[[324,6]]},"175":{"position":[[1179,5]]}},"keywords":{}}],["whop",{"_index":3100,"title":{},"content":{"91":{"position":[[1530,8]]}},"keywords":{}}],["whose",{"_index":4252,"title":{},"content":{"128":{"position":[[403,5]]},"190":{"position":[[314,5]]}},"keywords":{}}],["whynotu8",{"_index":5342,"title":{},"content":{"197":{"position":[[391,8],[426,8],[1206,10],[1323,8]]}},"keywords":{}}],["whyw",{"_index":3855,"title":{},"content":{"120":{"position":[[627,5]]}},"keywords":{}}],["wide",{"_index":3183,"title":{},"content":{"92":{"position":[[1506,4]]}},"keywords":{}}],["wider",{"_index":1377,"title":{},"content":{"30":{"position":[[2675,5]]}},"keywords":{}}],["width",{"_index":3165,"title":{},"content":{"91":{"position":[[4813,5],[5860,5]]}},"keywords":{}}],["width=1",{"_index":2765,"title":{},"content":{"78":{"position":[[522,8],[719,8]]}},"keywords":{}}],["wild",{"_index":2447,"title":{"63":{"position":[[0,4]]}},"content":{},"keywords":{}}],["wildli",{"_index":2396,"title":{},"content":{"62":{"position":[[192,6]]}},"keywords":{}}],["will",{"_index":5001,"title":{},"content":{"175":{"position":[[47,7]]}},"keywords":{}}],["willchang",{"_index":5133,"title":{},"content":{"184":{"position":[[1206,10]]}},"keywords":{}}],["win",{"_index":1582,"title":{},"content":{"33":{"position":[[991,7],[1168,7]]}},"keywords":{}}],["window",{"_index":3223,"title":{},"content":{"93":{"position":[[2370,8]]},"125":{"position":[[3430,6]]},"134":{"position":[[88,9]]},"173":{"position":[[264,7]]}},"keywords":{}}],["winner",{"_index":2247,"title":{},"content":{"53":{"position":[[1125,8]]}},"keywords":{}}],["wire",{"_index":4825,"title":{},"content":{"165":{"position":[[283,4]]}},"keywords":{}}],["wise",{"_index":2259,"title":{},"content":{"53":{"position":[[1249,4]]}},"keywords":{}}],["wish",{"_index":2485,"title":{},"content":{"64":{"position":[[1525,4]]}},"keywords":{}}],["wishlist",{"_index":4203,"title":{},"content":{"125":{"position":[[10926,8]]}},"keywords":{}}],["with"cut",{"_index":5033,"title":{},"content":{"175":{"position":[[1474,13]]}},"keywords":{}}],["with/without",{"_index":679,"title":{},"content":{"15":{"position":[[1280,12]]}},"keywords":{}}],["with:parse(timestr",{"_index":3864,"title":{},"content":{"120":{"position":[[900,20]]}},"keywords":{}}],["withconst/stat",{"_index":5109,"title":{},"content":{"182":{"position":[[267,17]]}},"keywords":{}}],["within",{"_index":1410,"title":{},"content":{"30":{"position":[[5622,6]]},"45":{"position":[[477,6],[602,6]]},"83":{"position":[[275,6]]},"125":{"position":[[2230,6],[2446,6]]},"135":{"position":[[398,6],[469,6]]}},"keywords":{}}],["within_leverag",{"_index":840,"title":{},"content":{"20":{"position":[[2094,15]]}},"keywords":{}}],["within_leverage(x",{"_index":832,"title":{},"content":{"20":{"position":[[1824,19]]}},"keywords":{}}],["without",{"_index":381,"title":{"14":{"position":[[8,7]]}},"content":{"7":{"position":[[112,7],[1115,7]]},"14":{"position":[[35,7],[2951,7],[3342,7]]},"29":{"position":[[406,7]]},"33":{"position":[[122,7]]},"45":{"position":[[1168,7]]},"61":{"position":[[152,7],[977,7]]},"64":{"position":[[1434,7]]},"97":{"position":[[6336,7]]},"104":{"position":[[1911,7]]},"106":{"position":[[358,7]]},"123":{"position":[[413,7]]},"125":{"position":[[4486,7]]},"160":{"position":[[2351,7]]},"163":{"position":[[761,7]]},"165":{"position":[[1341,7]]},"188":{"position":[[418,7],[1764,7]]}},"keywords":{}}],["withoutstd::vec",{"_index":4694,"title":{},"content":{"160":{"position":[[2455,16]]}},"keywords":{}}],["wmt",{"_index":3212,"title":{},"content":{"93":{"position":[[1952,3]]}},"keywords":{}}],["won't",{"_index":1705,"title":{},"content":{"39":{"position":[[6,5]]},"51":{"position":[[3078,5]]},"97":{"position":[[827,5],[5911,5]]},"101":{"position":[[737,5]]},"102":{"position":[[928,5]]},"111":{"position":[[893,5]]},"172":{"position":[[2519,5]]},"176":{"position":[[1010,5]]},"186":{"position":[[512,5]]},"195":{"position":[[988,5]]},"198":{"position":[[921,5]]}},"keywords":{}}],["wonder",{"_index":4347,"title":{},"content":{"132":{"position":[[449,9]]},"193":{"position":[[15,8]]}},"keywords":{}}],["woodchuck",{"_index":2056,"title":{},"content":{"49":{"position":[[283,9]]}},"keywords":{}}],["word",{"_index":2053,"title":{},"content":{"49":{"position":[[93,6],[137,5],[215,5],[238,5],[278,4]]},"51":{"position":[[406,5],[800,4],[823,4],[892,6],[918,5],[1109,5],[1284,4],[1366,5],[2869,4],[3031,5],[3477,5]]},"52":{"position":[[124,5],[580,5]]}},"keywords":{}}],["word_dist",{"_index":2102,"title":{},"content":{"51":{"position":[[1265,9],[4105,11]]},"52":{"position":[[223,10],[264,10],[305,10],[346,10],[1074,10]]}},"keywords":{}}],["word_dist[word",{"_index":2108,"title":{},"content":{"51":{"position":[[1419,15]]}},"keywords":{}}],["words.th",{"_index":2059,"title":{},"content":{"49":{"position":[[439,9]]}},"keywords":{}}],["work",{"_index":124,"title":{},"content":{"2":{"position":[[764,7]]},"3":{"position":[[1542,5]]},"34":{"position":[[139,4]]},"35":{"position":[[197,4]]},"39":{"position":[[89,4]]},"41":{"position":[[388,4]]},"43":{"position":[[60,5],[217,5],[1012,7]]},"54":{"position":[[263,4]]},"55":{"position":[[164,6]]},"57":{"position":[[281,4]]},"58":{"position":[[23,4],[910,4]]},"64":{"position":[[112,4]]},"73":{"position":[[329,5]]},"74":{"position":[[283,7],[1194,4]]},"75":{"position":[[105,5]]},"76":{"position":[[3393,5]]},"82":{"position":[[19,7]]},"91":{"position":[[2201,4]]},"93":{"position":[[1028,4]]},"95":{"position":[[308,4],[347,7]]},"96":{"position":[[2332,6]]},"97":{"position":[[651,5],[1177,7],[3372,7],[3859,7]]},"98":{"position":[[25,5]]},"100":{"position":[[17,7],[118,7],[310,4],[408,4]]},"102":{"position":[[461,5]]},"104":{"position":[[861,4]]},"106":{"position":[[87,5]]},"108":{"position":[[648,4],[849,5]]},"116":{"position":[[892,5]]},"117":{"position":[[1447,7],[1925,4]]},"121":{"position":[[8,6],[890,6]]},"123":{"position":[[635,7]]},"125":{"position":[[3258,4],[4081,6],[6965,4],[8733,4],[10009,5],[11084,4]]},"128":{"position":[[1707,7]]},"132":{"position":[[350,5]]},"141":{"position":[[111,4]]},"150":{"position":[[667,8]]},"158":{"position":[[258,4]]},"164":{"position":[[529,4],[1462,4]]},"165":{"position":[[847,4],[1456,4]]},"166":{"position":[[614,5]]},"172":{"position":[[677,4]]},"174":{"position":[[954,4]]},"183":{"position":[[803,4]]},"184":{"position":[[482,6]]},"188":{"position":[[720,4]]},"189":{"position":[[67,5],[427,5]]},"192":{"position":[[730,7]]},"193":{"position":[[1408,4]]}},"keywords":{}}],["work"",{"_index":296,"title":{},"content":{"4":{"position":[[1470,10]]},"188":{"position":[[762,10]]}},"keywords":{}}],["work?"",{"_index":4059,"title":{},"content":{"125":{"position":[[2170,11]]}},"keywords":{}}],["workaround",{"_index":4106,"title":{},"content":{"125":{"position":[[5090,10]]}},"keywords":{}}],["worker",{"_index":175,"title":{},"content":{"3":{"position":[[818,6]]},"121":{"position":[[1335,6]]}},"keywords":{}}],["workflow",{"_index":2369,"title":{},"content":{"61":{"position":[[1375,9]]}},"keywords":{}}],["worki",{"_index":240,"title":{},"content":{"4":{"position":[[426,5]]}},"keywords":{}}],["worklet",{"_index":87,"title":{},"content":{"2":{"position":[[176,8],[323,7],[537,8],[632,7]]},"3":{"position":[[223,7],[994,7],[1377,7]]}},"keywords":{}}],["worklets,"",{"_index":227,"title":{},"content":{"4":{"position":[[109,15]]}},"keywords":{}}],["world",{"_index":2548,"title":{},"content":{"66":{"position":[[597,6]]},"104":{"position":[[724,6]]},"160":{"position":[[774,5]]},"174":{"position":[[485,7]]}},"keywords":{}}],["world"",{"_index":4686,"title":{},"content":{"160":{"position":[[2145,11]]},"172":{"position":[[632,11]]}},"keywords":{}}],["worldwid",{"_index":1213,"title":{},"content":{"28":{"position":[[459,9]]}},"keywords":{}}],["worri",{"_index":77,"title":{},"content":{"2":{"position":[[41,5]]},"38":{"position":[[1329,8]]},"40":{"position":[[731,5]]},"45":{"position":[[1176,8],[1457,5]]},"98":{"position":[[696,5]]},"111":{"position":[[899,5]]},"122":{"position":[[827,5]]},"127":{"position":[[383,5]]},"160":{"position":[[1569,5]]},"194":{"position":[[16,7]]}},"keywords":{}}],["wors",{"_index":2668,"title":{},"content":{"75":{"position":[[829,6]]}},"keywords":{}}],["worse.typ",{"_index":4636,"title":{},"content":{"159":{"position":[[858,11]]}},"keywords":{}}],["worst",{"_index":1430,"title":{},"content":{"30":{"position":[[7534,5]]},"124":{"position":[[292,7]]},"170":{"position":[[244,5],[272,5]]}},"keywords":{}}],["worth",{"_index":2338,"title":{},"content":{"58":{"position":[[735,5]]},"66":{"position":[[250,5]]},"157":{"position":[[89,5]]},"160":{"position":[[4441,5]]},"161":{"position":[[458,5]]},"163":{"position":[[2386,5]]},"166":{"position":[[756,5]]},"174":{"position":[[981,6]]}},"keywords":{}}],["worthless",{"_index":1964,"title":{},"content":{"45":{"position":[[262,9]]}},"keywords":{}}],["wouldn't",{"_index":3451,"title":{},"content":{"98":{"position":[[957,8]]},"125":{"position":[[3177,8]]},"150":{"position":[[433,8]]}},"keywords":{}}],["wow",{"_index":1931,"title":{},"content":{"44":{"position":[[911,4]]}},"keywords":{}}],["wow64",{"_index":3226,"title":{},"content":{"93":{"position":[[2388,6]]}},"keywords":{}}],["wrangl",{"_index":1713,"title":{},"content":{"39":{"position":[[320,9]]}},"keywords":{}}],["wrap",{"_index":4654,"title":{},"content":{"160":{"position":[[371,7]]},"194":{"position":[[29,8]]}},"keywords":{}}],["wrapper",{"_index":5149,"title":{},"content":{"188":{"position":[[175,8]]}},"keywords":{}}],["write",{"_index":7,"title":{"110":{"position":[[8,7]]}},"content":{"1":{"position":[[38,5]]},"4":{"position":[[790,7]]},"6":{"position":[[403,8]]},"20":{"position":[[1188,5]]},"53":{"position":[[473,7]]},"76":{"position":[[845,5]]},"86":{"position":[[658,5]]},"95":{"position":[[563,5]]},"96":{"position":[[288,6]]},"97":{"position":[[263,5]]},"108":{"position":[[67,5]]},"109":{"position":[[635,7]]},"110":{"position":[[27,7]]},"121":{"position":[[1114,7]]},"122":{"position":[[638,7],[668,7]]},"125":{"position":[[2273,7],[9396,7]]},"132":{"position":[[699,7],[813,5]]},"137":{"position":[[31,5]]},"139":{"position":[[67,5],[402,7]]},"148":{"position":[[29,7],[420,5]]},"158":{"position":[[6,7],[103,5],[432,5]]},"160":{"position":[[2214,7],[2632,7],[4115,7]]},"161":{"position":[[1600,7]]},"163":{"position":[[769,7],[2475,5]]},"168":{"position":[[119,5]]},"173":{"position":[[983,7]]},"188":{"position":[[208,7]]}},"keywords":{}}],["writei",{"_index":4415,"title":{},"content":{"139":{"position":[[248,6]]}},"keywords":{}}],["writing)qqq",{"_index":321,"title":{},"content":{"6":{"position":[[320,11]]}},"keywords":{}}],["written",{"_index":2169,"title":{},"content":{"52":{"position":[[72,7]]},"173":{"position":[[226,7]]}},"keywords":{}}],["wrong",{"_index":3163,"title":{},"content":{"91":{"position":[[4727,5]]},"121":{"position":[[2555,6]]},"136":{"position":[[96,5]]}},"keywords":{}}],["wrote",{"_index":3719,"title":{},"content":{"112":{"position":[[1155,5]]},"121":{"position":[[2546,5]]},"173":{"position":[[10,5]]}},"keywords":{}}],["wxwdidget",{"_index":4047,"title":{},"content":{"125":{"position":[[1341,10]]}},"keywords":{}}],["wxwidget",{"_index":4040,"title":{},"content":{"125":{"position":[[1267,10]]}},"keywords":{}}],["x",{"_index":409,"title":{},"content":{"7":{"position":[[659,1]]},"20":{"position":[[1469,2],[1806,2],[1893,2],[1987,1],[2227,2]]},"22":{"position":[[536,2],[1496,2]]},"28":{"position":[[1402,2],[1506,2],[1509,1],[2246,1],[3197,2],[3297,2],[3300,1],[3919,1]]},"30":{"position":[[1768,2],[1867,2],[1870,1],[2147,1],[3117,2],[3216,2],[3219,1],[3633,1],[3852,1],[5036,2],[5131,2],[5134,1],[5406,1],[6185,2],[6285,2],[6288,1],[6706,1],[6931,1],[9428,2]]},"39":{"position":[[2710,2],[2769,2],[2834,2],[2900,2],[3013,2]]},"40":{"position":[[2168,3]]},"43":{"position":[[540,1]]},"51":{"position":[[551,2],[1141,2],[1245,1],[2268,2],[2275,1],[2367,1],[3294,2],[3332,1]]},"62":{"position":[[1064,2],[1102,2]]},"70":{"position":[[961,1]]},"74":{"position":[[608,1],[626,1],[663,1],[685,1]]},"76":{"position":[[608,1]]},"90":{"position":[[4105,1]]},"91":{"position":[[2030,2],[2044,2]]},"93":{"position":[[2776,2],[2846,2],[2849,1],[4443,2],[4457,2]]},"108":{"position":[[460,1]]},"110":{"position":[[472,1]]},"112":{"position":[[1708,1]]},"113":{"position":[[2284,1]]},"127":{"position":[[639,1],[1289,1]]},"128":{"position":[[276,1],[510,3],[574,3],[1148,1],[1400,3]]},"129":{"position":[[1442,2],[1563,2],[1932,1],[2617,1]]},"152":{"position":[[657,3],[721,1]]},"156":{"position":[[1052,2]]},"184":{"position":[[166,2],[273,2],[525,2],[593,2]]},"185":{"position":[[671,2],[831,2]]},"192":{"position":[[130,2],[310,2],[392,2]]},"193":{"position":[[921,2],[1784,2],[1819,2],[1851,2],[2226,2],[2739,2],[2774,2],[2806,2],[3192,2]]},"194":{"position":[[275,2],[327,1],[394,2]]},"196":{"position":[[976,1],[1134,2],[1555,1],[1594,4],[1757,1],[1791,4]]},"197":{"position":[[402,2],[549,2],[1128,1],[1334,2],[1362,2]]},"198":{"position":[[1009,2],[1144,2]]},"199":{"position":[[1352,1]]}},"keywords":{}}],["x+i",{"_index":2097,"title":{},"content":{"51":{"position":[[1147,4]]}},"keywords":{}}],["x.__str__",{"_index":4332,"title":{},"content":{"129":{"position":[[2636,11]]}},"keywords":{}}],["x.column",{"_index":1901,"title":{},"content":{"44":{"position":[[212,9]]}},"keywords":{}}],["x.drop(b_class",{"_index":1993,"title":{},"content":{"45":{"position":[[1993,15]]}},"keywords":{}}],["x.iter().enumer",{"_index":5383,"title":{},"content":{"199":{"position":[[1489,20]]}},"keywords":{}}],["x.nonzero()[1",{"_index":2596,"title":{},"content":{"70":{"position":[[1008,14]]}},"keywords":{}}],["x.union(i",{"_index":1482,"title":{},"content":{"30":{"position":[[9434,11]]}},"keywords":{}}],["x.valu",{"_index":5387,"title":{},"content":{"199":{"position":[[1679,10]]}},"keywords":{}}],["x1",{"_index":2599,"title":{},"content":{"70":{"position":[[1107,2]]},"71":{"position":[[1258,2]]},"193":{"position":[[1334,2],[1425,3],[1437,3],[2514,2],[3285,2],[3349,3],[3361,3],[3599,2],[3663,3],[3675,3]]}},"keywords":{}}],["x2",{"_index":2601,"title":{},"content":{"70":{"position":[[1134,2]]},"71":{"position":[[1285,2]]},"193":{"position":[[1348,2],[1431,3],[1443,4],[2528,2],[3299,2],[3355,3],[3367,4],[3613,2],[3669,3],[3681,4]]}},"keywords":{}}],["x2).plot(kind='hist",{"_index":2604,"title":{},"content":{"70":{"position":[[1176,21]]},"71":{"position":[[1327,21]]}},"keywords":{}}],["x[0",{"_index":898,"title":{},"content":{"22":{"position":[[539,4],[1499,4]]},"28":{"position":[[2236,5],[3909,5]]},"39":{"position":[[3016,5]]},"51":{"position":[[554,5],[1219,4],[2293,4],[2388,4]]}},"keywords":{}}],["x[0][0",{"_index":1771,"title":{},"content":{"39":{"position":[[2923,8]]}},"keywords":{}}],["x[1",{"_index":1764,"title":{},"content":{"39":{"position":[[2713,5]]}},"keywords":{}}],["x_axis_label='year",{"_index":1272,"title":{},"content":{"28":{"position":[[2142,20],[3806,20]]},"30":{"position":[[2122,20],[3608,20],[3815,20],[5381,20],[6681,20],[6894,20]]}},"keywords":{}}],["x_bin",{"_index":1913,"title":{},"content":{"44":{"position":[[602,5]]}},"keywords":{}}],["x_no_bin",{"_index":1992,"title":{},"content":{"45":{"position":[[1982,8]]}},"keywords":{}}],["x_pow",{"_index":5288,"title":{},"content":{"193":{"position":[[1417,5],[1497,5],[2570,5],[2658,5],[3341,5],[3421,5],[3655,5],[3735,5]]}},"keywords":{}}],["x_range=(1990",{"_index":1363,"title":{},"content":{"30":{"position":[[2100,14],[3586,14],[3793,14],[5359,14],[6659,14],[6872,14]]}},"keywords":{}}],["x_tick",{"_index":425,"title":{},"content":{"7":{"position":[[954,7],[992,7]]}},"keywords":{}}],["x_xform",{"_index":1996,"title":{},"content":{"45":{"position":[[2065,7],[2852,7]]}},"keywords":{}}],["xlabel",{"_index":420,"title":{},"content":{"7":{"position":[[844,6],[895,6]]}},"keywords":{}}],["xml",{"_index":4848,"title":{},"content":{"166":{"position":[[730,3]]}},"keywords":{}}],["xom",{"_index":710,"title":{},"content":{"17":{"position":[[154,7]]},"18":{"position":[[331,6]]},"19":{"position":[[553,6]]},"20":{"position":[[473,6],[2827,8]]}},"keywords":{}}],["xtick",{"_index":414,"title":{},"content":{"7":{"position":[[743,5]]}},"keywords":{}}],["xxx",{"_index":2091,"title":{},"content":{"51":{"position":[[831,4]]}},"keywords":{}}],["xyz",{"_index":3790,"title":{},"content":{"115":{"position":[[2655,3]]}},"keywords":{}}],["y",{"_index":1258,"title":{},"content":{"28":{"position":[[1853,2],[1867,1],[3601,2],[3615,1]]},"30":{"position":[[2023,1],[3429,1],[3517,1],[5273,1],[6503,1],[6591,1],[9431,2]]},"43":{"position":[[586,1]]},"44":{"position":[[665,2]]},"45":{"position":[[2139,2],[2168,2],[2919,2],[2948,2]]},"51":{"position":[[1144,2],[3301,2],[3356,1]]},"62":{"position":[[559,3],[1105,3]]},"88":{"position":[[755,3]]},"93":{"position":[[4170,3]]},"110":{"position":[[485,1]]},"112":{"position":[[1714,1]]},"113":{"position":[[2290,1]]},"127":{"position":[[1304,1],[1394,1],[1468,1]]},"152":{"position":[[690,1],[726,3],[875,3]]},"185":{"position":[[679,2],[837,2]]},"192":{"position":[[138,2],[316,2],[398,2]]},"193":{"position":[[929,2],[1790,2],[1825,2],[1857,2],[2234,2],[2745,2],[2780,2],[2812,2],[3200,2]]},"194":{"position":[[286,2],[353,1],[397,1]]},"196":{"position":[[1574,1],[1589,4],[1776,1],[1796,4]]},"199":{"position":[[1347,1],[1361,2],[1483,2],[1517,2],[1674,1],[1697,2]]}},"keywords":{}}],["y.uniqu",{"_index":1873,"title":{},"content":{"43":{"position":[[607,10]]}},"keywords":{}}],["y1",{"_index":5284,"title":{},"content":{"193":{"position":[[1362,2],[1460,3],[1472,3],[2542,2],[3313,2],[3384,3],[3396,3],[3627,2],[3698,3],[3710,3]]}},"keywords":{}}],["y2",{"_index":5286,"title":{},"content":{"193":{"position":[[1376,2],[1466,3],[1478,4],[2556,2],[3327,2],[3390,3],[3402,4],[3641,2],[3704,3],[3716,4]]}},"keywords":{}}],["y=motion",{"_index":437,"title":{},"content":{"7":{"position":[[1219,10]]}},"keywords":{}}],["y[i",{"_index":1936,"title":{},"content":{"44":{"position":[[1338,3]]}},"keywords":{}}],["y_axis_label='cloud",{"_index":1273,"title":{},"content":{"28":{"position":[[2163,19]]}},"keywords":{}}],["y_axis_label='precipit",{"_index":1305,"title":{},"content":{"28":{"position":[[3827,27]]}},"keywords":{}}],["y_pow",{"_index":5289,"title":{},"content":{"193":{"position":[[1452,5],[1505,6],[2609,5],[2666,6],[3376,5],[3429,6],[3690,5],[3743,6]]}},"keywords":{}}],["yahoo/celg",{"_index":1827,"title":{},"content":{"40":{"position":[[2652,13]]}},"keywords":{}}],["yaml",{"_index":3103,"title":{},"content":{"91":{"position":[[1848,4]]},"93":{"position":[[1452,4],[3858,4]]}},"keywords":{}}],["yaml.load('\\n'.join(filt",{"_index":3114,"title":{},"content":{"91":{"position":[[2085,30]]},"93":{"position":[[4498,30]]}},"keywords":{}}],["yarn",{"_index":4077,"title":{},"content":{"125":{"position":[[3133,4],[3157,4],[6403,4]]}},"keywords":{}}],["ye",{"_index":4436,"title":{},"content":{"141":{"position":[[80,4]]}},"keywords":{}}],["year",{"_index":347,"title":{},"content":{"6":{"position":[[669,5],[760,4],[977,5],[1029,4]]},"7":{"position":[[46,4],[173,4],[254,6]]},"9":{"position":[[659,4],[718,5],[724,5]]},"10":{"position":[[339,5]]},"11":{"position":[[141,4],[198,4]]},"13":{"position":[[360,5]]},"14":{"position":[[703,4],[847,4],[958,4],[1040,4],[1161,4]]},"15":{"position":[[348,4],[409,4],[463,4]]},"28":{"position":[[94,6],[724,5],[1229,5],[1760,5],[1872,6],[3029,5],[3620,6]]},"30":{"position":[[629,6],[1346,5],[2028,6],[2440,4],[3434,6],[3522,6],[4236,6],[4415,6],[5278,6],[5670,6],[5769,6],[6508,6],[6596,6],[7501,4],[7558,6],[9063,5],[9388,4],[9396,6]]},"40":{"position":[[76,5],[1106,4]]},"41":{"position":[[328,4]]},"64":{"position":[[356,6]]},"65":{"position":[[313,4],[791,5],[952,4],[1053,4],[1106,4],[1162,4],[1216,4]]},"66":{"position":[[490,6]]}},"keywords":{}}],["year_index",{"_index":580,"title":{},"content":{"13":{"position":[[1281,12],[1392,14]]},"14":{"position":[[2353,12],[2464,14]]},"15":{"position":[[2025,12],[2136,14]]}},"keywords":{}}],["year_mot",{"_index":520,"title":{},"content":{"11":{"position":[[441,11],[532,12]]},"12":{"position":[[399,11],[493,12]]}},"keywords":{}}],["year_pric",{"_index":565,"title":{},"content":{"13":{"position":[[640,12],[1150,13],[1187,12]]},"14":{"position":[[1481,12],[2184,13],[2232,12]]},"15":{"position":[[852,12],[1852,13],[1902,12]]}},"keywords":{}}],["year_prices[end",{"_index":576,"title":{},"content":{"13":{"position":[[959,16],[1036,17]]},"14":{"position":[[1977,16],[2070,17]]},"15":{"position":[[1645,16],[1738,17]]}},"keywords":{}}],["year_prices[i",{"_index":569,"title":{},"content":{"13":{"position":[[774,14]]},"14":{"position":[[1631,14]]},"15":{"position":[[1018,14]]}},"keywords":{}}],["yearli",{"_index":463,"title":{},"content":{"9":{"position":[[262,6],[612,6]]},"13":{"position":[[511,6]]},"14":{"position":[[564,6]]}},"keywords":{}}],["yeast",{"_index":4738,"title":{},"content":{"161":{"position":[[626,5]]}},"keywords":{}}],["yep",{"_index":2279,"title":{},"content":{"53":{"position":[[1570,3]]}},"keywords":{}}],["yerr=[min_err",{"_index":3007,"title":{},"content":{"90":{"position":[[1934,14],[3073,14]]}},"keywords":{}}],["yet?"",{"_index":3406,"title":{},"content":{"97":{"position":[[3867,10]]}},"keywords":{}}],["yew",{"_index":4160,"title":{},"content":{"125":{"position":[[8276,4],[8391,3],[9238,3]]}},"keywords":{}}],["yfinanc",{"_index":1750,"title":{},"content":{"39":{"position":[[2325,8]]}},"keywords":{}}],["yield",{"_index":3337,"title":{},"content":{"96":{"position":[[1231,6]]}},"keywords":{}}],["york",{"_index":1212,"title":{},"content":{"28":{"position":[[405,4]]},"93":{"position":[[3267,4]]}},"keywords":{}}],["you'd",{"_index":976,"title":{},"content":{"22":{"position":[[2725,5]]},"160":{"position":[[1549,5]]}},"keywords":{}}],["you'll",{"_index":1558,"title":{},"content":{"32":{"position":[[2133,6]]},"125":{"position":[[4513,6]]},"134":{"position":[[218,6],[350,6]]},"139":{"position":[[428,6]]},"155":{"position":[[182,6]]},"174":{"position":[[669,6]]},"184":{"position":[[960,6]]}},"keywords":{}}],["you'r",{"_index":1571,"title":{},"content":{"33":{"position":[[366,6]]},"59":{"position":[[189,6]]},"93":{"position":[[311,6]]},"97":{"position":[[139,6]]},"108":{"position":[[578,6],[794,6]]},"112":{"position":[[194,6],[402,6],[546,6]]},"118":{"position":[[108,6]]},"121":{"position":[[796,6],[1173,6]]},"125":{"position":[[4644,6],[7675,6],[9706,6]]},"139":{"position":[[395,6]]},"148":{"position":[[541,6]]},"150":{"position":[[711,6]]},"153":{"position":[[194,6]]},"157":{"position":[[534,6],[611,6]]},"176":{"position":[[1105,6]]},"184":{"position":[[778,6]]}},"keywords":{}}],["you'v",{"_index":1182,"title":{},"content":{"26":{"position":[[814,6]]},"39":{"position":[[188,6]]},"112":{"position":[[4,6]]},"125":{"position":[[3810,6]]},"134":{"position":[[10,6]]},"194":{"position":[[4,6]]}},"keywords":{}}],["young",{"_index":3930,"title":{"122":{"position":[[8,5]]}},"content":{},"keywords":{}}],["z",{"_index":2145,"title":{},"content":{"51":{"position":[[3307,2]]},"194":{"position":[[379,1]]}},"keywords":{}}],["zero",{"_index":2656,"title":{},"content":{"74":{"position":[[1596,4]]},"91":{"position":[[4120,4]]},"102":{"position":[[1054,5]]},"103":{"position":[[937,4]]},"155":{"position":[[1182,6]]},"164":{"position":[[1292,4]]},"165":{"position":[[435,4],[449,4]]}},"keywords":{}}],["zeros(m",{"_index":393,"title":{},"content":{"7":{"position":[[360,8]]}},"keywords":{}}],["zeros(num_simul",{"_index":587,"title":{},"content":{"13":{"position":[[1458,22]]},"14":{"position":[[2530,22]]},"15":{"position":[[2202,22]]}},"keywords":{}}],["zgc",{"_index":4909,"title":{},"content":{"172":{"position":[[576,4]]}},"keywords":{}}],["zip",{"_index":3674,"title":{},"content":{"108":{"position":[[693,3]]}},"keywords":{}}],["zombi",{"_index":4496,"title":{},"content":{"150":{"position":[[474,6]]}},"keywords":{}}]],"pipeline":["stemmer"]} \ No newline at end of file diff --git a/lunr-index.json b/lunr-index.json new file mode 100644 index 0000000..29c90b3 --- /dev/null +++ b/lunr-index.json @@ -0,0 +1 @@ +{"version":"2.3.9","fields":["title","content","keywords"],"fieldVectors":[["title/0",[0,702.378,1,634.395,2,528.917]],["content/0",[]],["keywords/0",[]],["title/1",[3,309.686,4,1066.856]],["content/1",[3,4.518,5,10.911,6,6.539,7,4.858,8,6.071,9,12.074,10,7.758,11,8.535,12,12.182,13,6.959,14,12.182,15,12.182,16,5.678,17,7.867,18,3.07,19,6.908,20,4.047,21,4.947,22,2.986,23,2.789,24,10.911,25,6.218,26,12.182,27,5.559,28,8.179,29,9.449,30,10.911,31,10.074,32,12.182,33,10.074,34,4.11,35,12.182,36,12.182,37,12.182,38,12.182,39,9.449,40,7.867,41,5.446,42,12.182,43,12.182,44,12.182,45,5.446,46,12.182,47,9.449,48,6.717,49,7.867,50,10.074,51,12.182,52,8.95,53,3.695,54,5.802,55,8.179,56,7.591,57,6.539,58,7.591,59,12.182,60,12.182,61,12.182,62,7.867,63,12.182,64,5.802,65,12.182,66,4.947,67,9.449,68,5.135,69,12.182,70,10.074,71,12.182]],["keywords/1",[]],["title/2",[72,838.449]],["content/2",[9,9.081,18,3.824,21,4.755,22,3.719,25,5.976,31,12.548,73,2.831,74,4.507,75,7.86,76,10.486,77,7.056,78,11.707,79,4.587,80,11.707,81,8.145,82,15.172,83,10.402,84,4.843,85,9.144,86,1.995,87,15.95,88,10.486,89,5.13,90,10.486,91,4.843,92,11.707,93,4.013,94,5.976,95,9.144,96,7.561,97,9.081,98,2.87,99,10.486,100,4.213,101,11.707,102,9.682,103,11.707,104,4.507,105,11.707,106,7.561,107,7.86,108,4.843,109,5.576,110,6.125,111,9.799,112,11.707,113,7.86,114,7.86,115,5.576,116,3.246,117,7.86,118,6.125,119,9.081,120,9.081,121,11.707,122,11.707,123,11.707,124,3.35,125,4.013,126,9.081,127,5.457,128,9.081,129,11.707,130,5.457,131,3.771,132,11.707]],["keywords/2",[]],["title/3",[133,1298.223]],["content/3",[0,12.624,2,5.481,6,5.037,9,7.278,10,4.676,13,4.195,18,2.365,21,6.111,28,8.778,29,10.141,30,13.477,34,4.411,47,7.278,66,3.811,73,2.269,74,3.612,75,6.3,81,5.037,83,7.637,86,1.783,87,13.477,94,4.789,98,3.205,104,5.033,106,6.06,107,6.3,108,3.882,113,6.3,114,6.3,116,2.007,118,6.84,120,7.278,124,2.685,125,3.216,131,3.022,134,3.882,135,3.216,136,8.147,137,4.469,138,6.574,139,8.404,140,4.676,141,5.01,142,4.554,143,5.174,144,7.76,145,2.579,146,9.383,147,5.174,148,6.894,149,5.481,150,9.383,151,9.383,152,6.06,153,3.117,154,4.783,155,9.383,156,5.655,157,10.812,158,5.847,159,5.321,160,4.195,161,7.278,162,4.676,163,9.383,164,5.729,165,9.383,166,7.76,167,3.069,168,13.477,169,8.404,170,7.328,171,9.383,172,7.76,173,6.3,174,6.06,175,8.404,176,8.404,177,9.383,178,8.404,179,3.432,180,6.06,181,7.76,182,9.383,183,12.443,184,4.373,185,2.804,186,12.443,187,6.894,188,4.282,189,8.404,190,2.977,191,4.469,192,8.404,193,6.894,194,9.383,195,5.847,196,9.383,197,9.383,198,5.174,199,9.383,200,9.383,201,5.847,202,7.76,203,7.278,204,8.404,205,9.383,206,4.469,207,9.383,208,2.846,209,6.06,210,7.278,211,5.847,212,2.977,213,9.383,214,9.383,215,4.373,216,1.98]],["keywords/3",[]],["title/4",[217,588.253,218,955.587]],["content/4",[0,10.283,1,6.707,2,5.592,7,3.818,13,4.28,21,5.384,28,6.427,39,10.283,64,4.56,66,3.888,74,3.685,81,7.116,86,1.134,89,4.195,91,3.96,98,2.347,137,4.56,140,4.771,145,1.888,147,5.278,149,10.069,154,3.502,160,4.28,167,3.131,170,4.663,176,11.874,179,3.502,183,7.917,184,4.462,185,3.962,186,12.577,188,4.369,189,8.574,190,3.037,191,4.56,204,8.574,208,4.021,210,10.283,212,3.037,217,7.31,219,4.404,220,13.257,221,7.033,222,4.195,223,4.114,224,9.573,225,9.573,226,9.573,227,9.573,228,7.917,229,4.886,230,9.288,231,8.574,232,7.033,233,2.991,234,9.573,235,9.573,236,7.426,237,9.573,238,9.573,239,3.162,240,9.573,241,7.917,242,6.427,243,7.426,244,8.901,245,1.863,246,5.77,247,8.574,248,9.573,249,6.183,250,4.771,251,8.574,252,4.771,253,7.033,254,9.573,255,7.426,256,3.818,257,9.573,258,9.573,259,8.574,260,6.183,261,5.965,262,6.707,263,10.964,264,9.573,265,3.561,266,6.05,267,7.917,268,9.573,269,6.427,270,9.573,271,9.573,272,9.573,273,6.427,274,9.166,275,3.389,276,5.77,277,5.429,278,9.573,279,6.707,280,8.574,281,7.033,282,5.77,283,9.573,284,8.574,285,6.183,286,5.429,287,9.573,288,7.917,289,3.18,290,9.573,291,9.573,292,6.427,293,7.917,294,6.183,295,8.574,296,8.574,297,7.033,298,8.574,299,5.592,300,4.195]],["keywords/4",[]],["title/5",[301,882.296,302,955.587]],["content/5",[]],["keywords/5",[]],["title/6",[303,642.995,304,371.602]],["content/6",[7,3.711,18,2.345,23,2.13,86,1.54,104,3.582,141,2.864,143,5.13,145,1.835,172,7.694,245,2.914,276,7.833,301,7.694,302,8.333,303,5.607,304,6.446,305,4.867,306,6.976,307,2.951,308,3.23,309,5.607,310,9.304,311,8.333,312,4.251,313,9.304,314,7.217,315,9.674,316,4.077,317,9.027,318,9.304,319,2.982,320,12.996,321,9.304,322,9.304,323,12.996,324,9.549,325,12.996,326,12.996,327,12.996,328,5.811,329,7.694,330,9.304,331,9.304,332,9.304,333,3.582,334,7.694,335,7.694,336,3.849,337,5.607,338,9.304,339,9.304,340,9.304,341,9.304,342,6.518,343,6.836,344,4.246,345,8.099,346,6.564,347,8.483,348,9.304,349,9.304,350,4.431,351,8.394,352,6.836,353,9.471,354,9.106,355,9.304,356,9.304,357,3.645,358,2.281,359,5.434,360,6.009,361,9.304,362,9.304,363,9.304,364,9.304,365,5.695,366,9.304,367,4.531,368,7.694,369,9.106,370,4.994,371,9.304,372,7.217,373,8.333]],["keywords/6",[]],["title/7",[304,371.602,344,486.887]],["content/7",[20,2.926,22,2.159,53,2.672,64,4.195,86,1.723,98,2.159,104,3.391,143,4.857,154,3.222,212,2.794,216,1.859,219,5.768,233,2.752,245,1.714,265,3.277,275,3.118,276,7.537,282,5.309,285,5.689,303,5.309,304,5.064,308,3.108,312,2.881,319,2.983,328,3.938,345,11.129,347,7.607,351,5.689,358,2.159,367,8.141,370,7.805,374,2.52,375,6.472,376,5.309,377,4.02,378,8.808,379,7.889,380,7.284,381,6.233,382,3.222,383,7.889,384,7.284,385,8.808,386,4.29,387,8.808,388,7.889,389,4.39,390,9.188,391,8.808,392,9.762,393,8.808,394,8.808,395,8.808,396,8.808,397,8.808,398,6.832,399,8.808,400,8.808,401,8.808,402,2.926,403,7.889,404,3.451,405,7.284,406,7.284,407,8.808,408,8.808,409,3.169,410,8.808,411,6.383,412,8.761,413,6.171,414,8.808,415,5.145,416,4.105,417,3.222,418,3.391,419,14.539,420,12.505,421,8.808,422,4.728,423,8.808,424,8.808,425,12.505,426,8.808,427,8.808,428,8.808,429,13.023,430,3.577,431,3.86,432,8.808,433,8.808,434,8.808,435,8.808,436,8.808,437,8.808,438,8.808,439,8.808,440,8.808,441,8.808,442,8.808,443,8.808]],["keywords/7",[]],["title/8",[185,318.859,304,371.602]],["content/8",[53,4.333,58,8.902,73,3.454,86,2.036,167,4.673,289,4.746,304,4.976,307,4.532,308,3.551,309,8.61,319,2.808,351,9.227,357,6.732,389,7.12,392,9.592,403,12.796,444,10.009,445,12.796,446,14.286,447,5.315,448,14.286,449,4.602,450,14.286,451,12.038,452,14.286]],["keywords/8",[]],["title/9",[143,499.273,328,404.835,453,486.063]],["content/9",[3,4.821,18,2.869,23,2.606,73,2.753,104,4.383,142,3.966,143,10.082,145,2.246,216,2.403,219,3.782,239,2.715,277,9.418,282,6.862,307,3.612,308,2.83,312,4.873,315,9.622,316,4.989,319,2.783,328,7.425,335,9.416,345,7.094,347,8.689,352,8.365,357,6.507,358,4.071,374,3.257,379,10.198,386,5.545,392,7.644,404,4.461,411,5.811,454,4.71,455,7.977,456,3.966,457,10.198,458,7.094,459,7.741,460,5.545,461,12.277,462,16.608,463,12.322,464,11.385,465,11.385,466,11.385,467,11.385,468,11.385,469,11.385,470,11.385,471,11.385,472,11.385,473,7.977,474,5.956,475,11.385,476,11.385,477,11.385,478,11.385]],["keywords/9",[]],["title/10",[143,499.273,328,404.835,479,905.483]],["content/10",[22,3.1,73,3.058,86,1.499,143,8.789,185,3.78,307,4.012,312,4.137,319,2.869,328,7.127,329,10.46,347,6.617,386,6.16,411,8.136,454,6.594,459,5.895,461,8.491,480,9.292,481,6.455,482,8.861,483,4.551,484,6.304,485,7.881,486,19.288,487,15.94,488,12.647,489,9.292,490,12.647,491,12.647,492,8.168,493,12.647,494,12.647,495,12.647,496,7.881,497,11.328,498,10.46,499,4.268,500,11.328,501,9.292,502,12.647,503,12.647,504,12.647,505,12.647,506,15.94]],["keywords/10",[]],["title/11",[303,545.735,304,315.394,507,634.395]],["content/11",[3,3.616,22,3.054,64,5.933,73,3.012,86,1.476,104,4.796,143,6.869,145,2.457,219,4.138,245,3.373,276,7.508,277,7.064,304,6.037,305,6.517,307,3.952,319,2.862,328,5.569,335,10.302,345,7.762,347,8.26,351,8.045,354,8.728,358,4.249,365,6.918,367,6.067,416,5.806,445,11.158,453,6.687,461,8.364,497,11.158,500,11.158,507,8.728,508,5.685,509,10.302,510,9.663,511,7.762,512,6.687,513,12.457,514,7.508,515,15.788,516,12.457,517,11.158,518,9.152,519,12.457,520,14.141,521,12.457,522,12.457,523,12.457]],["keywords/11",[]],["title/12",[304,371.602,524,371.602]],["content/12",[22,2.89,73,2.851,86,1.806,98,2.89,153,3.917,219,5.063,239,2.812,245,3.287,246,7.106,265,4.386,276,7.106,277,6.687,289,5.063,301,9.751,304,5.883,306,6.329,308,2.931,312,3.857,319,2.894,328,6.815,345,9.498,351,9.844,354,8.261,358,3.737,367,8.227,370,8.182,374,3.374,388,10.561,392,7.916,402,3.917,444,8.261,447,4.386,453,6.329,501,8.663,507,8.261,517,10.561,518,8.663,520,13.653,525,7.615,526,4.703,527,11.791,528,10.561,529,16.89,530,11.791,531,11.791,532,11.791,533,11.791,534,9.146,535,9.146,536,9.146,537,11.791,538,11.791,539,11.791]],["keywords/12",[]],["title/13",[304,371.602,540,882.296]],["content/13",[22,1.816,45,4.929,48,4.084,53,2.247,73,1.791,141,2.28,145,1.461,219,5.431,242,4.973,245,3.459,303,7.937,304,6.659,306,7.069,307,2.35,316,3.246,319,2.896,328,3.312,333,5.07,336,3.064,344,3.381,345,6.87,347,3.876,351,8.505,352,10.718,357,2.902,358,1.816,365,4.832,367,3.608,370,3.976,372,5.746,392,4.973,398,5.746,402,4.846,417,4.033,418,2.852,449,3.551,454,4.561,461,4.973,463,6.126,474,5.768,501,5.443,518,8.101,534,5.746,535,5.746,536,5.746,540,13.52,541,6.126,542,5.19,543,4.514,544,12.064,545,7.408,546,13.52,547,9.118,548,8.552,549,7.408,550,5.746,551,7.408,552,6.635,553,7.408,554,6.645,555,9.676,556,6.635,557,6.635,558,12.064,559,10.891,560,12.064,561,3.453,562,6.126,563,7.408,564,6.126,565,10.891,566,10.891,567,6.126,568,6.126,569,6.126,570,7.408,571,7.408,572,6.126,573,6.126,574,3.608,575,6.126,576,9.118,577,6.126,578,6.126,579,7.408,580,9.118,581,6.126,582,6.126,583,6.126,584,6.126,585,6.126,586,6.126,587,6.126,588,6.126,589,9.118,590,6.126,591,6.126,592,6.126,593,9.118,594,6.126,595,6.126,596,4.245,597,6.126,598,9.118,599,6.126,600,7.408,601,6.126,602,7.408,603,11.025,604,6.126,605,7.025,606,7.408,607,7.408,608,2.622,609,7.408,610,7.408,611,7.408,612,7.408,613,3.312,614,7.408,615,7.408,616,7.408,617,7.408,618,7.408,619,4.973,620,7.408,621,7.408]],["keywords/13",[]],["title/14",[304,273.955,381,392.002,622,610.095,623,265.389]],["content/14",[34,2.031,45,4.207,48,5.189,53,1.826,86,0.713,108,2.49,145,1.187,153,2,156,3.628,185,2.812,219,5.691,242,4.041,245,3.259,246,5.671,276,3.628,303,6.983,304,6.405,306,8.089,307,1.91,308,1.496,312,1.969,316,4.124,317,3.628,319,2.881,328,2.691,333,5.043,336,2.49,345,5.864,347,7.437,351,7.483,352,8.512,357,2.358,358,3.485,365,4.124,367,2.932,370,3.231,372,4.669,381,5.774,389,3,392,4.041,398,4.669,402,4.352,417,3.442,418,4.46,449,4.22,454,2.49,459,2.806,460,7.34,463,4.978,474,7.437,501,4.422,518,6.914,534,4.669,535,4.669,536,4.669,540,4.978,541,4.978,542,4.217,543,5.741,544,15.049,546,15.049,547,7.782,548,4.669,554,3.628,555,9.625,556,5.391,557,5.391,558,10.834,559,7.782,560,10.834,561,2.806,564,4.978,565,9.581,566,9.581,567,11.756,568,4.978,569,4.978,572,7.782,573,7.782,574,2.932,575,4.978,576,7.782,577,4.978,578,4.978,580,7.782,581,4.978,582,4.978,583,4.978,584,4.978,585,4.978,586,4.978,587,4.978,588,4.978,589,7.782,590,4.978,591,4.978,592,4.978,593,7.782,594,4.978,595,4.978,596,3.623,597,4.978,598,7.782,599,4.978,601,4.978,604,4.978,605,6.476,608,3.331,613,2.691,619,4.041,622,10.162,623,3.909,624,1.288,625,2.638,626,3.516,627,3.516,628,4.978,629,6.983,630,2.239,631,6.019,632,6.019,633,9.625,634,7.782,635,2.691,636,6.019,637,3.516,638,3.628,639,6.019,640,6.019,641,6.019,642,4.978,643,11.734,644,3.072,645,6.019,646,6.019,647,5.391,648,5.391,649,8.429,650,6.019,651,9.41,652,6.019,653,6.019,654,6.019,655,6.019,656,6.019,657,6.019,658,6.019,659,6.019,660,6.019,661,6.019,662,6.019,663,6.019]],["keywords/14",[]],["title/15",[304,315.394,622,702.378,623,305.531]],["content/15",[45,4.515,53,2,67,5.116,100,2.373,104,2.539,142,2.297,143,3.637,145,1.992,153,2.191,184,3.074,185,3.019,219,5.195,223,2.834,242,4.428,245,3.418,303,7.397,304,6.521,306,6.588,307,2.092,308,2.51,309,3.975,315,4.26,317,3.975,319,2.928,328,2.949,333,4.725,345,6.293,347,6.421,351,7.927,352,9.018,353,3.852,357,3.957,358,3.635,365,4.426,367,3.212,370,3.54,372,5.116,386,3.212,392,4.428,398,5.116,402,4.569,417,5.031,418,2.539,449,3.953,454,2.728,483,2.373,501,4.846,518,7.42,534,5.116,535,5.116,536,5.116,543,2.261,544,10.15,546,14.776,547,10.15,548,5.116,555,4.846,558,11.374,559,8.352,560,11.374,561,3.074,562,5.454,564,5.454,565,10.15,566,10.15,567,12.262,568,5.454,569,5.454,572,8.352,573,5.454,574,3.212,575,5.454,576,8.352,577,5.454,578,5.454,580,8.352,581,5.454,582,5.454,583,5.454,584,5.454,585,5.454,586,5.454,587,5.454,588,5.454,589,8.352,590,5.454,591,5.454,592,5.454,593,8.352,594,5.454,595,5.454,596,3.888,597,5.454,598,8.352,599,5.454,601,5.454,604,5.454,605,6.721,608,4.345,613,2.949,619,4.428,622,10.669,623,5.003,625,2.89,626,3.852,629,3.975,630,2.454,642,5.454,643,12.319,644,3.366,647,5.907,648,5.907,649,9.046,664,3.975,665,4.11,666,6.595,667,5.454,668,5.116,669,4.621,670,4.846,671,6.595,672,4.621,673,5.907,674,5.454,675,2.539,676,4.846,677,6.595,678,12.273,679,6.595,680,3.074,681,10.1,682,6.595,683,10.1,684,6.595,685,6.595,686,6.595,687,6.595,688,6.595,689,6.595,690,6.595,691,6.595,692,6.595,693,6.595,694,6.595,695,6.595]],["keywords/15",[]],["title/16",[696,1066.856,697,572.688]],["content/16",[]],["keywords/16",[]],["title/17",[698,702.378,699,905.483,700,396.796]],["content/17",[208,5.487,236,10.623,319,2.824,402,4.549,404,5.365,406,11.326,412,11.733,701,9.595,702,9.595,703,10.062,704,11.326,705,12.266,706,9.595,707,10.093,708,10.623,709,10.436,710,10.623,711,10.623,712,10.623,713,10.623,714,10.623,715,13.695,716,13.695,717,12.991,718,10.623,719,13.695,720,5.272,721,3.222,722,13.695,723,7.351,724,13.695]],["keywords/17",[]],["title/18",[402,354.397,411,544.542]],["content/18",[18,3.632,154,5.272,319,2.069,382,5.272,402,5.737,412,12.958,496,8.98,596,5.548,669,10.096,709,11.525,710,11.178,711,11.178,712,11.178,713,11.178,714,11.178,725,4.436,726,4.787,727,14.411,728,14.411,729,12.908,730,14.411,731,14.411,732,14.411,733,14.411,734,14.411]],["keywords/18",[]],["title/19",[411,462.175,703,665.279,735,811.045]],["content/19",[86,1.54,319,2.657,334,10.747,402,5.386,411,6.633,412,11.359,460,6.329,496,8.098,596,6.804,703,13.991,709,10.103,710,10.08,711,10.08,712,10.08,713,10.08,714,10.08,717,10.08,723,6.976,736,12.995,737,12.995,738,12.995,739,9.772,740,12.995,741,7.832,742,9.548,743,8.393,744,5.81,745,8.098,746,12.995,747,12.995,748,9.548,749,10.08,750,12.995,751,12.995,752,12.995,753,12.995,754,12.995,755,12.995,756,12.995,757,12.995,758,12.995,759,12.995]],["keywords/19",[]],["title/20",[411,544.542,704,882.296]],["content/20",[7,2.539,11,4.461,20,2.115,54,3.033,66,2.586,86,0.754,91,2.634,115,3.033,131,4.349,156,5.924,170,4.788,208,2.981,245,1.239,294,8.72,305,3.331,312,2.082,319,2.97,353,7.013,357,3.851,358,3.94,368,5.265,377,2.906,402,5.123,409,5.25,411,3.25,412,10.223,460,3.101,474,3.331,482,4.461,496,3.967,507,4.461,550,7.625,596,2.451,629,3.837,675,4.622,700,5.916,701,9.459,702,6.887,703,7.222,704,12.067,709,8.413,710,7.625,711,7.625,712,7.625,713,7.625,714,7.625,717,4.939,725,1.96,729,5.703,739,3.837,743,4.112,745,6.125,748,9.92,749,4.939,760,5.703,761,3.967,762,6.367,763,6.367,764,2.684,765,5.703,766,2.451,767,6.367,768,6.367,769,6.367,770,6.367,771,6.367,772,6.367,773,6.367,774,6.367,775,2.684,776,12.006,777,6.367,778,9.796,779,6.367,780,13.501,781,6.367,782,6.367,783,6.367,784,4.461,785,6.367,786,9.83,787,4.275,788,6.367,789,5.703,790,6.367,791,6.367,792,6.367,793,5.703,794,3.611,795,13.501,796,9.313,797,3.101,798,2.02,799,3.611,800,6.367,801,3.967,802,3.967,803,6.367,804,12.093,805,9.83,806,9.83,807,5.703,808,5.703,809,4.678,810,5.703,811,7.222,812,9.83,813,12.006,814,6.367,815,12.006,816,6.367,817,9.83,818,9.83,819,14.591,820,4.144,821,6.367,822,3.837,823,5.703,824,6.367,825,8.129,826,3.101,827,3.25,828,4.939,829,6.367,830,9.83,831,9.83,832,6.367,833,2.736,834,6.348,835,6.367,836,6.367,837,5.703,838,6.367,839,12.006,840,6.367,841,6.367,842,6.367,843,6.367,844,6.367,845,6.367,846,4.678,847,6.367,848,6.367,849,6.367,850,6.367,851,4.939,852,6.367,853,6.367,854,6.367,855,9.83,856,6.367,857,6.367,858,9.83,859,6.367,860,6.367,861,6.367,862,5.265,863,6.367,864,6.367,865,6.367,866,6.367,867,6.367,868,6.367,869,6.367,870,6.367]],["keywords/20",[]],["title/21",[871,497.261,872,882.296]],["content/21",[]],["keywords/21",[]],["title/22",[721,163.547,873,510.763,874,317.262,875,695.177,876,695.177]],["content/22",[20,3.407,22,1.65,23,1.541,34,2.271,68,2.837,98,2.514,100,2.421,130,5.792,141,2.072,142,2.344,145,1.327,147,3.711,154,2.462,167,2.201,221,9.131,233,2.103,274,4.056,275,2.382,308,1.673,312,2.201,319,2.984,344,3.071,353,3.931,357,4.018,358,3.046,402,4.97,409,3.69,418,2.591,430,2.733,608,2.382,613,3.009,623,2.271,627,3.931,635,3.009,721,2.924,741,4.056,798,2.135,820,6.91,873,4.944,874,3.071,877,2.041,878,6.028,879,7.259,880,8.976,881,12.716,882,6.729,883,6.729,884,6.729,885,5.22,886,6.729,887,9.187,888,13.557,889,13.4,890,6.729,891,6.729,892,6.729,893,6.729,894,7.186,895,6.729,896,10.256,897,10.256,898,7.956,899,10.256,900,6.729,901,11.131,902,6.729,903,6.729,904,6.729,905,10.256,906,6.729,907,5.565,908,4.715,909,10.256,910,4.518,911,9.187,912,10.256,913,3.711,914,4.193,915,6.729,916,6.729,917,10.256,918,10.256,919,10.256,920,7.535,921,6.729,922,6.729,923,6.729,924,6.729,925,6.729,926,6.729,927,6.729,928,8.707,929,6.729,930,6.028,931,6.729,932,6.028,933,5.565,934,9.187,935,6.028,936,6.729,937,6.028,938,6.729,939,6.729,940,6.028,941,5.235,942,6.729,943,6.729,944,12.427,945,6.729,946,6.729,947,3.816,948,6.729,949,6.028,950,5.565,951,6.028,952,12.427,953,6.729,954,6.028,955,15.764,956,6.729,957,14.961,958,11.494,959,6.729,960,6.729,961,6.729,962,6.729,963,6.028,964,6.729,965,6.729,966,6.729,967,6.729,968,8.707,969,6.729,970,6.729,971,6.729,972,6.729,973,6.729,974,6.729,975,3.521,976,6.028,977,3.612,978,4.193,979,3.931,980,4.346,981,10.256,982,6.729,983,6.729,984,6.729,985,3.816,986,6.028,987,6.729]],["keywords/22",[]],["title/23",[402,300.791,721,213.024,988,665.279]],["content/23",[1,9.25,18,3.327,73,3.192,142,4.599,216,2.786,307,4.188,308,3.281,312,4.318,319,2.799,353,7.712,374,3.777,613,5.903,706,9.25,721,3.852,846,9.7,874,6.025,941,6.739,986,11.826,989,8.527,990,8.227,991,10.241,992,9.25,993,10.241,994,13.203,995,10.241,996,10.919,997,12.03,998,10.241,999,10.919,1000,9.25,1001,10.919,1002,13.203,1003,13.203,1004,10.919,1005,13.203,1006,18.609,1007,10.919,1008,13.203,1009,10.919,1010,13.203,1011,13.203]],["keywords/23",[]],["title/24",[289,354.397,1012,783.844]],["content/24",[13,2.686,18,1.514,22,2.304,79,3.682,108,2.486,131,1.935,135,2.06,145,1.185,154,3.438,160,2.686,170,2.926,191,2.862,208,1.822,223,4.038,229,3.067,233,1.878,239,1.433,252,2.995,282,9.076,305,3.143,307,1.906,319,2.906,357,6.165,358,1.473,402,4.718,411,3.067,417,3.438,418,2.313,456,2.093,499,2.027,574,5.636,596,3.618,624,1.285,625,5.071,672,4.209,675,2.313,720,2.313,721,3.341,723,7.025,725,1.85,760,5.382,764,2.533,766,2.313,799,3.407,820,3.961,822,5.663,846,4.414,871,2.8,872,4.969,874,8.466,877,1.822,881,4.661,941,5.907,990,8.155,991,11.017,992,4.209,993,11.017,995,8.976,996,7.771,997,11.064,1000,4.209,1004,7.771,1007,7.771,1009,7.771,1013,6.069,1014,7.77,1015,6.008,1016,6.62,1017,9.397,1018,7.888,1019,3.744,1020,3.313,1021,3.621,1022,4.661,1023,6.008,1024,4.969,1025,5.382,1026,4.661,1027,5.382,1028,4.661,1029,5.382,1030,5.382,1031,5.382,1032,11.572,1033,6.008,1034,6.008,1035,7.771,1036,5.382,1037,5.382,1038,9.397,1039,6.008,1040,9.397,1041,6.008,1042,9.397,1043,6.008,1044,9.397,1045,6.008,1046,5.382,1047,8.417,1048,4.661,1049,3.744,1050,4.969,1051,5.382,1052,5.382,1053,5.382,1054,4.661,1055,5.382,1056,5.382,1057,5.382,1058,5.382,1059,11.722,1060,5.382,1061,8.417,1062,5.382,1063,5.382,1064,5.382,1065,11.722,1066,5.382,1067,5.382,1068,5.382,1069,5.382,1070,5.382,1071,5.382,1072,8.417,1073,8.417,1074,8.417,1075,10.365,1076,5.382,1077,5.382,1078,5.382,1079,5.382,1080,5.382,1081,5.382,1082,5.382,1083,5.382,1084,5.382,1085,5.382,1086,5.382,1087,5.382,1088,4.414,1089,5.382,1090,4.414,1091,5.382,1092,5.382,1093,5.382,1094,8.417,1095,15.336,1096,15.336,1097,10.365,1098,4.209,1099,6.008,1100,6.008,1101,6.008,1102,6.008,1103,6.008,1104,9.397,1105,6.008,1106,6.008,1107,6.008,1108,5.382,1109,6.008,1110,6.008,1111,6.008,1112,5.382,1113,6.008,1114,6.008,1115,6.008,1116,6.008,1117,6.008,1118,5.382,1119,3.067,1120,4.661,1121,6.008,1122,4.209,1123,6.008,1124,6.008,1125,4.209,1126,4.661,1127,4.661,1128,5.382,1129,6.583,1130,5.382,1131,5.382,1132,5.382,1133,4.661]],["keywords/24",[]],["title/25",[109,374.625,350,374.625,720,302.794,1016,366.594]],["content/25",[22,1.694,86,0.819,116,2.239,125,3.588,145,1.363,167,2.261,179,2.529,216,1.459,229,3.528,233,2.16,282,9.6,305,3.616,307,2.193,319,2.938,336,2.859,357,6.482,358,1.694,402,4.196,404,2.708,417,3.829,456,2.408,499,2.332,574,5.098,624,1.479,638,4.166,720,4.03,721,3.315,723,5.619,799,3.92,820,4.412,822,6.309,827,3.528,874,8.247,881,5.362,941,6.448,990,6.522,991,8.119,992,4.843,993,8.119,997,11.703,1000,4.843,1004,8.656,1007,8.656,1009,8.656,1014,4.641,1016,6.568,1018,4.166,1024,5.716,1025,6.191,1026,5.362,1027,6.191,1028,5.362,1030,6.191,1031,6.191,1035,10.447,1036,6.191,1037,6.191,1046,6.191,1047,9.376,1048,5.362,1049,4.307,1050,5.716,1051,6.191,1052,6.191,1053,6.191,1054,5.362,1055,6.191,1056,6.191,1057,6.191,1058,6.191,1059,12.621,1060,6.191,1061,9.376,1062,6.191,1063,6.191,1064,6.191,1065,12.621,1066,6.191,1067,6.191,1068,6.191,1069,6.191,1070,6.191,1071,6.191,1072,9.376,1073,9.376,1074,9.376,1075,11.315,1076,6.191,1077,6.191,1078,6.191,1079,6.191,1080,6.191,1081,6.191,1082,6.191,1083,6.191,1084,6.191,1085,6.191,1086,6.191,1087,6.191,1089,6.191,1090,5.079,1091,6.191,1092,6.191,1093,6.191,1094,9.376,1095,15.929,1096,15.929,1097,9.376,1098,7.333,1108,6.191,1112,9.376,1129,4.843,1134,3.71,1135,3.029,1136,6.912,1137,5.079,1138,8.656,1139,6.912,1140,10.467,1141,6.912,1142,10.467,1143,6.912,1144,10.467,1145,6.912,1146,10.467,1147,6.912,1148,6.912,1149,6.912,1150,6.912,1151,6.912,1152,6.912,1153,6.912,1154,14.091,1155,6.912,1156,6.912,1157,6.912,1158,6.912,1159,6.912,1160,6.912,1161,6.912,1162,6.912,1163,4.307,1164,6.912,1165,4.307,1166,5.362]],["keywords/25",[]],["title/26",[524,371.602,1167,955.587]],["content/26",[22,2.781,49,7.328,79,4.445,98,2.781,135,3.889,141,3.493,160,5.073,191,7.081,212,3.599,216,2.394,239,3.545,250,5.655,308,2.82,404,4.445,418,4.368,596,4.368,605,4.875,625,6.514,673,10.163,675,4.368,720,6.383,721,4.297,723,9.445,766,4.368,872,12.294,874,8.03,990,9.263,991,8.801,993,8.801,995,8.801,997,8.336,1014,7.618,1016,8.513,1018,8.959,1021,6.838,1022,8.801,1098,7.949,1130,13.315,1131,13.315,1132,10.163,1133,8.801,1135,4.972,1165,9.263,1168,9.383,1169,6.838,1170,11.346,1171,11.346,1172,7.07,1173,11.346,1174,10.163,1175,7.949,1176,11.346,1177,6.434,1178,5.936,1179,8.336,1180,11.346,1181,7.07,1182,7.949,1183,10.415,1184,10.163,1185,3.828,1186,10.163,1187,11.346,1188,11.346,1189,4.445,1190,8.336]],["keywords/26",[]],["title/27",[1191,882.296,1192,827.555]],["content/27",[]],["keywords/27",[]],["title/28",[1193,955.587,1194,783.844]],["content/28",[22,1.332,57,5.818,66,3.526,68,2.291,73,2.099,96,5.607,98,1.332,100,5.658,108,2.249,114,3.649,119,4.216,125,3.716,135,1.863,138,6.082,141,2.673,145,1.712,153,2.884,154,1.988,170,2.647,179,1.988,190,2.754,206,2.589,239,1.296,245,1.689,300,2.382,307,1.724,319,2.726,324,3.994,347,7.92,358,3.536,374,1.555,402,5.223,409,5.658,415,10.889,422,6.644,447,4.032,449,2.796,456,1.893,492,3.511,499,3.657,508,2.481,510,9.601,596,4.765,613,2.43,625,3.804,629,5.232,630,3.23,635,3.881,644,2.774,721,3.814,725,2.673,726,1.806,739,9.124,794,4.923,820,6.08,877,1.649,898,6.734,941,6.317,950,10.236,989,3.511,1134,2.918,1135,2.382,1137,3.994,1166,4.216,1185,1.834,1191,8.964,1192,11.188,1193,4.869,1194,13.595,1195,4.216,1196,4.869,1197,4.869,1198,2.918,1199,2.997,1200,5.436,1201,4.869,1202,9.709,1203,8.682,1204,4.495,1205,3.994,1206,4.495,1207,8.682,1208,6.734,1209,5.436,1210,5.436,1211,5.436,1212,4.869,1213,5.436,1214,5.436,1215,4.216,1216,3.511,1217,11.928,1218,10.105,1219,8.964,1220,10.494,1221,3.511,1222,4.216,1223,2.844,1224,3.276,1225,3.649,1226,4.869,1227,4.869,1228,4.869,1229,5.436,1230,4.869,1231,4.869,1232,4.869,1233,5.436,1234,5.436,1235,5.436,1236,4.869,1237,4.869,1238,4.869,1239,8.682,1240,7.776,1241,7.776,1242,7.776,1243,7.776,1244,7.776,1245,7.18,1246,5.436,1247,7.776,1248,7.776,1249,8.682,1250,8.682,1251,6.734,1252,8.682,1253,8.682,1254,4.869,1255,4.869,1256,3.994,1257,10.839,1258,5.769,1259,7.776,1260,3.808,1261,7.18,1262,4.869,1263,8.964,1264,3.276,1265,9.709,1266,3.994,1267,12.377,1268,8.682,1269,6.379,1270,8.682,1271,5.436,1272,7.776,1273,5.436,1274,7.18,1275,7.776,1276,8.682,1277,8.682,1278,8.682,1279,7.776,1280,5.436,1281,5.436,1282,8.682,1283,7.46,1284,3.66,1285,7.776,1286,4.495,1287,3.994,1288,5.436,1289,4.495,1290,3.511,1291,5.436,1292,3.649,1293,6.331,1294,5.436,1295,4.869,1296,4.869,1297,4.869,1298,8.682,1299,7.776,1300,5.436,1301,7.776,1302,4.869,1303,5.436,1304,5.436,1305,5.436,1306,3.808,1307,3.387,1308,3.276,1309,4.869,1310,5.436]],["keywords/28",[]],["title/29",[1311,715.826]],["content/29",[22,3.343,25,6.961,57,7.321,68,5.749,125,4.675,201,8.498,209,8.808,239,3.253,252,6.797,381,6.797,456,4.75,508,6.224,526,5.439,624,2.917,721,3.93,739,10.068,833,5.86,1189,5.343,1190,10.02,1192,12.958,1194,12.273,1195,12.958,1208,10.579,1217,11.279,1218,9.555,1219,11.279,1220,10.579,1289,11.279,1308,8.22,1312,13.638,1313,11.279,1314,10.579,1315,5.976,1316,9.157,1317,13.638,1318,11.279,1319,7.966,1320,6.961]],["keywords/29",[]],["title/30",[1195,827.555,1321,783.844]],["content/30",[3,3.186,18,0.701,20,0.924,21,1.13,22,1.967,23,1.129,25,2.516,34,1.663,57,1.494,58,1.734,68,1.173,73,0.673,74,1.898,86,1.301,89,1.22,91,1.151,95,2.971,96,1.797,98,0.682,100,1.001,110,1.456,116,1.054,117,1.869,125,0.954,127,3.093,135,2.275,140,1.387,141,1.518,142,0.969,145,0.549,147,1.535,158,4.135,167,3.001,184,1.297,188,3.662,190,0.883,195,1.734,208,4.052,209,1.797,215,2.298,218,5.943,219,0.924,229,1.421,233,2.074,239,2.789,245,0.959,249,4.285,250,3.999,255,2.159,256,1.966,275,0.985,279,1.95,299,1.626,300,1.22,308,0.692,309,1.677,312,2.17,316,1.22,319,2.842,328,1.244,333,1.071,344,2.25,346,3.516,347,8.202,357,1.09,358,3.565,365,2.16,370,5.447,389,1.387,402,4.092,409,5.723,415,10.073,417,1.803,422,7.406,431,1.22,444,4.649,447,2.468,449,2.584,451,3.454,456,1.717,459,3.093,474,2.579,481,1.421,483,1.774,492,3.184,499,1.663,508,1.27,510,6.224,561,1.297,574,3.232,596,3.906,624,1.054,626,1.626,627,2.879,630,1.035,637,1.626,669,1.95,670,2.045,672,1.95,680,1.297,701,1.95,702,1.95,707,5.53,718,2.159,721,3.567,725,2.47,726,0.924,739,8.052,761,1.734,764,3.382,766,6.28,794,1.578,797,1.356,798,0.883,801,1.734,802,1.734,820,4.627,834,3.184,862,2.302,874,1.27,914,1.734,941,6.288,947,1.578,950,8.391,968,3.454,977,1.494,989,3.184,1019,5.718,1021,2.971,1026,2.159,1028,2.159,1050,2.302,1054,2.159,1129,1.95,1135,1.22,1137,7.455,1167,2.493,1172,1.734,1175,1.95,1185,0.939,1189,1.09,1190,2.045,1191,10.188,1192,3.824,1194,4.875,1195,6.224,1196,9.088,1197,9.088,1199,2.718,1202,4.415,1208,2.159,1217,11.049,1218,10.19,1219,7.588,1220,7.871,1224,1.677,1226,4.415,1227,2.493,1228,2.493,1230,2.493,1231,7.187,1232,4.415,1236,2.493,1237,2.493,1238,2.493,1240,7.187,1241,8.219,1242,7.187,1243,7.187,1244,8.219,1245,6.636,1247,7.187,1248,7.187,1254,2.493,1255,2.493,1256,2.045,1258,5.116,1259,4.415,1260,1.95,1261,4.077,1262,2.493,1263,2.302,1265,7.187,1266,2.045,1269,7.455,1272,9.088,1274,4.077,1275,9.088,1279,9.088,1283,4.836,1285,2.493,1286,2.302,1293,3.876,1295,2.493,1296,2.493,1297,2.493,1299,4.415,1301,4.415,1302,2.493,1309,5.943,1311,1.535,1319,1.626,1321,4.875,1322,4.573,1323,2.783,1324,4.93,1325,2.783,1326,2.783,1327,2.783,1328,2.971,1329,2.971,1330,6.635,1331,2.783,1332,2.045,1333,1.11,1334,1.677,1335,2.159,1336,2.783,1337,2.302,1338,3.184,1339,11.694,1340,2.159,1341,2.493,1342,2.783,1343,2.783,1344,2.783,1345,2.783,1346,1.326,1347,2.159,1348,7.957,1349,1.535,1350,2.579,1351,2.783,1352,2.783,1353,2.783,1354,2.783,1355,2.783,1356,2.783,1357,2.783,1358,4.93,1359,2.783,1360,2.783,1361,8.024,1362,10.147,1363,10.147,1364,11.035,1365,10.147,1366,2.783,1367,10.147,1368,10.147,1369,3.184,1370,4.93,1371,4.93,1372,1.626,1373,3.072,1374,2.783,1375,2.159,1376,2.745,1377,2.783,1378,2.493,1379,2.302,1380,1.626,1381,2.783,1382,2.783,1383,2.783,1384,2.783,1385,2.783,1386,4.93,1387,2.783,1388,4.93,1389,2.783,1390,4.93,1391,2.783,1392,2.045,1393,4.93,1394,2.302,1395,1.456,1396,2.493,1397,2.783,1398,2.493,1399,1.677,1400,2.302,1401,3.31,1402,1.834,1403,3.622,1404,2.783,1405,4.93,1406,2.783,1407,2.783,1408,2.783,1409,1.869,1410,2.045,1411,2.783,1412,1.95,1413,2.493,1414,2.783,1415,2.783,1416,2.302,1417,2.783,1418,6.635,1419,4.93,1420,2.783,1421,4.415,1422,2.783,1423,2.783,1424,4.93,1425,2.783,1426,2.783,1427,2.783,1428,2.783,1429,7.187,1430,2.302,1431,2.783,1432,1.151,1433,2.045,1434,2.159,1435,2.493,1436,1.95,1437,1.95,1438,3.454,1439,1.677,1440,1.535,1441,2.783,1442,2.159,1443,2.783,1444,2.302,1445,1.95,1446,2.493,1447,1.869,1448,2.493,1449,2.783,1450,4.93,1451,2.783,1452,2.783,1453,4.93,1454,2.783,1455,2.783,1456,4.93,1457,2.783,1458,2.783,1459,4.93,1460,2.783,1461,2.783,1462,6.635,1463,1.869,1464,2.159,1465,2.783,1466,2.745,1467,2.783,1468,6.635,1469,2.783,1470,4.93,1471,4.93,1472,2.783,1473,2.783,1474,2.783,1475,2.783,1476,4.415,1477,1.421,1478,4.93,1479,2.783,1480,4.93,1481,2.493,1482,2.783,1483,2.783,1484,2.783,1485,2.783,1486,2.783,1487,2.783,1488,2.783,1489,4.93,1490,8.024,1491,4.93,1492,2.783,1493,2.493,1494,2.783,1495,2.783,1496,2.783,1497,2.783,1498,2.783,1499,2.783,1500,1.95,1501,2.783,1502,7.117,1503,2.783,1504,2.783,1505,2.783,1506,2.783]],["keywords/30",[]],["title/31",[115,431.291,1165,564.238,1507,905.483]],["content/31",[]],["keywords/31",[]],["title/32",[1307,564.238,1508,811.045,1509,607.94]],["content/32",[3,2.465,6,4.558,19,4.816,34,4.807,73,2.053,86,1.006,98,2.082,104,3.269,115,8.171,145,2.81,147,4.682,160,5.447,190,3.865,215,3.958,216,3.729,219,2.821,245,2.371,275,3.006,299,4.96,306,8.847,312,2.777,316,3.721,319,2.366,346,3.721,358,3.493,376,5.118,382,5.212,416,3.958,417,3.106,430,3.449,447,3.159,460,5.934,499,2.865,543,2.911,552,7.606,619,5.701,624,1.816,720,5.993,723,4.558,725,3.75,726,2.821,766,6.802,894,5.949,1018,5.118,1127,6.587,1134,4.558,1165,11.639,1185,2.865,1189,3.327,1223,4.443,1307,5.291,1319,4.96,1322,4.232,1402,3.159,1416,10.075,1466,3.513,1509,5.701,1510,6.587,1511,4.558,1512,8.492,1513,8.492,1514,8.492,1515,8.492,1516,8.492,1517,5.118,1518,11.01,1519,7.606,1520,9.45,1521,8.492,1522,8.827,1523,8.492,1524,8.492,1525,8.322,1526,5.701,1527,11.437,1528,8.492,1529,8.492,1530,7.606,1531,12.183,1532,17.154,1533,8.492,1534,4.682,1535,5.484,1536,8.492,1537,7.606,1538,7.606,1539,8.492,1540,8.492,1541,8.492,1542,12.183,1543,15.566,1544,8.492,1545,15.566,1546,8.492,1547,8.492,1548,8.492,1549,8.492,1550,12.183,1551,8.492,1552,8.492,1553,8.492,1554,8.492,1555,8.492,1556,4.045,1557,7.606,1558,5.701,1559,7.606,1560,8.492,1561,8.492,1562,7.606]],["keywords/32",[]],["title/33",[499,359.982,1563,827.555]],["content/33",[11,9.576,34,3.377,86,1.186,104,3.853,108,4.14,135,3.43,145,3.299,179,3.661,208,3.035,216,3.695,219,3.324,239,2.387,286,5.675,299,5.846,300,4.385,306,9.932,308,2.487,333,3.853,358,3.351,365,4.385,374,3.911,376,6.031,381,4.988,382,3.661,447,3.723,459,4.664,460,8.147,474,5.236,492,6.463,499,3.377,543,3.43,624,2.924,635,4.474,675,3.853,680,4.664,720,6.741,725,3.081,726,3.324,743,6.463,744,4.474,745,8.517,761,6.236,766,6.44,1016,4.664,1018,8.238,1165,10.912,1199,5.518,1223,5.236,1333,3.991,1372,5.846,1402,3.723,1416,11.303,1466,4.14,1517,8.238,1518,11.529,1522,5.675,1525,5.846,1526,6.719,1527,7.353,1537,8.964,1564,8.964,1565,4.767,1566,6.463,1567,10.007,1568,10.007,1569,8.276,1570,10.007,1571,5.108,1572,8.964,1573,10.007,1574,7.763,1575,10.007,1576,7.763,1577,10.007,1578,6.657,1579,10.007,1580,8.964,1581,10.007,1582,13.668,1583,6.812,1584,7.763,1585,8.276,1586,10.007,1587,8.964,1588,10.007,1589,8.276,1590,6.463]],["keywords/33",[]],["title/34",[289,354.397,304,371.602]],["content/34",[3,1.634,18,1.419,22,2.719,23,2.89,34,1.9,49,5.766,73,3.328,86,0.667,89,2.467,100,2.026,102,4.656,116,1.91,124,1.611,125,1.93,141,2.748,145,2.188,153,1.87,156,3.393,185,1.683,212,1.786,216,2.664,219,4.866,239,1.343,265,2.094,266,2.569,289,2.966,299,3.289,304,5.102,305,5.804,306,6.777,307,4.005,308,1.399,312,1.841,319,2.907,344,4.074,353,6.48,357,2.206,358,3.095,365,3.912,374,2.554,382,4.058,389,2.806,402,3.685,404,2.206,417,2.06,447,4.127,451,6.255,454,5.694,459,5.171,460,5.403,483,2.026,496,3.508,498,7.383,596,2.167,608,1.993,644,2.874,668,4.367,675,5.299,701,6.255,706,3.944,720,5.299,721,1.324,725,2.748,726,2.966,744,4.96,745,5.563,766,6.313,796,10.678,798,1.786,833,2.419,871,2.624,877,1.708,1019,3.508,1035,4.656,1138,4.656,1165,5.563,1185,1.9,1205,4.136,1223,4.671,1264,6.686,1266,6.559,1315,2.467,1320,2.874,1376,2.329,1402,2.094,1433,8.151,1508,5.043,1509,7.448,1511,4.792,1518,11.899,1522,6.291,1527,6.559,1557,7.996,1565,2.682,1587,5.043,1590,11.933,1591,5.63,1592,3.193,1593,3.763,1594,5.63,1595,3.78,1596,5.63,1597,5.63,1598,11.094,1599,5.043,1600,3.636,1601,5.043,1602,5.63,1603,5.63,1604,5.63,1605,7.996,1606,7.996,1607,11.308,1608,5.63,1609,3.78,1610,5.043,1611,5.043,1612,4.367,1613,6.925,1614,5.043,1615,6.925,1616,9.936,1617,5.63,1618,3.393,1619,5.63,1620,5.63,1621,5.63,1622,5.63,1623,6.559,1624,5.043,1625,5.63,1626,5.63,1627,5.043,1628,5.63,1629,5.63,1630,3.78,1631,7.996,1632,14.647,1633,8.928,1634,9.936,1635,8.928,1636,7.996,1637,5.63,1638,5.63,1639,5.043,1640,11.308,1641,8.928,1642,5.63,1643,5.63,1644,5.63,1645,5.63,1646,5.63,1647,5.63,1648,5.63,1649,5.63,1650,5.63,1651,5.63,1652,5.63,1653,5.63,1654,5.63,1655,5.63,1656,5.63,1657,8.928,1658,8.928,1659,7.996,1660,5.043,1661,8.928,1662,5.63,1663,5.63,1664,5.63,1665,4.656,1666,5.63,1667,5.043,1668,5.63,1669,5.63,1670,5.63]],["keywords/34",[]],["title/35",[1172,808.967]],["content/35",[16,6.305,22,4.074,23,3.097,102,11.187,109,6.443,124,3.87,201,8.429,216,2.855,232,9.938,233,5.194,239,3.226,250,8.284,308,3.362,344,6.173,359,7.901,382,4.948,454,5.596,460,6.588,484,6.742,700,5.928,720,5.208,726,4.493,745,8.429,871,6.305,1020,7.458,1165,10.357,1216,8.736,1223,7.077,1509,12.6,1518,11.212,1590,8.736,1671,12.116,1672,10.493,1673,9.477,1674,13.527,1675,12.116]],["keywords/35",[]],["title/36",[333,348.594,1676,584.8,1677,905.483]],["content/36",[49,10.051,115,7.413,216,3.284,619,10.449,635,6.958,999,12.871,1165,9.698,1518,9.698,1678,13.94,1679,9.698,1680,15.563,1681,15.563,1682,15.563]],["keywords/36",[]],["title/37",[86,93.195,1518,490.104,1527,577.87,1590,507.965]],["content/37",[]],["keywords/37",[]],["title/38",[1683,827.555,1684,882.296]],["content/38",[3,3.984,18,2.537,20,3.345,22,2.468,34,3.397,48,5.551,53,4.163,73,2.434,77,6.068,79,3.945,100,4.938,134,4.165,141,3.1,142,3.507,145,2.707,153,3.345,154,3.683,160,4.501,170,4.904,172,8.326,190,3.194,216,3.295,223,4.326,245,1.959,289,3.345,297,7.397,307,3.194,336,4.165,342,7.054,358,3.364,359,5.881,374,4.468,418,5.284,460,6.685,554,6.068,555,7.397,596,3.876,605,4.326,723,5.405,725,5.402,745,6.274,766,7.261,796,14.047,798,4.354,871,4.693,874,6.263,877,3.054,1134,5.405,1165,6.274,1185,4.631,1189,3.945,1293,8.017,1308,6.068,1320,5.139,1432,4.165,1517,6.068,1518,11.919,1527,10.084,1590,10.085,1600,6.502,1609,6.76,1685,5.71,1686,5.881,1687,13.724,1688,13.724,1689,9.018,1690,8.326,1691,12.293,1692,10.068,1693,11.472,1694,10.068,1695,6.76,1696,5.881,1697,5.881,1698,13.724,1699,6.76,1700,10.068,1701,10.068,1702,7.81,1703,7.397,1704,6.068]],["keywords/38",[]],["title/39",[289,354.397,304,371.602]],["content/39",[3,3.915,20,2.111,23,1.455,104,2.446,116,2.1,124,1.818,141,1.956,142,2.213,145,1.253,167,3.21,190,2.016,208,4.422,216,2.071,219,2.111,222,2.785,233,1.986,249,4.104,250,3.167,304,2.213,307,2.016,319,2.967,353,5.733,358,4.34,370,5.269,374,1.818,389,3.167,402,4.843,409,5.246,417,2.325,430,2.581,460,3.095,483,4.853,526,2.534,574,3.095,596,2.446,624,1.359,675,4.617,706,4.452,707,5.915,709,6.116,720,2.446,721,2.309,725,1.956,726,2.111,748,4.669,766,3.779,787,8.051,801,3.96,802,3.96,820,6.145,874,2.9,898,4.929,992,4.452,998,4.929,1018,3.83,1138,5.255,1178,3.325,1182,4.452,1264,5.915,1320,3.243,1328,3.83,1329,3.83,1372,3.712,1376,2.629,1433,8.811,1518,11.031,1522,7.649,1590,10.374,1601,5.692,1605,10.741,1606,13.058,1607,8.791,1613,7.613,1614,5.692,1615,7.613,1616,5.692,1623,4.669,1624,5.692,1627,5.692,1631,10.741,1634,10.741,1636,8.791,1639,5.692,1640,5.692,1660,5.692,1667,5.692,1671,5.692,1705,3.712,1706,2.9,1707,5.255,1708,4.452,1709,3.095,1710,4.266,1711,4.929,1712,3.095,1713,6.355,1714,6.355,1715,3.96,1716,5.692,1717,4.669,1718,4.669,1719,6.355,1720,4.669,1721,3.83,1722,6.355,1723,6.355,1724,6.355,1725,6.355,1726,9.815,1727,6.355,1728,6.355,1729,6.355,1730,6.355,1731,14.578,1732,9.815,1733,9.815,1734,6.355,1735,6.355,1736,6.355,1737,9.815,1738,6.355,1739,6.355,1740,6.355,1741,11.992,1742,6.355,1743,6.355,1744,6.355,1745,6.355,1746,9.815,1747,6.355,1748,5.255,1749,5.255,1750,6.355,1751,9.815,1752,9.815,1753,6.355,1754,9.815,1755,6.355,1756,6.355,1757,6.355,1758,6.355,1759,6.355,1760,6.355,1761,5.692,1762,6.355,1763,14.578,1764,6.355,1765,6.355,1766,9.815,1767,6.355,1768,9.815,1769,6.355,1770,6.355,1771,6.355,1772,6.355,1773,6.355,1774,6.355,1775,9.815,1776,6.355,1777,4.929,1778,6.355,1779,6.355,1780,6.355,1781,5.255]],["keywords/39",[]],["title/40",[73,218.94,499,305.531,1782,441.023]],["content/40",[3,1.877,18,3.055,22,1.585,34,3.357,48,7.506,68,2.726,73,1.564,74,2.489,77,3.897,90,8.91,100,2.327,119,5.016,125,3.41,134,2.675,135,2.217,136,4.029,141,1.991,145,2.391,153,2.148,162,3.223,167,4.452,185,1.933,190,4.318,191,3.08,212,3.156,219,2.148,223,2.779,239,3.247,241,5.348,245,1.936,260,4.176,300,2.834,307,4.318,308,1.607,312,2.115,319,1.74,328,2.891,333,2.489,342,10.295,346,2.834,347,5.205,358,2.439,374,1.85,382,2.366,402,2.148,409,2.327,431,4.359,449,2.083,456,2.252,460,7.873,474,3.383,483,2.327,496,8.482,499,4.958,514,3.897,524,3.465,525,4.176,526,3.967,561,5.651,596,5.657,605,2.779,627,3.777,635,2.891,644,6.188,675,2.489,697,3.471,698,5.016,720,3.83,721,1.521,723,6.508,725,1.991,726,2.148,766,6.223,775,6.194,796,5.016,798,2.051,799,3.667,826,3.149,871,3.014,877,1.961,985,3.667,1024,5.348,1122,4.53,1127,5.016,1129,4.53,1135,4.359,1163,4.029,1166,5.016,1185,2.182,1199,3.565,1261,10.026,1263,5.348,1284,2.726,1287,4.751,1293,3.777,1308,3.897,1315,2.834,1333,4.835,1346,3.08,1350,6.343,1364,8.91,1369,4.176,1376,2.675,1379,5.348,1401,4.341,1440,3.565,1509,8.14,1518,4.029,1564,5.792,1569,5.348,1584,5.016,1590,10.776,1693,11.876,1749,5.348,1781,12.833,1783,12.124,1784,6.97,1785,6.466,1786,6.466,1787,6.466,1788,9.948,1789,9.948,1790,6.466,1791,12.124,1792,13.899,1793,12.124,1794,12.124,1795,15.517,1796,6.466,1797,12.124,1798,12.124,1799,10.859,1800,5.792,1801,6.466,1802,6.466,1803,5.016,1804,12.124,1805,6.466,1806,8.791,1807,4.53,1808,6.466,1809,5.016,1810,4.53,1811,6.466,1812,6.466,1813,6.466,1814,6.466,1815,6.466,1816,6.466,1817,6.466,1818,6.466,1819,6.466,1820,6.466,1821,4.637,1822,6.466,1823,6.466,1824,10.859,1825,6.466,1826,6.466,1827,6.466,1828,6.466,1829,6.466,1830,6.466,1831,6.466,1832,6.466,1833,5.348,1834,6.466,1835,6.466,1836,6.466,1837,4.53,1838,4.751,1839,4.751,1840,6.466,1841,6.466,1842,6.466,1843,6.466,1844,5.348,1845,6.466,1846,3.667,1847,6.466]],["keywords/40",[]],["title/41",[109,374.625,250,392.002,1172,490.104,1848,551.044]],["content/41",[3,4.661,58,7.973,62,10.37,109,6.094,124,3.661,135,4.386,137,6.094,167,5.252,233,3.998,250,6.377,275,4.529,289,4.25,304,4.456,317,7.711,342,11.249,347,6.694,449,4.121,483,5.777,499,5.418,526,6.404,624,2.737,630,4.76,675,4.926,698,9.924,720,4.926,721,3.01,725,3.939,990,7.973,1122,8.964,1134,6.868,1183,8.964,1185,4.317,1224,7.711,1283,7.711,1284,5.393,1333,5.103,1341,11.46,1373,7.973,1433,9.4,1509,10.78,1590,8.263,1676,8.263,1849,11.46,1850,12.794,1851,9.924,1852,12.794,1853,12.794,1854,5.607,1855,12.794,1856,11.46,1857,10.581]],["keywords/41",[]],["title/42",[152,507.965,1016,366.594,1858,786.514,1859,551.044]],["content/42",[]],["keywords/42",[]],["title/43",[206,508.154,721,250.988]],["content/43",[3,3.78,8,4.65,18,2.351,22,2.287,23,3.434,73,3.149,86,1.106,91,3.86,110,4.881,116,1.996,124,4.292,135,3.198,142,3.25,145,1.84,152,11.029,167,3.052,203,7.237,208,4.924,209,6.026,212,2.96,216,3.166,229,4.762,233,2.916,239,2.225,245,1.815,256,3.721,275,3.303,289,3.099,308,3.237,309,5.623,312,5.586,319,2.539,333,3.592,346,4.088,357,3.655,358,3.677,382,3.413,386,4.544,405,7.716,409,3.357,458,5.814,474,4.881,483,3.357,484,4.65,629,5.623,669,6.537,707,7.848,720,3.592,721,4.018,739,5.623,801,5.814,802,5.814,871,4.349,877,2.83,880,8.41,977,5.008,978,5.814,1016,6.992,1021,5.623,1134,5.008,1169,5.623,1185,3.148,1205,6.855,1258,4.349,1289,7.716,1315,4.088,1328,5.623,1329,5.623,1337,7.716,1347,7.237,1395,6.813,1412,6.537,1437,6.537,1445,6.537,1447,6.264,1466,3.86,1717,6.855,1718,6.855,1720,6.855,1721,5.623,1839,6.855,1859,6.537,1860,9.33,1861,7.237,1862,7.237,1863,6.855,1864,9.33,1865,7.716,1866,5.623,1867,9.33,1868,9.33,1869,9.33,1870,9.33,1871,9.33,1872,9.33,1873,9.33,1874,9.33,1875,9.33,1876,9.33,1877,11.664,1878,8.357,1879,8.357,1880,6.537,1881,9.33,1882,9.33,1883,9.33,1884,9.33,1885,9.33,1886,7.716,1887,5.623,1888,9.33,1889,13.022,1890,8.41,1891,8.357,1892,5.144,1893,7.716]],["keywords/43",[]],["title/44",[56,388.117,358,152.685,1894,457.62,1895,557.886,1896,284.252,1897,515.098]],["content/44",[13,3.777,18,3.059,19,4.791,23,1.934,56,5.264,73,3.435,79,3.31,100,3.04,104,3.252,125,2.896,145,1.666,152,11.06,164,3.702,167,3.97,180,5.456,184,3.938,188,3.856,190,2.68,191,6.767,198,4.658,208,2.562,239,2.015,274,5.092,286,4.791,307,2.68,319,2.804,357,6.444,358,3.483,382,3.091,389,4.211,416,3.938,418,3.252,449,3.91,451,5.919,453,4.535,454,3.495,456,4.228,499,2.851,524,2.943,605,3.63,608,2.991,672,5.919,680,3.938,701,5.919,721,3.87,725,2.601,761,5.264,775,3.561,1016,6.622,1098,10.88,1126,6.553,1134,4.535,1135,5.319,1137,6.207,1185,2.851,1223,4.42,1258,3.938,1315,3.702,1439,9.36,1447,5.672,1466,3.495,1556,4.024,1706,5.539,1810,5.919,1821,3.938,1866,7.316,1879,10.872,1880,8.504,1887,7.316,1896,6.483,1897,10.038,1898,5.919,1899,8.448,1900,12.138,1901,8.448,1902,8.448,1903,4.935,1904,8.448,1905,8.448,1906,12.138,1907,10.872,1908,12.138,1909,7.567,1910,12.138,1911,4.935,1912,8.448,1913,8.448,1914,8.448,1915,8.448,1916,8.448,1917,8.448,1918,8.448,1919,8.448,1920,8.448,1921,8.448,1922,8.448,1923,7.567,1924,8.448,1925,7.567,1926,8.448,1927,8.448,1928,8.448,1929,8.448,1930,12.138,1931,8.448,1932,8.448,1933,6.207,1934,8.448,1935,14.206,1936,8.448,1937,8.448,1938,8.448,1939,8.448,1940,7.567,1941,8.448,1942,8.448,1943,8.448,1944,8.448,1945,8.448,1946,8.448,1947,10.872,1948,8.448,1949,8.448,1950,8.448,1951,8.448,1952,6.553,1953,7.567,1954,6.553,1955,7.567]],["keywords/44",[]],["title/45",[56,433.189,608,246.084,1894,510.763,1895,622.673,1956,622.673]],["content/45",[20,3.988,22,3.31,27,2.906,41,2.847,56,10.016,57,3.418,58,3.967,62,4.112,64,3.033,73,2.377,77,5.924,81,3.418,86,1.729,89,2.79,98,3.31,104,2.451,125,2.183,141,3.696,142,2.218,145,1.939,153,2.115,164,2.79,184,2.968,208,2.981,212,2.02,219,3.988,232,4.678,233,3.072,239,1.518,245,1.239,250,3.173,289,2.115,307,3.118,308,2.443,312,3.215,315,4.112,319,2.446,333,2.451,346,4.307,358,2.41,377,2.906,381,3.173,389,3.173,402,3.265,413,4.461,431,2.79,447,3.657,453,5.276,457,5.703,458,10.016,499,2.148,554,3.837,561,4.582,596,2.451,635,4.395,637,3.719,721,2.825,725,1.96,726,3.265,775,5.691,797,4.788,810,5.703,820,4.144,827,3.25,871,2.968,880,6.348,908,6.887,1014,4.275,1016,6.293,1020,3.511,1098,4.461,1126,4.939,1163,6.125,1175,4.461,1185,4.556,1222,4.939,1258,6.293,1283,3.837,1320,3.25,1372,3.719,1376,2.634,1402,2.369,1409,4.275,1410,7.222,1439,9.294,1447,6.6,1466,4.066,1556,3.033,1609,4.275,1706,2.906,1800,5.703,1838,4.678,1854,2.79,1861,4.939,1866,3.837,1877,5.703,1887,5.924,1893,9.929,1894,9.92,1896,5.479,1897,5.265,1907,5.703,1940,8.804,1947,15.259,1954,4.939,1955,5.703,1956,8.804,1957,6.367,1958,9.83,1959,9.83,1960,6.367,1961,6.367,1962,9.83,1963,5.703,1964,6.367,1965,5.703,1966,6.125,1967,5.265,1968,6.367,1969,3.611,1970,4.939,1971,6.367,1972,14.591,1973,6.367,1974,6.367,1975,6.367,1976,4.939,1977,4.275,1978,9.83,1979,9.83,1980,6.367,1981,3.837,1982,5.703,1983,9.96,1984,6.367,1985,4.678,1986,5.703,1987,5.703,1988,4.461,1989,6.367,1990,12.006,1991,5.703,1992,6.367,1993,6.367,1994,12.006,1995,9.83,1996,9.83,1997,6.367,1998,9.83,1999,9.83,2000,9.83,2001,13.501,2002,9.83,2003,8.804,2004,9.83,2005,9.83,2006,9.83,2007,9.83,2008,9.83,2009,9.83,2010,9.83,2011,13.501,2012,9.83,2013,9.83,2014,8.804,2015,9.83,2016,6.367,2017,5.265,2018,9.83,2019,5.703,2020,4.461,2021,5.703,2022,6.367,2023,3.719,2024,6.367,2025,6.367,2026,3.033,2027,4.461,2028,4.678]],["keywords/45",[]],["title/46",[358,221.971,766,348.594,1172,564.238]],["content/46",[3,3.671,22,3.908,34,4.268,56,7.881,62,8.168,74,4.869,86,1.499,98,3.1,100,5.736,125,4.336,152,10.295,198,6.974,219,4.201,233,4.981,239,3.016,244,8.491,245,3.102,260,8.168,280,11.328,289,4.201,315,8.168,319,1.816,430,5.136,458,7.881,459,5.895,526,5.044,625,5.542,721,3.75,775,5.331,797,6.16,799,7.172,1016,5.895,1022,9.811,1168,10.46,1178,6.617,1190,9.292,1222,9.811,1283,7.623,1509,8.491,1565,6.024,1865,10.46,1866,7.623,1880,8.861,1909,11.328,2020,8.861,2029,11.712,2030,8.861,2031,12.647,2032,12.647,2033,12.647,2034,12.647,2035,9.811,2036,12.647,2037,12.647,2038,12.647]],["keywords/46",[]],["title/47",[1863,953.834]],["content/47",[86,1.761,116,3.18,208,4.508,319,2.69,389,7.408,721,4.409,1862,11.53,2039,14.864,2040,14.864,2041,17.593,2042,14.864,2043,13.314,2044,14.864,2045,14.864,2046,14.864,2047,14.864,2048,14.864,2049,14.864]],["keywords/47",[]],["title/48",[2050,909.555]],["content/48",[]],["keywords/48",[]],["title/49",[833,557.854]],["content/49",[3,3.671,20,4.201,22,3.1,23,3.649,86,1.889,91,5.232,111,8.168,130,7.43,145,2.494,185,4.764,245,2.461,265,4.705,308,3.143,316,8.03,346,5.542,374,3.619,404,6.839,665,7.881,672,11.168,877,3.836,1019,7.881,1179,11.712,1189,4.955,1220,12.365,1559,11.328,1821,8.542,2050,11.168,2051,9.811,2052,9.811,2053,15.623,2054,12.647,2055,12.647,2056,12.647,2057,10.46,2058,11.328,2059,12.647,2060,15.155,2061,11.328,2062,12.647]],["keywords/49",[]],["title/50",[721,305.42]],["content/50",[3,4.201,86,2.275,116,3.096,179,5.295,185,4.326,233,4.523,265,5.384,294,9.348,353,8.454,798,4.592,1134,7.769,1189,5.671,1283,8.723,1284,6.101,1372,8.454,1574,11.227,1837,10.141,1866,8.723,2050,12.133,2051,11.227,2063,14.321,2064,14.474,2065,10.634,2066,14.474]],["keywords/50",[]],["title/51",[697,696.885]],["content/51",[3,1.573,18,3.404,20,2.876,21,2.2,22,3.311,23,2.476,55,3.638,57,2.908,66,3.517,73,3.266,74,2.086,86,1.464,98,3.311,109,4.124,126,4.203,135,1.857,138,3.796,142,3.016,154,1.982,184,5.758,185,1.619,188,3.952,190,1.719,208,4.369,211,5.396,212,1.719,219,1.8,233,2.706,239,2.065,245,2.104,256,2.161,260,3.499,265,3.221,294,3.499,304,3.016,307,4.569,308,1.347,316,2.374,319,2.906,336,3.582,346,3.794,350,2.581,365,2.374,369,3.796,402,4.487,404,3.392,409,5.651,431,2.374,447,2.015,449,1.745,454,3.582,456,1.887,483,1.949,484,4.316,489,3.981,508,3.952,509,7.161,605,2.328,624,1.159,630,2.015,672,3.796,675,2.086,720,2.086,721,2.544,725,1.668,744,2.422,798,1.719,801,3.376,802,3.376,820,5.694,834,3.499,898,9.583,977,2.908,990,5.396,1119,2.765,1135,2.374,1169,3.265,1189,2.123,1221,3.499,1222,4.203,1258,5.041,1316,3.638,1322,2.7,1328,3.265,1329,3.265,1333,3.453,1338,3.499,1346,2.581,1349,2.987,1350,2.835,1380,8.413,1399,3.265,1401,3.638,1421,13.542,1432,2.241,1439,3.265,1442,4.203,1446,4.853,1447,3.638,1481,4.853,1576,4.203,1578,2.639,1705,3.165,1708,3.796,1717,3.981,1718,3.981,1720,3.981,1721,3.265,1782,2.639,1821,6.713,1854,2.374,1861,9.583,2050,11.634,2053,14.026,2057,4.481,2060,13.733,2061,4.853,2063,4.481,2067,5.418,2068,2.639,2069,5.418,2070,5.418,2071,5.418,2072,4.203,2073,5.418,2074,8.659,2075,5.418,2076,5.418,2077,5.418,2078,5.418,2079,9.687,2080,5.418,2081,8.659,2082,5.418,2083,5.418,2084,5.418,2085,5.418,2086,5.418,2087,5.418,2088,5.418,2089,5.418,2090,5.418,2091,5.418,2092,3.981,2093,5.418,2094,3.981,2095,4.853,2096,8.659,2097,5.418,2098,10.815,2099,5.418,2100,5.418,2101,5.418,2102,7.756,2103,5.418,2104,7.756,2105,5.418,2106,8.659,2107,5.418,2108,5.418,2109,5.418,2110,4.853,2111,5.418,2112,5.418,2113,5.418,2114,5.418,2115,5.418,2116,5.418,2117,5.418,2118,3.981,2119,5.418,2120,8.659,2121,5.418,2122,5.418,2123,8.659,2124,4.853,2125,10.815,2126,5.418,2127,7.756,2128,5.418,2129,5.418,2130,5.418,2131,5.418,2132,8.659,2133,4.481,2134,4.853,2135,5.418,2136,5.418,2137,3.499,2138,2.908,2139,4.853,2140,5.418,2141,4.853,2142,5.418,2143,7.756,2144,7.756,2145,4.853,2146,5.418,2147,3.265,2148,4.853,2149,8.659,2150,7.161,2151,8.659,2152,5.418,2153,5.418,2154,5.418,2155,5.418,2156,5.418,2157,5.418,2158,5.418,2159,4.853,2160,5.418,2161,8.659,2162,5.418,2163,4.853,2164,8.659,2165,5.418,2166,5.418,2167,5.418]],["keywords/51",[]],["title/52",[514,642.995,2168,827.555]],["content/52",[8,4.958,18,4.547,22,2.438,23,2.277,45,4.447,48,5.485,73,2.405,98,2.438,116,2.128,134,5.631,141,3.062,145,1.962,185,2.973,242,6.678,256,3.967,304,5.812,307,4.318,308,3.383,309,5.995,312,3.254,319,2.97,336,6.419,358,2.438,376,5.995,402,3.304,417,3.639,454,4.115,489,7.308,496,6.198,508,4.54,514,5.995,608,3.521,820,4.193,2050,12.242,2053,11.257,2057,8.226,2060,14.451,2102,15.651,2124,12.192,2127,12.192,2133,11.257,2138,5.34,2139,8.91,2147,5.995,2159,12.192,2163,8.91,2169,8.91,2170,9.947,2171,9.947,2172,9.947,2173,13.612,2174,9.947,2175,13.612,2176,9.947,2177,9.947,2178,9.947,2179,9.947,2180,8.226,2181,9.947,2182,8.226,2183,9.947,2184,9.947,2185,15.517,2186,9.947,2187,9.947,2188,9.947,2189,9.947,2190,9.947,2191,13.612,2192,9.947,2193,9.947]],["keywords/52",[]],["title/53",[483,467.128]],["content/53",[7,3.029,18,3.721,20,3.731,21,3.084,25,3.876,31,6.281,68,3.201,73,2.716,79,2.976,86,0.9,91,3.142,98,3.276,100,2.733,116,1.625,125,2.603,135,2.603,141,2.338,142,2.645,143,4.188,145,3.108,153,2.523,160,3.396,190,2.409,191,6.366,212,2.409,216,2.82,219,2.523,233,4.176,239,2.679,245,1.478,249,4.905,250,5.598,255,5.891,256,3.029,275,3.976,298,6.803,308,2.791,319,2.683,418,2.924,453,4.077,458,4.733,484,3.785,543,2.603,630,2.825,635,5.021,637,4.436,644,5.733,720,4.324,721,1.787,725,3.458,726,3.731,744,3.396,766,4.324,798,2.409,827,3.876,908,5.321,1090,5.58,1119,3.876,1137,5.58,1169,4.577,1177,4.307,1181,4.733,1189,2.976,1194,5.58,1284,3.201,1333,3.029,1369,7.254,1392,5.58,1399,4.577,1432,4.646,1502,5.891,1583,3.785,1708,5.321,1844,6.281,1859,5.321,2028,5.58,2035,5.891,2050,7.869,2063,9.288,2068,3.699,2194,5.321,2195,7.595,2196,6.803,2197,7.595,2198,7.595,2199,7.595,2200,11.231,2201,6.803,2202,7.595,2203,11.231,2204,6.803,2205,7.595,2206,7.595,2207,7.595,2208,6.803,2209,7.595,2210,7.595,2211,7.595,2212,7.595,2213,7.595,2214,7.595,2215,6.803,2216,7.595,2217,6.803,2218,6.803,2219,7.595,2220,10.06,2221,7.595,2222,7.595,2223,7.595,2224,7.595,2225,7.595,2226,7.595,2227,7.595,2228,6.281,2229,7.595,2230,7.869,2231,7.595,2232,7.595,2233,7.595,2234,7.595,2235,5.891,2236,7.595,2237,7.595,2238,7.595,2239,10.06,2240,7.595,2241,7.595,2242,7.595,2243,7.595,2244,5.891,2245,6.281,2246,4.733,2247,7.595,2248,11.231,2249,11.231,2250,9.363,2251,11.231,2252,11.231,2253,9.288,2254,7.595,2255,6.281,2256,7.595,2257,7.595,2258,7.595,2259,7.595,2260,7.595,2261,11.231,2262,11.231,2263,9.288,2264,11.231,2265,7.595,2266,7.595,2267,7.595,2268,7.595,2269,5.891,2270,7.595,2271,7.595,2272,7.595,2273,4.733,2274,7.595,2275,7.595,2276,7.595,2277,7.595,2278,7.595,2279,7.595,2280,7.595,2281,13.364,2282,7.595,2283,3.201,2284,10.06,2285,7.254,2286,7.595,2287,6.281]],["keywords/53",[]],["title/54",[108,441.342,630,396.885]],["content/54",[23,3.313,40,9.348,57,7.769,79,5.671,91,5.988,116,3.096,124,4.141,141,4.456,145,2.855,499,5.843,526,5.773,605,6.219,726,4.808,880,9.348,1134,7.769,1307,9.019,1319,8.454,1350,7.572,1565,6.894,1892,7.981,2035,11.227,2288,14.474,2289,17.317,2290,14.474,2291,14.474,2292,7.05,2293,12.964]],["keywords/54",[]],["title/55",[1412,747.456,1709,519.621]],["content/55",[23,3.358,41,6.557,79,5.746,124,4.196,212,4.653,233,5.454,239,3.498,256,5.849,508,6.693,638,8.839,1119,7.486,1333,5.849,1565,6.986,1679,9.139,2250,10.275,2294,13.137,2295,14.666,2296,13.137,2297,12.129,2298,14.666,2299,12.129,2300,14.666,2301,14.666,2302,13.137,2303,12.129]],["keywords/55",[]],["title/56",[412,747.456,2304,1066.856]],["content/56",[]],["keywords/56",[]],["title/57",[2305,747.456,2306,827.555]],["content/57",[10,7.831,18,3.116,74,4.76,124,3.537,134,5.115,141,3.806,145,2.439,160,5.528,167,4.044,190,3.922,233,3.864,239,2.949,245,3.057,256,4.931,289,4.107,300,7.569,307,3.922,308,4.293,309,7.452,319,1.775,336,5.115,346,7.569,382,4.523,404,4.844,415,7.222,418,4.76,499,4.172,512,6.637,524,4.307,526,6.267,721,4.064,1199,6.817,1315,5.418,1320,6.311,1373,7.704,1511,6.637,1517,7.452,1609,8.301,1665,10.225,1892,6.817,2020,8.662,2118,9.084,2220,11.074,2305,8.662,2306,9.591,2307,12.364,2308,8.301,2309,11.074,2310,12.364,2311,9.084,2312,12.364,2313,12.364,2314,8.662,2315,12.364,2316,8.301,2317,9.084,2318,7.012]],["keywords/57",[]],["title/58",[2319,827.555,2320,955.587]],["content/58",[3,4.248,10,5.522,34,3.739,64,5.277,68,4.671,79,4.341,86,1.734,124,4.187,145,2.887,188,5.057,198,8.07,208,3.361,219,4.862,233,5.121,245,2.156,256,6.536,261,6.904,346,8.159,360,10.584,415,6.472,418,4.266,483,3.987,499,3.739,526,6.536,675,6.309,721,4.101,1283,6.678,1290,10.584,1338,7.156,1399,6.678,1402,4.122,1517,8.821,1556,5.277,2020,10.254,2023,6.472,2118,10.753,2305,10.254,2306,13.522,2308,7.439,2316,7.439,2317,12.041,2320,9.924,2321,11.08,2322,9.163,2323,9.924,2324,9.924,2325,11.08,2326,11.08,2327,9.163,2328,11.08,2329,11.08,2330,8.141,2331,9.924,2332,11.08,2333,9.163,2334,11.08,2335,11.353,2336,10.584,2337,11.08,2338,7.156,2339,9.924]],["keywords/58",[]],["title/59",[481,544.542,721,250.988]],["content/59",[6,8.051,95,9.04,118,7.847,266,6.845,374,4.291,499,5.061,630,5.58,721,4.161,988,11.02,1322,7.475,1571,7.656,1710,10.07,1890,9.687,2168,11.634,2311,11.02,2340,8.27,2341,10.508,2342,13.434,2343,11.634,2344,9.687]],["keywords/59",[]],["title/60",[118,558.161,2341,747.456]],["content/60",[118,7.707,127,8.157,208,5.308,256,5.875,308,3.661,309,8.879,319,2.115,374,4.215,977,7.908,1020,8.123,1348,9.514,1464,14.482,1890,9.514,2311,10.824,2341,10.321,2343,11.427,2345,12.183,2346,10.321,2347,14.732,2348,13.195,2349,13.195]],["keywords/60",[]],["title/61",[222,396.796,608,320.529,2343,702.378]],["content/61",[6,4.115,8,3.82,18,1.932,20,2.546,23,4.023,34,2.586,64,3.651,66,3.113,73,2.734,74,2.951,86,1.592,88,6.866,98,2.772,104,2.951,109,3.651,116,1.64,118,9.681,140,3.82,145,1.512,208,2.325,212,2.432,216,2.386,222,3.359,239,1.828,245,2.2,255,5.946,256,4.51,274,9.976,308,2.811,319,2.739,350,6.4,358,1.879,377,5.161,381,5.636,416,3.573,430,3.113,447,2.852,449,2.469,456,2.67,507,7.923,574,5.508,608,2.713,625,4.955,630,5.518,634,6.339,665,4.776,721,4.353,725,4.137,726,5.255,766,2.951,794,4.347,798,2.432,826,3.733,914,8.373,947,4.347,968,10.392,1020,4.226,1090,5.632,1134,4.115,1135,3.359,1189,4.43,1284,5.664,1322,5.636,1346,3.651,1466,3.171,1517,4.62,1522,4.347,1525,4.477,1583,5.636,1611,13.286,1630,5.146,1710,5.146,1810,5.37,1854,3.359,1969,7.62,2026,3.651,2079,10.129,2137,4.95,2311,12.162,2342,6.866,2343,8.772,2348,12.035,2349,6.866,2350,8.886,2351,13.437,2352,5.37,2353,7.665,2354,9.021,2355,10.423,2356,5.146,2357,5.37,2358,5.37,2359,5.632,2360,4.477,2361,7.665,2362,7.665,2363,4.01,2364,7.665,2365,5.146,2366,6.866,2367,6.866,2368,7.665,2369,7.665,2370,7.665,2371,10.129,2372,7.665,2373,11.308,2374,7.665,2375,7.665,2376,7.665,2377,7.665,2378,7.665,2379,7.665,2380,7.665,2381,7.665,2382,7.665,2383,7.665,2384,5.632,2385,6.866,2386,6.866,2387,7.665,2388,6.339,2389,7.665,2390,5.146,2391,6.866,2392,7.665]],["keywords/61",[]],["title/62",[721,250.988,914,664.795]],["content/62",[20,2.903,22,3.549,23,2,27,3.988,57,4.691,64,6.895,73,3.007,86,1.473,96,5.644,104,3.364,145,1.723,181,7.227,208,4.391,245,2.42,292,5.867,300,3.829,307,2.772,319,2.901,358,4.085,370,6.675,402,4.131,409,4.474,418,3.364,454,5.144,461,8.349,482,6.122,624,1.869,707,7.494,721,4.074,748,6.42,766,3.364,787,9.719,820,3.684,834,5.644,940,7.827,941,4.46,968,6.122,988,6.42,1001,7.227,1021,7.494,1189,4.872,1256,11.587,1258,5.796,1328,7.494,1329,5.267,1348,5.644,1777,9.645,1851,9.645,2168,6.778,2308,5.867,2311,6.42,2317,11.587,2335,6.778,2340,4.818,2350,4.691,2391,12.966,2393,7.827,2394,12.435,2395,12.966,2396,8.738,2397,6.778,2398,8.738,2399,7.827,2400,5.267,2401,8.738,2402,8.738,2403,8.738,2404,8.738,2405,8.738,2406,8.738,2407,8.738,2408,11.138,2409,11.138,2410,8.738,2411,8.738,2412,8.738,2413,12.435,2414,8.738,2415,8.738,2416,8.738,2417,8.738,2418,12.435,2419,8.738,2420,8.738,2421,8.738,2422,8.738,2423,8.738,2424,8.738,2425,8.738,2426,8.738,2427,8.738,2428,8.738,2429,8.738,2430,8.738,2431,8.738,2432,8.738,2433,8.738,2434,8.738,2435,8.738,2436,7.827,2437,8.738,2438,8.738,2439,7.827,2440,10.284,2441,8.738,2442,8.738,2443,8.738,2444,8.738,2445,7.227,2446,8.738]],["keywords/62",[]],["title/63",[721,185.035,826,383.078,2335,610.095,2447,786.514]],["content/63",[86,1.785,100,5.421,108,6.233,216,3.18,233,4.708,277,8.545,415,8.801,418,5.801,624,3.223,721,4.172,826,7.339,1016,7.023,1119,7.691,1189,5.903,2023,8.801,2029,11.07,2336,9.731,2448,11.687,2449,15.067]],["keywords/63",[]],["title/64",[188,413.24,526,361.133,2308,607.94]],["content/64",[18,3.505,23,1.863,45,3.638,54,3.875,73,2.856,74,3.132,86,1.808,98,1.995,116,1.74,124,2.328,141,2.505,184,3.792,188,6.347,190,2.581,215,3.792,233,3.691,245,1.583,256,4.711,292,7.931,308,3.793,312,3.864,319,2.847,346,7.644,347,4.257,350,3.875,367,5.754,369,5.701,370,4.368,381,4.055,386,7.894,415,4.753,418,3.132,484,4.055,526,5.547,543,2.789,550,9.163,561,6.482,608,2.88,619,5.463,630,3.027,739,4.904,764,3.43,766,5.354,778,5.463,798,2.581,851,6.311,1020,4.486,1129,5.701,1189,3.188,1256,10.218,1315,3.566,1316,5.463,1432,4.887,1437,5.701,1583,5.888,1782,3.963,1851,13.53,2137,5.255,2305,5.701,2306,9.163,2308,11.997,2309,7.288,2317,5.978,2318,4.614,2330,5.978,2331,7.288,2436,7.288,2439,7.288,2445,9.769,2450,8.136,2451,8.136,2452,15.261,2453,8.136,2454,13.669,2455,6.311,2456,11.813,2457,10.581,2458,7.288,2459,7.288,2460,7.288,2461,7.288,2462,7.288,2463,7.288,2464,7.288,2465,8.136,2466,10.581,2467,10.581,2468,7.288,2469,7.288,2470,7.288,2471,13.908,2472,11.813,2473,13.908,2474,8.136,2475,8.136,2476,8.136,2477,7.288,2478,8.136,2479,11.813,2480,8.136,2481,7.288,2482,7.288,2483,10.581,2484,8.136,2485,8.136,2486,11.813,2487,8.136,2488,11.813,2489,8.136,2490,7.288,2491,8.136,2492,7.288,2493,8.136,2494,8.136,2495,8.136,2496,8.136,2497,8.136,2498,8.136]],["keywords/64",[]],["title/65",[188,413.24,2308,607.94,2499,528.917]],["content/65",[3,3.087,18,2.68,34,2.382,48,5.864,57,3.79,64,3.363,73,2.572,74,4.094,79,2.766,86,1.516,98,3.936,104,2.718,108,2.921,138,4.946,145,1.392,184,3.291,188,7.328,208,2.141,212,2.24,215,5.964,233,3.324,256,4.242,277,4.004,292,7.141,300,3.094,307,2.24,319,2.84,346,5.607,347,8.718,350,6.095,358,3.491,360,6.869,365,3.094,367,5.18,369,7.451,370,3.79,376,4.255,404,2.766,447,2.626,456,2.459,481,3.603,496,10.384,524,3.704,526,2.816,550,8.25,608,3.765,613,6.368,644,3.603,707,4.255,708,5.476,721,2.502,725,2.173,726,4.251,766,5.483,778,4.74,985,4.004,1014,4.74,1016,3.291,1134,3.79,1189,2.766,1199,3.893,1256,7.814,1338,4.56,1346,5.066,1349,3.893,1434,5.476,1502,5.476,1556,5.066,1589,5.838,1672,5.476,1699,4.74,1851,5.476,2020,7.451,2118,7.814,2137,9.868,2308,11.188,2317,10.464,2318,9.45,2445,5.838,2454,13.685,2457,13.685,2458,6.323,2459,6.323,2460,6.323,2461,6.323,2462,6.323,2463,6.323,2464,6.323,2466,6.323,2467,9.526,2468,6.323,2469,6.323,2470,6.323,2477,6.323,2483,6.323,2490,9.526,2492,9.526,2500,6.323,2501,7.06,2502,7.06,2503,14.242,2504,7.814,2505,7.06,2506,5.187,2507,10.635,2508,10.635,2509,7.06,2510,7.06,2511,7.06,2512,8.796,2513,9.526,2514,7.06,2515,14.242,2516,7.06,2517,5.838,2518,7.06,2519,5.476,2520,12.796,2521,12.796,2522,10.635,2523,10.635,2524,7.06,2525,7.06,2526,7.06,2527,7.06,2528,10.635,2529,7.06,2530,7.06,2531,10.635,2532,7.06,2533,7.06,2534,7.06,2535,6.323,2536,6.323,2537,7.06,2538,7.06,2539,7.06]],["keywords/65",[]],["title/66",[1172,808.967]],["content/66",[19,6.501,20,3.808,33,9.481,34,3.868,49,7.404,54,5.46,57,8.034,68,7.024,72,7.404,73,2.772,74,4.413,75,7.697,109,5.46,125,3.93,126,8.893,135,5.13,138,8.032,145,2.952,188,5.232,208,3.477,216,2.419,245,3.437,250,5.714,260,7.404,281,8.423,308,2.849,343,8.423,346,6.559,347,5.998,382,5.475,415,6.696,418,4.413,431,5.024,461,7.697,481,5.851,512,6.154,624,3.201,630,4.265,721,2.697,726,4.972,941,7.639,1208,8.893,1215,8.893,1314,8.893,1315,5.024,1322,5.714,1334,6.909,1398,10.268,1399,6.909,1402,4.265,1409,7.697,1444,9.481,1565,5.46,1618,6.909,1933,8.423,2201,10.268,2318,8.487,2335,8.893,2336,7.404,2338,7.404,2339,10.268,2359,8.423,2499,6.696,2540,11.464,2541,8.893,2542,11.464,2543,10.268,2544,6.501,2545,11.464,2546,8.423,2547,10.268,2548,8.893,2549,10.268,2550,11.464,2551,10.268]],["keywords/66",[]],["title/67",[2552,955.587,2553,642.995]],["content/67",[]],["keywords/67",[]],["title/68",[174,584.8,2356,607.94,2554,665.279]],["content/68",[18,3.705,19,6.326,110,5.836,135,3.824,142,3.885,174,7.204,188,5.091,190,3.539,208,5.301,212,4.664,216,3.688,239,2.66,275,5.204,307,3.539,308,2.772,319,2.361,333,4.294,383,9.991,422,5.988,449,3.593,548,8.653,554,6.723,608,3.949,625,4.888,665,9.16,801,6.951,802,6.951,877,3.383,1169,6.723,1260,11.52,1328,6.723,1329,6.723,1333,4.449,1338,7.204,1346,5.313,1432,7.23,1436,7.815,1578,5.433,1685,6.326,1717,8.196,1718,8.196,1720,8.196,1721,6.723,1821,8.864,1981,6.723,2285,7.204,2554,10.801,2555,7.204,2556,9.225,2557,9.225,2558,10.619,2559,9.87,2560,11.155,2561,14.7,2562,11.403,2563,11.155,2564,11.155,2565,11.155,2566,8.653,2567,11.155,2568,9.991,2569,11.155,2570,7.815,2571,6.326,2572,11.155,2573,11.155,2574,11.155,2575,11.155]],["keywords/68",[]],["title/69",[1432,441.342,2285,689.022]],["content/69",[68,5.87,74,5.361,110,7.285,137,6.633,145,2.747,153,4.626,167,4.555,174,8.994,216,2.939,307,4.418,404,6.628,449,5.449,483,5.011,499,4.699,675,6.513,721,3.276,877,4.224,1177,7.897,1346,6.633,1432,5.761,1578,6.782,1585,11.516,1821,6.491,2285,8.994,2553,8.393,2554,10.231,2558,10.927,2570,11.853,2571,10.335,2576,13.925,2577,12.473]],["keywords/69",[]],["title/70",[358,221.971,1432,374.584,2285,584.8]],["content/70",[20,4.404,160,5.927,167,3.131,239,2.283,319,2.869,337,7.99,358,3.728,365,5.809,367,6.457,402,3.18,409,3.445,418,5.104,449,3.083,561,6.179,608,4.693,613,5.927,675,3.685,778,13.282,797,6.457,820,4.035,1135,4.195,1260,9.288,1695,11.021,1821,4.462,1846,5.429,2137,6.183,2305,6.707,2318,7.518,2559,8.901,2562,10.283,2566,7.426,2578,9.573,2579,8.574,2580,8.574,2581,10.964,2582,17.48,2583,14.456,2584,15.504,2585,12.577,2586,13.622,2587,11.874,2588,8.574,2589,8.574,2590,8.574,2591,8.574,2592,9.573,2593,9.573,2594,9.573,2595,9.573,2596,9.573,2597,8.574,2598,8.574,2599,7.917,2600,8.574,2601,7.917,2602,8.574,2603,8.574,2604,8.574,2605,9.573,2606,7.917]],["keywords/70",[]],["title/71",[608,320.529,1432,374.584,2285,584.8]],["content/71",[20,4.334,34,3.157,49,6.043,110,7.86,153,3.108,154,3.423,160,5.834,167,3.06,174,6.043,212,2.968,223,4.02,239,2.231,316,4.1,319,2.83,337,7.864,358,3.683,365,5.718,418,5.023,422,5.022,449,4.203,454,3.871,485,5.83,508,4.27,526,3.732,561,6.082,608,5.318,613,5.834,625,4.1,675,3.602,778,13.237,797,6.355,877,2.838,954,8.38,1260,6.555,1290,6.043,1378,8.38,1402,3.481,1673,6.555,1695,6.282,1821,6.082,1952,7.258,2318,7.399,2558,6.043,2559,10.913,2562,10.121,2566,7.258,2579,8.38,2580,8.38,2581,10.791,2582,17.412,2583,13.733,2584,15.079,2585,12.425,2586,13.457,2587,11.687,2588,8.38,2590,8.38,2591,8.38,2597,11.687,2598,8.38,2599,7.738,2600,8.38,2601,7.738,2602,8.38,2603,8.38,2604,8.38,2607,9.356,2608,13.048,2609,9.356,2610,9.356,2611,9.356,2612,8.38]],["keywords/71",[]],["title/72",[174,689.022,1311,588.253]],["content/72",[54,5.867,64,5.867,110,6.444,142,4.29,174,7.955,185,4.685,190,3.908,239,2.938,260,7.955,282,7.424,390,9.05,449,5.846,474,6.444,483,6.204,499,4.156,511,7.676,524,4.29,675,6.987,742,9.05,794,6.985,877,5.23,1224,7.424,1290,7.955,1432,5.096,1565,5.867,1584,9.555,1821,7.306,2273,7.676,2285,7.955,2358,8.63,2552,11.033,2554,12.668,2555,7.955,2558,11.722,2570,12.716,2571,10.628,2613,12.16,2614,14.041,2615,11.033,2616,7.955,2617,10.187,2618,9.555,2619,11.033]],["keywords/72",[]],["title/73",[304,371.602,2620,588.253]],["content/73",[20,3.959,22,2.922,53,4.655,56,7.427,81,6.398,86,1.412,98,3.763,104,4.588,110,6.235,116,3.283,124,3.41,135,4.086,141,3.669,145,2.351,167,5.02,208,3.615,212,3.781,215,5.555,217,6.572,233,3.724,239,2.843,304,5.913,374,3.41,377,5.439,431,5.223,458,7.427,483,4.288,574,5.805,596,4.588,697,9.113,700,6.726,725,4.725,775,5.024,797,5.805,798,3.781,1013,7.697,1223,6.235,1224,7.183,1251,9.245,1284,5.024,1287,8.757,1395,6.235,1440,6.572,1556,8.086,1618,7.183,1684,9.857,1689,10.675,1821,7.154,1854,5.223,2344,7.697,2571,8.704,2620,9.361,2621,8.002,2622,9.857,2623,10.675,2624,8.002,2625,11.918,2626,11.918,2627,11.918,2628,8.35,2629,9.857,2630,8.757]],["keywords/73",[]],["title/74",[53,274.647,2630,665.279,2631,748.84]],["content/74",[18,2.371,22,2.307,23,2.999,53,3.973,64,4.482,66,5.32,73,2.275,81,5.051,89,4.123,94,4.803,104,3.622,124,3.748,142,3.277,154,5.961,160,4.207,161,7.299,167,4.285,184,4.386,188,4.294,208,2.854,239,2.244,246,5.671,261,5.863,273,6.317,315,6.077,316,4.123,317,5.671,319,2.546,328,4.207,333,3.622,346,4.123,373,8.428,382,3.442,404,3.687,409,5.863,411,6.686,416,4.386,418,3.622,422,7.032,449,3.031,453,8.089,483,4.713,499,3.175,514,5.671,608,4.637,624,2.013,625,4.123,720,3.622,721,2.214,725,2.897,726,4.351,764,3.966,778,12.217,798,2.985,826,4.583,827,4.803,851,7.299,877,2.854,998,7.299,1048,7.299,1049,5.863,1185,3.175,1189,3.687,1266,9.624,1333,3.753,1380,8.802,1477,4.803,1530,8.428,1595,6.317,1821,7.024,1898,6.592,1952,7.299,2023,5.496,2030,6.592,2318,5.336,2390,6.317,2555,6.077,2559,8.795,2570,9.178,2571,5.336,2581,7.782,2585,7.782,2628,6.592,2630,9.624,2631,7.782,2632,9.409,2633,9.409,2634,9.409,2635,9.409,2636,9.409,2637,9.409,2638,8.428,2639,9.409,2640,9.409,2641,9.409,2642,9.409,2643,5.496,2644,9.409,2645,9.409,2646,9.409,2647,9.409,2648,9.409,2649,8.428,2650,6.592,2651,7.782,2652,9.409,2653,9.409,2654,6.077,2655,9.409,2656,6.317,2657,6.592,2658,9.409,2659,9.409,2660,9.409,2661,9.409]],["keywords/74",[]],["title/75",[304,315.394,1854,396.796,2620,499.273]],["content/75",[3,3.122,8,5.361,21,7.498,48,5.931,53,4.352,72,6.947,104,7.372,109,6.835,124,3.077,141,4.418,154,5.907,212,3.412,216,2.27,245,2.093,282,6.482,304,3.746,316,4.713,317,11.804,336,6.68,360,6.947,449,5.201,542,7.536,605,4.622,697,8.668,700,6.288,720,4.141,721,2.53,764,4.534,775,4.534,877,3.262,894,7.536,910,10.842,1000,7.536,1013,6.947,1175,7.536,1308,6.482,1380,8.382,1432,4.449,1439,8.649,1517,6.482,1526,7.221,1538,9.634,1708,7.536,1821,7.527,1848,7.536,1898,7.536,2194,7.536,2400,8.649,2536,9.634,2559,7.221,2571,6.1,2620,5.931,2630,7.902,2649,9.634,2662,10.756,2663,10.756,2664,8.343,2665,10.756,2666,8.895,2667,10.756,2668,10.756,2669,9.634,2670,10.756,2671,10.756,2672,10.756,2673,11.131,2674,10.756]],["keywords/75",[]],["title/76",[22,261.53,116,228.21]],["content/76",[3,2.623,7,2.28,8,2.85,16,2.665,20,4.23,21,3.67,22,2.215,23,2.069,41,2.556,49,3.693,53,1.734,73,2.71,84,2.365,86,0.677,91,3.739,97,4.435,100,2.057,116,1.223,124,1.636,125,1.96,136,3.563,141,1.76,145,1.128,154,3.306,170,7.521,198,6.179,208,2.741,216,1.907,219,3.002,223,2.457,242,3.839,245,1.113,252,2.85,256,2.28,308,1.421,319,2.978,334,4.728,336,3.739,344,2.609,346,2.505,357,5.777,358,2.215,377,4.124,402,4.607,409,2.057,411,4.613,417,3.306,430,2.322,431,2.505,449,2.911,454,3.739,456,1.991,483,2.057,489,4.201,514,3.446,542,4.006,561,5.935,596,2.201,605,2.457,608,3.199,697,3.069,700,2.505,702,4.006,801,5.631,802,3.563,820,5.368,822,6.754,910,7.524,975,2.991,980,3.693,992,4.006,1135,2.505,1177,3.242,1199,3.153,1223,2.991,1264,3.446,1308,3.446,1376,2.365,1380,6.546,1409,3.839,1437,4.006,1439,8.359,1578,5.458,1589,4.728,1618,3.446,1630,3.839,1693,8.233,1696,3.34,1706,2.609,1708,4.006,1821,2.665,1857,4.728,1861,4.435,1954,4.435,2020,6.332,2065,4.201,2134,8.095,2239,5.121,2246,3.563,2390,3.839,2400,3.446,2440,4.728,2558,3.693,2559,6.068,2571,3.242,2628,4.006,2666,7.474,2669,5.121,2673,4.435,2675,11.206,2676,9.037,2677,12.734,2678,5.717,2679,5.717,2680,9.037,2681,5.717,2682,5.717,2683,5.717,2684,13.869,2685,5.717,2686,5.717,2687,5.717,2688,3.563,2689,4.435,2690,4.006,2691,5.717,2692,5.717,2693,9.037,2694,5.717,2695,5.717,2696,5.717,2697,4.435,2698,5.717,2699,5.121,2700,5.717,2701,5.717,2702,5.717,2703,9.037,2704,5.717,2705,5.717,2706,3.693,2707,5.717,2708,15.442,2709,5.717,2710,15.442,2711,5.717,2712,5.717,2713,5.717,2714,5.717,2715,5.717,2716,4.728,2717,5.121,2718,5.717,2719,5.717,2720,5.717,2721,13.869,2722,13.869,2723,14.745,2724,8.095,2725,15.442,2726,15.442,2727,9.037,2728,4.435,2729,11.206,2730,10.037,2731,10.037,2732,9.037,2733,4.435,2734,9.037,2735,5.717,2736,2.85,2737,5.717,2738,14.745,2739,4.728,2740,9.037,2741,5.717,2742,9.037,2743,5.717]],["keywords/76",[]],["title/77",[2553,642.995,2744,882.296]],["content/77",[3,4.334,22,3.66,64,7.112,98,3.66,110,7.812,141,4.597,167,4.884,215,6.959,261,9.304,307,4.737,308,3.711,1565,7.112,1585,14.589,1821,6.959,2553,8.999,2554,10.97,2558,9.643,2571,10.004,2744,12.348,2745,13.374]],["keywords/77",[]],["title/78",[164,467.512,358,261.53]],["content/78",[3,4.296,86,1.335,125,3.863,208,3.418,219,3.743,223,4.842,245,3.215,304,3.925,319,2.777,336,4.662,337,6.792,365,4.938,367,7.208,431,4.938,820,4.75,877,3.418,1264,6.792,1308,6.792,1693,8.279,1695,7.566,1821,8.179,2400,6.792,2513,10.093,2553,6.792,2566,8.741,2571,6.391,2620,8.16,2730,10.093,2731,13.256,2746,10.093,2747,11.269,2748,14.799,2749,11.269,2750,11.269,2751,11.269,2752,16.525,2753,11.269,2754,14.799,2755,11.269,2756,11.269,2757,11.269,2758,11.269,2759,11.269,2760,11.269,2761,11.269,2762,11.269,2763,14.799,2764,11.269,2765,14.799,2766,11.269,2767,11.269,2768,11.269,2769,11.269,2770,11.269,2771,11.269,2772,11.269,2773,11.269,2774,11.269,2775,16.324,2776,16.755,2777,8.741,2778,11.269,2779,11.269]],["keywords/78",[]],["title/79",[164,467.512,608,377.653]],["content/79",[73,3.562,86,1.746,223,6.33,245,2.866,304,5.131,358,3.611,561,6.866,1695,9.891,2553,8.879,2571,8.354,2583,14.482,2584,15.802,2620,8.123,2780,12.183,2781,13.195,2782,14.732]],["keywords/79",[]],["title/80",[164,467.512,418,410.72]],["content/80",[20,5.737,73,3.484,86,1.708,245,2.804,304,5.019,358,3.533,418,5.548,561,6.717,613,6.443,1695,9.675,2553,8.685,2559,11.596,2583,14.347,2584,15.742,2620,7.946,2780,14.284,2781,12.908,2783,14.411]],["keywords/80",[]],["title/81",[164,467.512,613,476.984]],["content/81",[73,3.643,216,3.18,245,2.932,304,5.248,308,3.745,430,6.119,447,5.605,483,5.421,524,5.248,561,8.266,745,9.389,1402,5.605,2553,9.081,2558,9.731,2620,8.308,2724,13.496,2784,15.067,2785,15.067,2786,15.067]],["keywords/81",[]],["title/82",[164,467.512,365,467.512]],["content/82",[3,2.845,11,6.866,22,2.402,73,2.37,124,2.804,125,3.359,135,3.359,179,3.585,185,2.929,191,6.417,241,8.104,245,1.907,303,5.906,304,3.413,336,7.961,368,8.104,374,2.804,382,3.585,431,8.433,447,3.646,454,4.054,458,6.107,483,3.526,525,6.329,526,3.908,625,4.294,700,4.294,721,3.901,797,4.773,877,2.972,996,8.104,1048,7.602,1306,6.866,1308,11.598,1376,4.054,1402,3.646,1439,5.906,1525,5.724,1583,4.884,1693,14.138,1695,6.58,1821,6.28,1854,4.294,1965,8.778,1982,8.778,2246,6.107,2400,11.598,2499,5.724,2562,7.602,2571,5.557,2620,5.403,2673,7.602,2746,8.778,2775,16.088,2776,15.569,2777,7.602,2787,9.8,2788,9.8,2789,9.8,2790,9.8,2791,9.8,2792,8.778,2793,9.8,2794,9.8,2795,9.8,2796,9.8,2797,9.8,2798,9.8,2799,9.8,2800,9.8,2801,9.8,2802,9.8,2803,9.8,2804,9.8,2805,9.8,2806,9.8,2807,9.8,2808,7.602,2809,8.778]],["keywords/82",[]],["title/83",[1311,715.826]],["content/83",[25,6.556,34,5.431,74,6.196,134,5.313,145,2.533,167,4.201,185,3.839,191,6.118,343,9.437,382,4.699,404,6.306,474,6.72,483,6.325,524,4.474,596,4.945,624,2.747,625,7.053,697,8.64,700,5.628,721,3.022,826,6.256,877,3.896,1013,8.295,1020,7.082,1127,9.963,1290,10.395,1320,6.556,1372,7.502,1402,4.778,1410,9.437,1466,5.313,1583,6.401,1618,7.741,1699,8.623,1821,7.502,1838,9.437,1866,9.701,2553,7.741,2571,7.284,2809,11.504,2810,10.622,2811,12.844,2812,11.504,2813,12.844,2814,12.844,2815,7.502,2816,12.844,2817,12.844]],["keywords/83",[]],["title/84",[304,315.394,1684,748.84,2620,499.273]],["content/84",[]],["keywords/84",[]],["title/85",[304,371.602,2620,588.253]],["content/85",[18,3.354,34,4.491,53,4.037,56,8.293,81,7.144,86,1.577,134,5.506,141,5.499,142,4.636,154,4.869,216,2.809,253,9.778,304,5.732,317,8.021,343,9.778,357,5.214,358,4.034,404,5.214,422,8.833,430,5.405,449,4.287,512,7.144,596,5.124,697,7.144,700,7.211,798,4.222,1697,7.774,2026,6.339,2104,11.921,2138,7.144,2344,8.596,2346,9.324,2620,9.073,2638,11.921,2818,11.921,2819,14.739,2820,13.309,2821,13.309,2822,13.309,2823,11.921,2824,10.324]],["keywords/85",[]],["title/86",[91,537.055]],["content/86",[3,3.092,7,4.248,19,6.041,22,2.611,23,3.264,53,3.231,81,5.718,86,2.12,89,4.668,98,2.611,116,2.279,140,5.309,141,3.279,142,5.597,154,3.897,179,3.897,185,3.184,233,3.329,239,2.54,243,8.263,245,2.073,249,6.879,250,7.106,253,10.475,261,6.638,289,3.538,294,6.879,304,4.966,317,6.42,328,6.374,329,13.29,382,3.897,431,4.668,453,5.718,456,3.71,458,6.638,526,5.686,625,4.668,697,9.603,700,7.839,702,7.463,761,6.638,871,4.965,877,3.231,880,6.879,1185,3.594,1403,7.826,1437,7.463,1444,8.809,1525,6.222,1618,9.685,1673,7.463,1679,6.638,1706,4.861,1838,7.826,1839,7.826,1954,8.263,1981,6.42,2230,7.463,2283,4.49,2346,7.463,2553,6.42,2558,6.879,2620,7.861,2623,9.541,2630,7.826,2812,9.541,2825,9.113,2826,9.208,2827,17.161,2828,9.541,2829,10.652,2830,10.652,2831,10.652,2832,8.809,2833,10.652,2834,8.809,2835,7.152,2836,7.826,2837,9.541]],["keywords/86",[]],["title/87",[1225,528.065,1292,528.065,2292,383.078,2688,490.104]],["content/87",[]],["keywords/87",[]],["title/88",[723,572.688,2330,783.844]],["content/88",[3,2.724,18,1.511,66,2.436,68,2.528,73,1.45,86,0.711,89,4.112,98,1.47,100,2.158,116,2.473,119,4.652,134,2.481,145,1.851,158,3.737,167,3.781,185,1.792,190,2.977,191,2.857,208,4.936,219,3.117,245,1.167,300,5.729,305,3.138,306,7.018,307,2.977,308,2.873,312,1.962,319,2.768,336,2.481,358,3.205,365,6.218,370,3.219,382,3.433,402,3.84,416,2.795,418,5.033,422,7.018,447,2.231,460,2.921,474,3.138,482,4.202,492,8.444,524,2.089,561,2.795,608,2.123,613,7.48,625,2.628,638,3.615,675,2.309,706,6.574,707,5.655,709,3.737,718,4.652,721,1.411,723,7.617,775,3.955,787,6.3,820,4.872,827,3.061,834,3.873,877,3.506,941,3.061,1016,2.795,1020,3.307,1135,2.628,1225,7.76,1258,2.795,1269,6.894,1284,2.528,1293,8.289,1308,3.615,1320,3.061,1328,3.615,1329,3.615,1346,4.469,1464,4.652,1574,7.279,1676,6.06,1685,3.401,1704,3.615,1717,4.406,1718,4.406,1720,4.406,1721,3.615,1777,13.746,1866,3.615,2023,3.503,2043,5.372,2150,7.76,2194,4.202,2245,4.96,2292,7.329,2345,4.96,2535,5.372,2739,4.96,2838,5.372,2839,5.997,2840,5.997,2841,8.966,2842,5.372,2843,9.383,2844,5.997,2845,5.997,2846,5.997,2847,5.997,2848,5.997,2849,9.383,2850,8.405,2851,4.96,2852,5.372,2853,4.202,2854,5.372,2855,7.279,2856,5.372,2857,5.372,2858,5.372,2859,5.372,2860,5.997,2861,5.997,2862,5.997,2863,14.19,2864,5.997,2865,5.997,2866,5.997,2867,5.997,2868,5.997,2869,5.997,2870,5.997,2871,5.997,2872,5.997,2873,5.997,2874,5.997,2875,11.711,2876,5.997,2877,9.383,2878,9.383,2879,10.353,2880,9.383,2881,9.383,2882,13.074,2883,11.711,2884,5.372,2885,5.997,2886,5.997,2887,5.997,2888,11.559,2889,11.711,2890,5.997,2891,9.383,2892,9.559,2893,5.997,2894,5.997,2895,5.997,2896,5.372,2897,4.406,2898,5.997,2899,4.96,2900,5.997,2901,5.997,2902,8.405,2903,5.997,2904,5.997,2905,4.202,2906,5.997,2907,9.383,2908,9.383,2909,5.997,2910,5.997,2911,5.997,2912,5.997,2913,4.96,2914,4.96,2915,5.997,2916,5.372,2917,5.997,2918,5.372,2919,7.76,2920,5.997,2921,9.383,2922,5.372,2923,4.96,2924,5.997,2925,5.372,2926,5.372,2927,8.405,2928,5.997,2929,5.997,2930,5.997,2931,9.383,2932,5.997,2933,5.372,2934,5.372,2935,5.997,2936,5.997,2937,5.372,2938,4.96,2939,5.997,2940,3.873,2941,5.997,2942,5.997]],["keywords/88",[]],["title/89",[19,605.017,2943,1066.856]],["content/89",[13,5.038,19,8.393,20,3.743,23,2.58,25,5.752,34,3.802,66,4.576,72,9.558,73,2.725,79,5.798,125,3.863,142,5.155,145,2.223,153,3.743,185,4.423,188,5.143,212,4.695,252,5.616,300,4.938,360,7.278,367,5.489,386,5.489,404,4.415,416,5.252,456,3.925,460,7.208,484,5.616,485,7.022,499,3.802,525,7.278,596,4.338,624,2.41,721,2.651,723,8.87,725,4.556,764,4.75,766,4.338,826,5.489,877,3.418,1016,6.898,1098,7.895,1199,6.213,1216,7.278,1225,11.782,1293,9.652,1322,5.616,1348,7.278,1413,10.093,1429,10.093,1440,6.213,1466,4.662,1565,5.367,1706,5.143,2292,8.547,2359,8.279,2841,11.48,2944,11.269,2945,11.269,2946,11.269,2947,11.269,2948,8.279,2949,14.799,2950,10.093,2951,11.269,2952,11.269,2953,11.269,2954,11.269,2955,11.269,2956,11.269,2957,8.741,2958,11.269,2959,11.269,2960,11.269]],["keywords/89",[]],["title/90",[1292,716.286,2688,664.795]],["content/90",[18,1.15,20,1.517,22,1.119,27,3.439,54,2.175,55,3.065,79,1.789,86,0.893,100,1.643,108,1.889,116,0.977,125,1.565,137,2.175,145,0.9,148,3.354,154,5.148,167,1.493,173,5.059,185,2.252,208,3.748,216,0.963,222,2.001,306,7.554,308,1.135,316,4.216,319,2.931,324,3.354,343,3.354,344,2.084,357,2.952,358,4.378,365,5.415,382,2.756,402,1.517,404,2.952,409,1.643,411,2.33,430,1.854,459,3.512,460,4.686,474,2.389,492,2.949,542,3.199,561,2.128,562,3.776,605,7.808,608,4.374,619,3.065,624,0.977,628,3.776,629,4.541,680,3.512,701,7.823,702,3.199,707,4.541,708,3.541,717,12.492,720,1.758,721,1.074,725,2.32,741,2.752,742,3.354,744,2.041,748,3.354,764,3.176,766,6.333,778,5.059,787,5.059,798,2.39,801,2.845,802,2.845,807,8.617,820,4.055,833,1.962,941,2.33,975,2.389,978,5.995,985,2.589,992,5.279,1001,6.231,1018,2.752,1020,2.517,1029,4.089,1133,3.541,1135,3.302,1172,4.695,1266,3.354,1269,3.354,1274,3.776,1292,3.065,1328,2.752,1329,2.752,1333,1.821,1346,2.175,1349,4.154,1412,3.199,1437,3.199,1438,3.199,1565,2.175,1578,2.224,1679,4.695,1708,3.199,1777,3.541,1781,6.231,1892,2.517,1923,4.089,1925,11.915,1966,6.958,2014,4.089,2273,2.845,2292,2.224,2305,3.199,2318,2.589,2319,5.845,2358,3.199,2360,2.667,2408,6.749,2440,3.776,2589,4.089,2688,10.441,2689,3.541,2690,7.823,2697,3.541,2699,4.089,2824,3.541,2850,4.089,2851,3.776,2884,4.089,2892,3.776,2896,4.089,2913,3.776,2914,3.776,2948,3.354,2961,3.541,2962,3.199,2963,4.565,2964,7.535,2965,4.565,2966,7.535,2967,4.089,2968,4.089,2969,3.776,2970,4.565,2971,4.565,2972,4.565,2973,4.565,2974,4.565,2975,4.565,2976,4.565,2977,4.565,2978,4.565,2979,7.535,2980,11.165,2981,7.535,2982,7.535,2983,7.535,2984,15.707,2985,7.535,2986,7.535,2987,7.535,2988,7.535,2989,14.71,2990,7.535,2991,7.535,2992,7.535,2993,7.535,2994,7.535,2995,15.707,2996,4.565,2997,4.565,2998,4.565,2999,9.62,3000,9.62,3001,9.62,3002,4.565,3003,11.165,3004,13.302,3005,7.535,3006,4.565,3007,7.535,3008,7.535,3009,4.565,3010,4.565,3011,4.565,3012,9.62,3013,4.565,3014,4.565,3015,4.565,3016,4.565,3017,4.565,3018,4.565,3019,4.565,3020,4.565,3021,4.565,3022,4.565,3023,3.776,3024,3.776,3025,4.565,3026,4.565,3027,4.565,3028,4.089,3029,7.535,3030,7.535,3031,7.535,3032,4.089,3033,4.565,3034,4.565,3035,4.089,3036,4.565,3037,4.565,3038,4.565,3039,4.565,3040,4.565,3041,7.535,3042,4.565,3043,4.565,3044,4.565,3045,4.565,3046,4.565,3047,4.565,3048,4.565,3049,4.565,3050,4.565,3051,4.565,3052,4.565,3053,4.565,3054,9.62,3055,9.62,3056,9.62,3057,4.565,3058,4.565,3059,4.565,3060,4.565,3061,4.565,3062,4.565,3063,4.565,3064,9.62,3065,4.565,3066,4.565,3067,4.565,3068,4.565,3069,3.776,3070,2.845]],["keywords/90",[]],["title/91",[131,152.896,300,208.012,358,116.364,367,231.197,596,182.743,766,182.743,1199,261.734,1293,277.273,2688,295.79]],["content/91",[3,2.076,8,2.137,13,1.917,18,1.802,20,1.424,22,1.051,23,2.106,27,3.264,28,2.878,54,2.042,57,2.301,64,2.042,79,3.605,86,1.09,96,2.769,98,1.051,100,3.311,108,3.806,109,2.042,116,2.759,124,1.227,125,1.47,127,1.998,131,1.381,134,1.774,141,2.202,145,1.411,153,3.056,154,2.616,160,1.917,167,1.402,179,1.568,185,1.281,190,2.269,195,4.456,208,3.257,212,1.36,215,1.998,216,1.509,239,1.023,245,2.789,256,1.71,266,1.957,277,2.431,289,1.424,300,6.525,306,3.839,307,1.36,308,1.066,315,2.769,316,3.134,319,2.899,333,1.651,344,1.957,346,1.879,353,5.374,357,1.68,358,2.256,359,2.504,365,4.032,367,2.088,374,1.227,386,2.088,389,2.137,402,2.376,404,2.802,409,2.573,418,4.134,422,3.839,430,1.741,447,1.595,449,1.381,454,1.774,459,3.333,460,6.982,481,2.188,483,3.311,492,2.769,496,2.672,524,1.493,561,3.333,596,4.965,608,1.518,613,6.409,624,0.917,627,4.178,630,1.595,644,6.582,669,5.011,680,1.998,709,7.438,720,2.753,721,2.527,723,6.408,725,2.202,739,4.31,741,4.31,742,5.255,766,6.962,775,3.015,798,2.919,820,3.015,822,2.584,874,1.957,877,1.3,879,2.504,913,3.943,928,3.004,941,3.65,949,3.84,980,2.769,1000,3.004,1014,2.878,1018,2.584,1135,1.879,1199,2.364,1223,2.243,1225,8.658,1264,2.584,1269,3.15,1284,1.807,1290,2.769,1292,8.658,1293,7.991,1320,2.188,1338,2.769,1348,2.769,1373,2.672,1376,5.335,1379,3.546,1380,2.504,1401,2.878,1433,3.15,1438,3.004,1511,2.301,1517,2.584,1556,3.406,1565,2.042,1593,1.807,1706,5.448,1709,2.088,1792,3.84,1807,3.004,1863,5.255,1898,3.004,1911,2.504,1966,4.456,2023,2.504,2026,2.042,2052,3.326,2292,6.281,2318,2.431,2333,12.313,2360,2.504,2512,3.546,2519,3.326,2544,2.431,2656,2.878,2688,9.574,2689,3.326,2733,3.326,2837,3.84,2855,5.548,2875,3.84,2879,6.406,2883,6.406,2889,3.84,2892,5.915,2913,3.546,2914,3.546,2916,3.84,2918,3.84,2919,5.915,2923,3.546,2925,3.84,2926,3.84,2927,6.406,2933,3.84,2934,3.84,2937,3.84,2962,5.011,2967,3.84,3023,12.313,3035,6.406,3069,3.546,3071,4.287,3072,4.287,3073,4.287,3074,4.287,3075,4.287,3076,7.152,3077,4.287,3078,4.287,3079,4.287,3080,4.287,3081,4.287,3082,4.287,3083,4.287,3084,7.152,3085,4.287,3086,4.287,3087,4.287,3088,7.152,3089,4.287,3090,4.287,3091,4.287,3092,4.287,3093,4.287,3094,4.287,3095,4.287,3096,4.287,3097,4.287,3098,4.287,3099,6.406,3100,4.287,3101,4.287,3102,4.287,3103,3.84,3104,3.546,3105,6.406,3106,3.84,3107,3.84,3108,3.84,3109,3.326,3110,3.546,3111,3.84,3112,3.84,3113,3.84,3114,3.84,3115,3.546,3116,4.287,3117,4.287,3118,4.287,3119,4.287,3120,7.152,3121,4.287,3122,4.287,3123,4.287,3124,4.287,3125,4.287,3126,4.287,3127,3.546,3128,3.84,3129,6.406,3130,6.406,3131,3.84,3132,3.84,3133,3.84,3134,3.84,3135,3.84,3136,3.84,3137,3.84,3138,3.84,3139,3.84,3140,4.287,3141,4.287,3142,9.201,3143,4.287,3144,4.287,3145,4.287,3146,4.287,3147,4.287,3148,4.287,3149,4.287,3150,3.84,3151,3.84,3152,4.287,3153,4.287,3154,4.287,3155,4.287,3156,4.287,3157,3.84,3158,9.201,3159,11.551,3160,8.241,3161,7.152,3162,6.406,3163,3.546,3164,4.287,3165,7.152,3166,3.84,3167,6.406,3168,3.15,3169,3.84,3170,7.152,3171,4.287,3172,4.287,3173,3.84,3174,7.152,3175,4.287,3176,4.287]],["keywords/91",[]],["title/92",[131,181.714,145,111.269,367,274.774,608,199.702,766,217.187,1293,329.534,2688,351.541]],["content/92",[20,2.778,27,3.817,57,6.468,73,2.022,79,3.276,89,5.28,98,2.05,100,3.009,116,3.306,134,3.46,141,2.574,145,2.786,167,2.735,179,4.408,190,2.653,195,5.211,215,3.898,216,1.765,223,3.594,230,5.859,245,3.321,277,4.743,300,6.19,306,4.489,308,3.511,312,2.735,319,2.868,333,4.639,346,3.665,353,8.251,357,3.276,358,2.05,402,4.692,417,3.059,418,3.22,430,3.396,447,3.111,459,3.898,460,7.98,483,3.009,525,5.401,596,4.639,625,5.28,626,4.885,627,7.038,630,4.483,644,4.268,709,5.211,720,3.22,721,2.835,725,2.574,741,5.04,742,6.144,766,6.57,820,3.525,874,3.817,913,4.611,928,5.859,941,4.268,980,5.401,1016,3.898,1199,4.611,1225,5.615,1293,9.029,1348,5.401,1349,4.611,1373,5.211,1376,5.843,1402,3.111,1593,3.525,1863,6.144,1911,4.885,2023,4.885,2314,5.859,2333,9.965,2360,4.885,2519,6.487,2688,8.802,2689,6.487,2855,6.487,2962,8.442,3023,11.682,3069,6.916,3099,7.491,3127,6.916,3128,7.491,3129,7.491,3130,7.491,3131,7.491,3132,7.491,3133,7.491,3134,7.491,3135,7.491,3136,7.491,3137,7.491,3138,7.491,3139,7.491,3157,7.491,3159,15.285,3160,12.652,3162,10.793,3166,7.491,3168,8.853,3169,7.491,3173,7.491,3177,12.05,3178,8.363,3179,14.125,3180,12.05,3181,8.363,3182,8.363,3183,8.363,3184,6.487,3185,12.05,3186,12.05]],["keywords/92",[]],["title/93",[1172,664.795,1311,588.253]],["content/93",[1,3.177,3,1.316,18,1.143,19,2.571,21,1.841,23,1.715,28,3.044,34,1.53,48,2.5,57,2.434,66,1.841,72,2.928,79,4.356,86,0.537,89,1.987,98,1.111,100,1.631,109,2.16,116,1.603,124,1.297,141,2.306,145,1.478,179,1.659,190,3.037,198,2.5,208,5.355,219,1.506,239,2.283,245,1.458,274,2.733,282,4.515,292,3.044,306,5.968,319,2.954,336,1.876,342,3.177,345,4.668,358,1.111,370,2.434,374,1.297,382,1.659,402,3.693,404,1.776,409,4.43,431,4.195,447,1.687,460,6.457,461,3.044,473,3.177,483,1.631,484,2.26,489,3.331,499,1.53,511,2.825,525,4.839,627,4.376,635,2.027,637,2.648,638,2.733,664,4.515,669,3.177,680,2.113,706,6.707,707,5.77,708,5.811,709,9.477,720,2.884,721,3.578,723,7.117,725,2.947,726,3.18,766,1.746,775,4.687,784,3.177,787,5.03,799,2.571,820,5.589,822,2.733,834,4.839,873,3.331,874,3.419,877,1.375,879,2.648,880,2.928,887,4.061,888,9.195,889,4.061,894,3.177,901,4.061,911,4.061,914,2.825,920,3.331,928,5.249,932,4.061,933,3.75,934,6.711,935,4.061,941,5.675,951,4.061,958,3.75,963,4.061,977,2.434,995,7.426,997,3.331,999,3.75,1016,3.492,1018,2.733,1021,2.733,1054,3.517,1122,3.177,1168,3.75,1177,2.571,1185,1.53,1199,4.131,1212,4.061,1225,7.465,1245,3.75,1258,2.113,1264,2.733,1292,3.044,1293,2.648,1306,3.177,1328,4.515,1329,4.515,1346,2.16,1369,2.928,1402,1.687,1439,2.733,1464,3.517,1466,1.876,1476,4.061,1477,2.314,1493,4.061,1535,2.928,1562,4.061,1571,2.314,1593,1.911,1676,4.839,1685,2.571,1686,2.648,1703,3.331,1784,3.177,1824,4.061,1854,1.987,1862,3.517,1863,3.331,1865,3.75,1866,2.733,1933,3.331,1966,2.825,1985,3.331,2023,5.592,2026,2.16,2052,3.517,2292,4.663,2345,3.75,2397,3.517,2544,4.249,2688,8.261,2733,3.517,2792,8.575,2842,4.061,2851,3.75,2852,4.061,2853,3.177,2854,4.061,2855,5.811,2856,4.061,2857,4.061,2858,4.061,2859,4.061,2902,4.061,2948,7.034,3024,6.196,3032,6.711,3103,6.711,3104,3.75,3105,8.575,3106,4.061,3107,6.711,3108,4.061,3109,3.517,3110,3.75,3111,6.711,3112,4.061,3113,4.061,3114,4.061,3167,4.061,3187,4.061,3188,4.061,3189,4.534,3190,4.061,3191,4.534,3192,4.534,3193,4.534,3194,4.534,3195,3.75,3196,4.534,3197,4.061,3198,4.534,3199,4.534,3200,3.177,3201,4.534,3202,4.534,3203,4.534,3204,4.534,3205,4.534,3206,6.196,3207,9.574,3208,4.534,3209,4.534,3210,4.534,3211,4.534,3212,4.534,3213,4.534,3214,4.534,3215,7.492,3216,4.534,3217,4.534,3218,4.534,3219,4.534,3220,4.534,3221,7.492,3222,4.534,3223,3.517,3224,4.534,3225,4.534,3226,4.534,3227,4.534,3228,4.534,3229,4.534,3230,4.534,3231,4.534,3232,4.534,3233,4.534,3234,4.534,3235,4.534,3236,4.534,3237,4.534,3238,4.534,3239,7.492,3240,4.534,3241,4.534,3242,4.534,3243,4.534,3244,4.534,3245,4.534,3246,4.534,3247,4.534,3248,4.534,3249,4.534,3250,4.534,3251,4.534,3252,4.534,3253,4.534,3254,4.534,3255,4.534,3256,4.534,3257,4.534,3258,4.061,3259,4.534,3260,4.534,3261,4.534,3262,4.534,3263,4.534,3264,4.534,3265,4.534,3266,4.534,3267,4.534,3268,4.534,3269,4.534,3270,4.534,3271,4.534,3272,4.534,3273,4.534,3274,4.534,3275,4.534,3276,4.534,3277,4.534,3278,4.534,3279,6.196,3280,7.492,3281,11.119,3282,7.492,3283,7.492,3284,11.119,3285,7.492,3286,7.492,3287,7.492,3288,7.492,3289,7.492,3290,7.492,3291,3.044,3292,4.534,3293,4.534,3294,4.534,3295,4.534,3296,4.534]],["keywords/93",[]],["title/94",[638,474.032,2853,551.044,3297,786.514,3298,786.514]],["content/94",[]],["keywords/94",[]],["title/95",[3299,1073.638]],["content/95",[7,5.064,17,8.2,22,3.112,23,2.906,54,6.047,68,5.352,74,6.151,86,1.504,98,3.917,124,4.572,130,5.918,141,3.909,145,2.504,167,4.153,219,4.217,222,5.564,233,3.967,239,3.028,308,3.156,377,5.794,382,5.845,390,9.328,447,4.723,481,6.48,484,7.964,499,4.284,514,7.652,524,4.422,543,4.352,596,4.888,624,2.716,721,2.987,766,4.888,988,9.328,1440,7,1463,8.524,1500,8.895,1712,6.184,2068,6.184,2299,10.5,2853,8.895,2940,8.2,3300,11.372,3301,10.5,3302,11.372,3303,12.696,3304,12.696,3305,12.696,3306,12.696,3307,12.696,3308,3.29,3309,6.328,3310,8.2,3311,9.848,3312,11.372,3313,12.696]],["keywords/95",[]],["title/96",[100,325.812,358,221.971,947,513.501]],["content/96",[3,3.271,7,3.043,13,3.411,18,1.923,20,2.535,21,3.099,22,1.87,23,2.58,39,5.918,40,4.928,52,5.606,54,3.634,66,3.099,74,2.937,91,3.156,93,3.863,94,7.554,98,1.87,124,2.183,131,2.458,141,4.556,145,2.223,153,2.535,159,4.327,160,5.991,167,2.496,184,3.556,185,3.368,190,4.251,216,1.61,222,3.343,229,3.894,233,2.384,245,2.607,250,3.803,300,3.343,307,4.695,308,1.896,319,2.616,374,2.183,402,2.535,413,5.346,417,5.776,418,2.937,431,3.343,449,2.458,456,2.658,483,2.745,543,2.615,605,3.279,624,1.632,630,2.838,675,4.339,725,4.125,726,3.744,744,3.411,766,2.937,798,2.42,820,3.216,822,4.598,914,9.839,947,9.372,968,11.578,980,4.928,1088,9.846,1120,8.742,1134,4.096,1177,7.599,1178,3.992,1185,2.574,1284,3.216,1286,6.31,1307,4.754,1315,3.343,1322,3.803,1340,5.918,1372,4.457,1376,3.156,1432,3.156,1463,5.123,1466,3.156,1583,3.803,1686,6.583,1706,3.482,1712,7.208,1748,9.32,1810,5.346,1846,4.327,1848,5.346,1896,3.482,1911,4.457,1969,4.327,1988,10.369,2244,5.918,2352,5.346,2354,5.123,2371,6.834,2384,5.606,2400,4.598,2555,4.928,2736,5.617,3308,3.835,3314,6.834,3315,5.123,3316,5.918,3317,7.63,3318,11.27,3319,5.346,3320,7.63,3321,6.31,3322,7.63,3323,7.63,3324,7.63,3325,7.63,3326,7.63,3327,5.155,3328,14.8,3329,9.937,3330,13.256,3331,13.256,3332,11.27,3333,7.63,3334,6.834,3335,6.834,3336,14.8,3337,7.63,3338,7.63,3339,4.928,3340,7.63,3341,7.63,3342,7.63,3343,7.63,3344,3.556,3345,13.401,3346,8.28,3347,7.63,3348,6.834,3349,7.63,3350,5.346,3351,7.63,3352,7.63,3353,7.63,3354,6.31]],["keywords/96",[]],["title/97",[100,250.139,608,246.084,2235,539.245,2621,466.741,3355,539.245]],["content/97",[2,4.004,3,2.575,7,1.626,13,5.62,16,3.195,17,2.632,18,1.027,20,2.947,21,3.603,22,2.55,23,2.031,27,4.049,34,1.375,39,3.162,40,6.718,41,1.822,45,1.822,52,6.518,53,5.279,54,1.941,58,4.272,66,1.655,67,3.162,68,1.718,73,2.515,74,1.569,86,1.584,89,5.084,91,4.8,93,3.977,94,5.309,95,2.457,96,2.632,98,3.276,100,1.467,104,3.415,108,4.8,115,3.265,116,2.225,118,2.132,120,3.162,124,2.976,130,3.195,131,2.208,134,1.686,135,2.35,136,4.272,137,1.941,140,2.031,141,4.114,145,2.052,153,1.354,162,4.422,164,4.558,168,3.651,169,3.651,170,4.321,179,1.491,184,1.9,185,3.109,187,2.995,188,4.049,190,3.3,201,4.272,202,3.371,209,4.427,212,1.293,215,4.848,216,1.872,222,5.084,229,2.08,233,2.772,239,2.116,244,2.737,245,1.334,265,3.3,266,1.86,273,2.737,274,2.457,303,2.457,307,2.175,308,2.884,312,2.902,317,4.132,319,2.548,333,2.639,336,2.836,344,1.86,358,0.999,365,1.786,374,2.976,375,2.995,376,2.457,377,3.129,381,2.031,382,1.491,390,2.995,402,3.455,417,4.244,449,2.208,454,2.836,456,1.42,459,1.9,480,2.995,481,3.499,483,1.467,484,2.031,512,2.188,524,1.42,526,1.626,543,3.566,554,4.132,608,1.443,613,1.822,623,1.375,624,1.898,627,2.381,630,2.55,635,3.065,680,1.9,721,1.613,725,3.202,726,2.277,794,3.888,798,3.3,811,2.995,826,1.985,877,2.691,885,3.162,910,2.737,914,7.832,947,3.888,975,3.587,1020,2.247,1022,6.882,1049,2.54,1120,3.162,1163,2.54,1181,2.54,1185,2.994,1218,4.803,1221,2.632,1283,2.457,1284,3.74,1307,2.54,1316,2.737,1319,4.004,1320,2.08,1346,5.987,1372,2.381,1373,2.54,1395,3.587,1439,2.457,1440,6.931,1466,3.67,1520,3.162,1534,2.247,1535,2.632,1556,1.941,1565,3.265,1571,2.08,1593,3.74,1672,3.162,1673,2.856,1679,2.54,1690,3.371,1705,4.004,1706,1.86,1810,2.856,1846,2.311,1880,2.856,1886,3.371,1887,2.457,1898,2.856,1911,2.381,1969,2.311,1981,2.457,1985,2.995,2017,3.371,2026,1.941,2051,3.162,2235,5.318,2283,2.89,2340,2.247,2350,2.188,2352,2.856,2354,2.737,2355,5.318,2357,2.856,2363,2.132,2365,2.737,2386,3.651,2390,2.737,2448,3.162,2499,2.381,2517,3.371,2544,2.311,2555,4.427,2621,6.984,2628,2.856,2706,2.632,2717,3.651,2808,6.882,2825,3.888,2826,7.493,2853,2.856,2923,3.371,2940,2.632,3188,3.651,3190,3.651,3300,9.317,3301,3.371,3308,3.782,3310,4.427,3315,5.957,3321,8.602,3327,2.388,3329,6.984,3330,6.14,3331,9.317,3344,4.848,3350,2.856,3355,3.162,3356,6.882,3357,4.076,3358,6.14,3359,2.737,3360,2.188,3361,3.651,3362,3.371,3363,2.632,3364,3.651,3365,4.076,3366,12.569,3367,4.076,3368,5.318,3369,4.076,3370,5.669,3371,6.855,3372,4.076,3373,4.076,3374,5.037,3375,5.735,3376,9.317,3377,4.076,3378,2.995,3379,4.427,3380,4.076,3381,4.076,3382,6.855,3383,4.076,3384,2.632,3385,4.076,3386,4.076,3387,4.076,3388,4.076,3389,4.076,3390,6.855,3391,3.651,3392,4.076,3393,4.076,3394,4.076,3395,4.076,3396,5.184,3397,4.076,3398,4.076,3399,4.076,3400,2.995,3401,10.402,3402,2.381,3403,4.076,3404,10.402,3405,3.651,3406,4.076,3407,8.872,3408,4.076,3409,10.402,3410,4.076,3411,4.076,3412,6.855,3413,6.855,3414,4.076,3415,4.803,3416,3.651,3417,3.651,3418,4.603,3419,2.995,3420,4.076,3421,4.076,3422,4.076,3423,4.076,3424,4.076,3425,3.651,3426,4.076,3427,4.076,3428,3.371,3429,4.076,3430,6.14,3431,2.856,3432,4.076,3433,4.076,3434,4.076,3435,4.076,3436,4.076]],["keywords/97",[]],["title/98",[1311,715.826]],["content/98",[3,2.977,11,7.185,21,4.165,23,2.348,41,4.585,53,3.111,62,6.623,68,4.323,73,2.48,75,6.886,77,6.181,86,2.158,94,5.235,104,3.948,116,2.194,118,7.271,124,2.934,125,4.764,130,4.78,137,4.885,140,5.111,145,2.023,147,5.655,173,6.886,191,4.885,208,3.111,217,5.655,233,3.205,239,2.446,256,4.09,265,3.815,279,7.185,289,3.407,308,2.549,346,6.09,358,2.514,359,5.991,374,2.934,524,3.572,623,4.689,624,3.372,766,3.948,794,5.816,797,4.995,798,3.253,833,4.407,874,6.342,877,4.215,913,5.655,947,5.816,1119,7.094,1163,6.391,1179,7.535,1185,3.46,1313,8.481,1320,5.235,1333,4.09,1335,7.955,1346,4.885,1463,6.886,1466,4.243,1593,4.323,1706,4.68,1712,4.995,1837,7.185,1903,9.208,1911,5.991,1970,7.955,2253,8.481,2316,6.886,2355,7.955,2499,5.991,2506,7.535,2544,5.816,2556,8.481,2657,7.185,2969,8.481,3308,4.576,3309,5.111,3315,6.886,3316,7.955,3363,6.623,3368,7.955,3418,9.331,3437,10.255,3438,8.481,3439,6.623,3440,10.255,3441,10.255,3442,7.955,3443,10.255,3444,9.186,3445,7.535,3446,10.255,3447,6.623,3448,10.255,3449,8.481,3450,7.185,3451,8.481,3452,10.255,3453,10.255,3454,10.255]],["keywords/98",[]],["title/99",[83,528.917,1983,584.8,3455,564.238]],["content/99",[]],["keywords/99",[]],["title/100",[21,252.952,1119,317.912,1125,436.376,2780,515.098,3455,388.117,3456,457.62]],["content/100",[10,8.968,18,3.409,21,5.493,73,3.271,83,9.709,111,8.736,124,5.37,145,2.668,191,6.443,201,8.429,215,6.305,233,4.227,245,2.632,266,6.173,294,8.736,308,3.362,328,6.048,404,5.3,512,7.261,721,3.91,725,4.164,1189,5.3,1565,6.443,1583,6.742,1600,10.735,1854,5.928,2245,11.187,2263,11.187,2835,9.082,2899,11.187,3370,11.187,3455,8.429,3456,9.938,3457,13.527,3458,13.527,3459,13.527,3460,9.477]],["keywords/100",[]],["title/101",[83,459.424,3455,490.104,3461,786.514,3462,786.514]],["content/101",[3,3.082,23,2.431,34,3.583,83,9.372,86,1.258,89,4.653,127,8.757,142,4.955,145,2.806,153,4.726,212,3.368,216,2.241,219,3.527,239,3.393,262,7.439,273,7.129,275,3.758,292,7.129,293,8.781,300,4.653,308,2.639,369,7.439,382,3.884,413,7.439,483,3.82,526,4.235,624,3.043,721,3.347,766,4.088,798,3.368,799,8.068,877,3.22,1178,5.555,1185,4.8,1223,5.555,1284,4.476,1315,4.653,1322,5.292,1332,7.801,1350,5.555,1402,3.95,1447,7.129,1525,6.202,1556,5.057,1705,6.202,1706,4.846,1890,6.857,1892,5.854,2029,7.801,2138,8.612,2230,7.439,2615,9.51,2736,7.09,3368,8.236,3431,7.439,3439,6.857,3455,11.462,3463,12.742,3464,8.781,3465,10.618,3466,8.781,3467,11.765,3468,10.618,3469,10.618,3470,9.51,3471,9.51,3472,10.618,3473,10.618,3474,10.618,3475,11.765,3476,8.781,3477,10.618,3478,9.51,3479,10.618,3480,9.51,3481,8.781,3482,12.445,3483,5.7,3484,10.618,3485,9.51,3486,10.618,3487,10.618,3488,9.51]],["keywords/101",[]],["title/102",[360,507.965,1983,507.965,3455,490.104,3456,577.87]],["content/102",[3,2.803,20,3.208,22,2.367,23,2.211,45,4.317,56,8.311,74,3.718,83,5.641,86,2.049,98,2.367,104,3.718,124,2.763,125,4.572,127,4.501,140,8.912,141,4.106,142,4.646,153,3.208,184,7.121,188,4.407,212,4.847,217,5.325,219,3.208,233,4.168,245,1.879,262,6.766,265,3.592,273,6.483,289,3.208,316,5.845,346,6.695,404,5.986,416,4.501,481,4.929,499,3.258,543,3.31,624,2.066,697,5.184,720,5.135,721,3.876,725,4.106,761,6.017,827,4.929,978,8.311,989,6.237,1000,6.766,1013,6.237,1224,8.038,1333,3.851,1346,4.6,1565,4.6,1578,6.496,1580,8.65,1595,6.483,1600,6.237,1630,6.483,1665,11.03,1683,7.491,1703,7.095,1705,5.641,1854,4.232,1866,5.82,1887,8.038,1892,8.424,1894,9.799,1953,8.65,1976,7.491,1977,10.258,1981,5.82,1983,11.167,2138,5.184,2273,6.017,2319,10.346,2352,6.766,2622,7.986,2656,6.483,3439,6.237,3455,8.311,3456,9.799,3460,11.544,3475,7.986,3476,7.986,3489,9.799,3490,7.491,3491,8.65,3492,9.657,3493,9.657,3494,9.657,3495,8.65,3496,11.03,3497,8.65,3498,5.82,3499,8.65]],["keywords/102",[]],["title/103",[289,354.397,697,572.688]],["content/103",[3,3.874,18,3.363,22,3.272,23,1.735,53,2.298,73,1.832,74,4.317,83,9.196,86,1.748,91,4.638,104,2.917,109,3.609,110,5.866,116,1.621,125,2.597,127,3.532,134,5.521,140,3.777,141,2.333,145,2.211,153,2.517,208,4.474,217,4.178,219,3.725,275,3.969,289,3.725,300,3.32,307,4.234,308,3.317,309,4.567,312,2.478,315,4.894,319,2.864,344,3.458,346,3.32,357,4.393,365,3.32,402,2.517,444,7.856,447,4.171,454,3.135,499,2.557,508,3.458,574,3.691,624,1.621,625,6.464,630,2.819,675,2.917,697,6.019,705,6.787,743,4.894,801,4.722,802,4.722,820,3.194,825,6.266,826,3.691,1125,7.856,1189,2.969,1264,6.758,1332,5.567,1347,5.878,1392,5.567,1436,5.309,1686,4.426,1706,5.117,1712,3.691,1838,5.567,1854,3.32,1893,6.266,1903,4.426,1977,5.087,1983,11.016,1991,6.787,2023,4.426,2354,5.087,2656,5.087,2938,6.266,3115,6.266,3374,10.837,3439,4.894,3460,10.334,3464,9.273,3471,6.787,3495,10.043,3496,12.199,3497,10.043,3500,7.577,3501,11.212,3502,4.894,3503,7.577,3504,7.577,3505,7.577,3506,7.577,3507,5.309,3508,7.577,3509,7.577,3510,7.577,3511,7.577,3512,7.577,3513,7.577,3514,13.346,3515,7.577,3516,5.309,3517,6.787,3518,7.577,3519,11.954,3520,7.577,3521,10.043,3522,7.577,3523,14.765,3524,7.577,3525,11.212,3526,7.577,3527,7.577,3528,6.266,3529,7.577,3530,7.577,3531,7.577,3532,7.577,3533,10.043,3534,7.577,3535,12.212,3536,7.577,3537,7.577,3538,7.577,3539,10.043,3540,10.043,3541,8.697,3542,7.577,3543,6.787,3544,6.787,3545,5.567,3546,5.878,3547,6.266,3548,6.787,3549,7.577,3550,6.787,3551,7.577]],["keywords/103",[]],["title/104",[985,605.017,3550,955.587]],["content/104",[13,3.777,18,2.129,23,3.252,54,5.781,68,3.561,83,7.09,86,1.438,91,3.495,98,2.071,113,5.672,124,2.417,125,2.896,137,5.781,141,4.373,145,1.666,154,3.091,164,3.702,170,4.115,184,6.622,185,2.525,198,8.563,212,2.68,216,2.998,219,2.806,239,2.895,245,1.644,256,3.369,299,4.935,300,3.702,305,6.35,337,7.316,346,5.319,374,3.473,381,4.211,499,4.794,507,5.919,508,5.539,526,3.369,605,5.216,624,3.663,625,5.319,626,4.935,721,1.988,764,3.561,797,8.011,826,5.912,978,8.852,1020,6.693,1049,5.264,1118,7.567,1181,5.264,1189,3.31,1221,5.456,1332,8.918,1333,4.841,1432,5.021,1436,5.919,1477,6.195,1566,5.456,1709,4.115,1710,5.672,1782,4.115,1837,5.919,1854,3.702,1866,7.316,1891,15.802,1911,4.935,1966,7.564,1967,6.987,1969,6.884,1977,12.119,1983,11.872,2058,7.567,2263,6.987,2314,5.919,2360,4.935,2399,7.567,2455,6.553,2482,7.567,2546,6.207,2548,6.553,2628,8.504,2969,6.987,3321,6.987,3418,8.149,3456,6.207,3460,11.997,3476,6.987,3482,6.553,3485,7.567,3489,6.207,3535,9.415,3548,10.872,3552,8.448,3553,8.448,3554,8.448,3555,12.138,3556,8.448,3557,8.448,3558,8.448,3559,8.448,3560,8.448,3561,12.138,3562,8.448,3563,5.919,3564,5.919,3565,8.448,3566,6.553,3567,6.987,3568,8.448,3569,8.448,3570,7.567,3571,8.448,3572,6.207,3573,7.567]],["keywords/104",[]],["title/105",[185,270.628,239,215.958,1510,702.378]],["content/105",[8,2.92,13,2.62,23,1.341,53,1.777,68,2.47,83,5.382,86,1.53,91,4.71,98,1.436,127,2.731,135,2.009,140,2.92,141,2.836,153,1.946,167,1.916,179,2.143,208,2.795,219,1.946,239,1.397,245,1.14,260,3.784,265,2.18,307,2.923,319,2.848,337,3.531,346,4.037,358,3.958,367,4.488,369,6.455,374,1.676,382,2.143,402,4.288,431,4.99,444,4.105,447,4.236,454,2.424,456,3.966,459,4.294,473,4.105,483,3.315,525,3.784,526,2.337,605,3.959,608,3.261,613,6.662,625,2.568,630,2.18,720,3.547,735,5.248,797,2.854,820,4.8,826,2.854,877,1.777,908,4.105,913,6.278,1012,4.305,1125,4.105,1290,3.784,1307,3.651,1315,2.568,1328,3.531,1329,3.531,1400,4.846,1432,2.424,1440,3.231,1510,4.545,1520,4.545,1565,2.791,1612,4.545,1696,3.423,1703,4.305,1706,2.674,1761,5.248,1890,3.784,1894,4.305,1977,8.667,1983,10.726,2021,5.248,2118,6.769,2138,4.946,2285,3.784,2314,4.105,2504,9.484,2541,4.545,2834,4.846,2841,7.147,3110,4.846,3258,8.253,3319,6.455,3374,10.947,3439,3.784,3455,7.095,3463,5.248,3464,4.846,3466,4.846,3467,4.846,3470,5.248,3483,6.929,3496,13.353,3519,10.199,3521,8.253,3523,8.253,3533,5.248,3535,8.832,3539,11.562,3540,10.199,3541,10.013,3545,10.311,3574,5.248,3575,5.859,3576,5.859,3577,3.784,3578,5.859,3579,6.278,3580,5.859,3581,9.214,3582,5.859,3583,11.386,3584,8.253,3585,4.545,3586,5.859,3587,5.859,3588,5.859,3589,11.386,3590,9.214,3591,5.859,3592,3.934,3593,5.859,3594,5.859,3595,5.859,3596,11.386,3597,15.781,3598,10.199,3599,12.908,3600,12.908,3601,16.146,3602,5.859,3603,5.859,3604,9.214,3605,9.214,3606,9.214,3607,5.859,3608,9.214,3609,5.859,3610,9.214,3611,5.859,3612,5.859,3613,5.859,3614,5.859,3615,5.859,3616,5.859,3617,5.859,3618,5.859,3619,5.859,3620,5.859,3621,9.214,3622,5.859,3623,5.859,3624,5.859,3625,5.859,3626,5.859,3627,5.859,3628,5.859,3629,15.587,3630,5.859,3631,5.859,3632,9.214,3633,5.859,3634,9.214,3635,5.859,3636,5.859,3637,5.859,3638,5.859,3639,14.034,3640,5.859,3641,5.859,3642,5.859,3643,5.859,3644,5.859,3645,5.859,3646,5.859,3647,4.545,3648,5.248,3649,4.846]],["keywords/105",[]],["title/106",[1311,715.826]],["content/106",[18,2.601,22,3.421,23,2.362,34,5.336,54,4.915,57,5.539,68,5.883,79,4.043,83,9.237,86,1.874,100,3.713,115,4.915,124,2.953,125,3.537,134,4.269,140,5.143,145,2.753,167,3.375,190,3.274,201,6.43,216,2.178,239,2.461,273,9.37,275,3.653,277,5.852,289,3.428,381,5.143,405,15.086,483,3.713,499,3.482,624,3.383,625,6.116,668,8.005,675,3.973,697,5.539,721,3.283,764,4.35,798,5.017,799,5.852,826,6.797,827,5.267,874,4.71,877,3.13,913,5.69,1049,6.43,1119,5.267,1163,6.43,1169,6.22,1178,5.399,1185,3.482,1284,5.883,1290,6.665,1307,6.43,1333,4.116,1346,4.915,1525,6.028,1610,9.243,1696,6.028,1699,6.928,1846,5.852,1854,4.522,1892,5.69,1977,9.37,1983,11.43,2138,8.489,2196,9.243,2273,6.43,2826,6.665,3311,8.005,3350,7.23,3363,6.665,3439,6.665,3455,6.43,3460,11.079,3478,9.243,3535,8.005,3541,8.005,3650,10.319,3651,10.319,3652,10.319,3653,14.637,3654,8.005,3655,10.319,3656,10.319,3657,10.319]],["keywords/106",[]],["title/107",[10,392.002,3299,650.452,3658,704.484,3659,704.484]],["content/107",[]],["keywords/107",[]],["title/108",[106,507.965,350,374.625,358,192.807,3660,610.095]],["content/108",[7,4.588,22,2.82,23,3.821,54,5.479,55,7.724,86,1.978,106,11.849,107,10.071,116,2.461,124,4.292,127,5.362,135,3.943,203,8.923,212,3.65,216,3.166,239,2.744,274,10.06,275,4.072,276,9.041,316,5.041,350,5.479,409,4.139,430,6.092,456,4.007,484,5.734,605,4.943,630,4.28,726,4.983,744,5.143,764,4.849,798,3.65,873,8.452,1185,3.882,1189,4.507,1376,4.759,1534,6.343,1571,7.656,1593,4.849,1685,6.524,1896,7.618,1933,8.452,2026,5.479,2068,5.603,2292,5.603,2340,6.343,2344,7.43,2736,5.734,3070,7.168,3312,10.304,3660,11.636,3661,6.933,3662,6.175,3663,11.504,3664,11.504,3665,8.06,3666,11.504,3667,11.504,3668,10.304,3669,11.504,3670,10.304,3671,11.504,3672,11.504,3673,11.504,3674,11.504,3675,11.504,3676,9.514,3677,8.923,3678,11.504]],["keywords/108",[]],["title/109",[3,163.761,10,281.174,350,268.71,608,199.702,3308,146.175,3662,302.835,3679,311.066]],["content/109",[2,7.064,7,4.823,8,6.027,10,7.721,22,2.964,23,2.768,27,5.519,45,5.407,73,2.924,104,5.964,107,8.119,116,2.587,130,5.636,145,3.056,159,6.858,245,2.353,265,4.499,269,10.401,316,5.299,319,2.783,358,2.964,447,4.499,454,5.003,608,4.281,624,2.587,630,4.499,637,7.064,664,7.288,764,5.098,1163,7.535,1623,8.885,1686,7.064,1896,5.519,2068,5.89,2110,10.831,2390,8.119,2899,10.001,3308,4.014,3660,12.017,3662,8.316,3668,13.876,3679,8.542,3680,10.831,3681,12.812,3682,10.001,3683,8.885,3684,10.831,3685,12.093,3686,12.093,3687,12.093,3688,10.831,3689,12.093,3690,10.001,3691,15.492,3692,12.093,3693,11.382]],["keywords/109",[]],["title/110",[7,277.257,350,331.12,418,267.63,455,487.052,3661,418.984]],["content/110",[3,5.014,7,4.931,10,6.162,18,3.116,27,7.171,45,5.528,54,5.889,58,7.704,73,3.799,127,5.763,130,5.763,143,6.817,156,7.452,179,4.523,216,2.609,284,11.074,308,4.293,312,5.945,316,5.418,319,2.48,357,4.844,358,3.031,409,4.449,430,5.021,447,4.6,454,5.115,455,8.662,459,5.763,721,2.909,833,5.313,1119,8.02,1258,5.763,1618,7.452,1679,7.704,1896,5.643,2027,8.662,2541,9.591,2555,7.985,2736,6.162,3396,6.162,3400,9.084,3489,9.084,3579,6.817,3661,10.954,3680,11.074,3681,10.225,3682,10.225,3694,12.995,3695,12.364,3696,12.364,3697,14.074]],["keywords/110",[]],["title/111",[104,239.785,145,122.846,265,231.708,350,296.668,613,278.47,1854,272.94]],["content/111",[10,5.578,20,3.718,22,2.744,45,5.004,64,5.331,73,3.562,77,6.746,84,4.63,86,1.746,93,5.999,104,5.672,116,2.394,127,8.702,130,5.217,131,3.605,144,9.256,145,2.906,153,3.718,190,3.551,216,2.362,245,2.178,261,6.974,265,5.481,312,3.661,316,4.905,319,2.513,358,2.744,382,5.39,416,5.217,430,4.545,447,4.164,454,4.63,484,5.578,526,4.464,608,3.962,624,2.394,638,6.746,764,4.718,1223,5.856,1349,6.171,1445,7.842,1477,5.713,1704,6.746,1705,6.538,1854,4.905,2027,7.842,2065,8.223,2147,6.746,2733,8.682,3308,2.9,3327,3.898,3649,9.256,3661,10.548,3662,7.909,3679,8.124,3684,10.025,3690,12.184,3698,14.733,3699,8.223,3700,9.256,3701,7.229,3702,11.192,3703,11.192,3704,11.192,3705,11.192,3706,11.192,3707,9.256,3708,14.733,3709,11.192,3710,11.192,3711,11.192]],["keywords/111",[]],["title/112",[265,292.594,289,261.271,350,374.625,365,344.662]],["content/112",[8,4.461,10,6.304,18,2.256,22,3.908,23,2.049,68,3.773,73,3.058,91,3.703,98,2.194,104,3.446,111,5.781,116,3.734,127,5.896,130,4.172,135,3.068,137,4.264,141,2.756,144,7.403,145,1.765,153,2.973,159,7.173,167,5.214,179,4.627,180,8.169,184,6.837,185,3.78,190,5.057,198,6.974,208,2.715,212,2.84,229,4.569,256,3.57,265,4.705,276,8.841,286,5.076,289,4.873,308,2.225,312,2.928,316,3.923,319,1.816,344,5.773,374,3.619,409,3.221,416,4.172,459,4.172,484,4.461,485,5.578,508,4.085,526,3.57,624,1.915,626,5.229,664,5.395,726,2.973,743,5.781,764,7.089,798,2.84,1012,6.577,1119,4.569,1182,6.271,1189,3.507,1206,7.403,1258,4.172,1314,6.943,1321,6.577,1322,4.461,1349,4.936,1448,8.018,1466,3.703,1556,4.264,1565,4.264,1571,7.487,1609,6.01,1862,6.943,1892,4.936,1970,6.943,2068,4.36,2283,3.773,2297,7.403,2340,6.974,2624,6.01,2650,6.271,2825,5.076,2826,9.473,3308,2.319,3375,6.974,3384,9.473,3396,4.461,3402,7.388,3450,6.271,3564,6.271,3661,5.395,3662,4.805,3677,11.378,3679,4.936,3681,7.403,3683,9.293,3694,10.46,3712,8.951,3713,11.329,3714,8.018,3715,8.951,3716,8.951,3717,8.951,3718,8.018,3719,7.403,3720,8.951,3721,8.018,3722,12.131,3723,10.777,3724,6.943,3725,12.649,3726,8.951,3727,12.649,3728,8.951]],["keywords/112",[]],["title/113",[179,287.728,216,165.981,350,374.625,561,366.594]],["content/113",[3,3.164,10,5.432,22,3.549,23,2.495,27,5.955,45,4.873,53,2.212,58,6.791,73,3.746,84,3.017,86,0.864,104,5.573,106,4.71,109,3.474,116,3.477,127,3.399,130,6.747,137,5.191,141,2.245,145,2.855,179,3.987,185,2.18,187,5.359,210,5.657,216,2.3,233,3.406,245,2.121,265,4.854,282,4.396,307,3.457,308,3.243,312,2.386,319,2.935,333,2.808,336,3.017,344,3.328,350,3.474,377,3.328,409,2.624,422,3.915,430,2.962,447,2.713,449,3.51,454,4.508,456,2.54,524,2.54,596,2.808,624,2.791,630,4.854,635,3.261,721,3.07,726,2.423,764,6.102,808,6.533,826,3.552,877,2.212,978,4.545,979,4.26,1258,3.399,1284,3.074,1349,6.009,1376,3.017,1466,3.017,1583,5.432,1593,3.074,1696,4.26,1704,4.396,1721,4.396,1782,5.308,1848,5.11,1854,3.196,1896,3.328,1898,5.11,1969,4.136,2026,3.474,2147,4.396,2182,9.013,2316,4.897,2350,3.915,2357,5.11,2499,4.26,2621,4.897,2825,4.136,2905,5.11,3311,5.657,3316,5.657,3327,2.54,3329,4.897,3375,9.289,3384,8.427,3498,4.396,3516,5.11,3574,6.533,3660,8.454,3661,6.568,3662,7.771,3676,6.032,3679,7.982,3683,5.359,3690,6.032,3697,6.533,3700,6.032,3701,4.71,3714,6.533,3722,10.791,3723,5.359,3729,6.032,3730,7.293,3731,3.635,3732,7.293,3733,7.293,3734,7.293,3735,7.293,3736,7.293,3737,7.293,3738,6.032,3739,7.293,3740,7.636,3741,7.293,3742,7.293,3743,7.293,3744,7.293,3745,7.293,3746,7.293,3747,7.293,3748,7.293,3749,7.293,3750,7.293,3751,4.897,3752,10.142,3753,6.032,3754,7.293,3755,7.293,3756,9.142,3757,5.657,3758,5.657,3759,5.657,3760,5.359,3761,5.657,3762,6.032,3763,6.533,3764,6.533]],["keywords/113",[]],["title/114",[1696,459.424,3658,704.484,3659,704.484,3765,551.044]],["content/114",[]],["keywords/114",[]],["title/115",[108,325.369,164,344.662,358,192.807,1593,331.546]],["content/115",[13,3.204,16,3.34,18,2.711,21,2.911,79,2.808,84,2.965,85,10.817,86,1.275,91,4.45,93,2.457,94,7.325,108,4.45,115,3.414,116,2.301,125,2.457,130,5.014,135,2.457,140,6.436,141,2.206,160,3.204,164,3.141,190,2.274,222,6.739,256,2.858,275,2.537,308,1.781,312,3.518,319,2.97,333,2.759,386,7.49,417,5.25,422,3.847,456,2.496,459,3.34,481,3.658,508,3.271,613,3.204,670,5.266,798,2.274,811,10.544,1019,4.466,1181,4.466,1284,4.534,1320,3.658,1376,4.45,1392,5.266,1522,4.064,1526,4.812,1578,3.491,1583,3.572,1593,4.534,1630,4.812,1807,5.021,1880,10.054,1896,3.271,1966,4.466,1969,4.064,2072,8.344,2235,5.559,2350,3.847,2363,8.763,2388,11.868,2395,12.854,2512,5.927,2621,4.812,2629,5.927,2631,5.927,3109,8.344,3168,5.266,3308,3.718,3327,2.496,3329,4.812,3355,5.559,3359,4.812,3360,3.847,3375,3.952,3378,10.544,3379,9.268,3391,6.419,3516,5.021,3564,5.021,3752,7.536,3756,5.021,3757,5.559,3758,5.559,3759,5.559,3760,5.266,3761,10.016,3762,5.927,3763,6.419,3764,6.419,3765,5.021,3766,4.812,3767,6.419,3768,7.167,3769,7.167,3770,5.927,3771,5.927,3772,9.158,3773,7.536,3774,11.566,3775,12.912,3776,12.912,3777,12.912,3778,14.35,3779,11.868,3780,9.635,3781,9.635,3782,6.419,3783,9.635,3784,9.635,3785,6.419,3786,7.167,3787,7.167,3788,7.167,3789,5.559,3790,7.167,3791,4.629,3792,9.635,3793,6.419,3794,6.419,3795,7.167,3796,7.167]],["keywords/115",[]],["title/116",[45,310.809,164,304.637,608,246.084,3723,510.763,3797,466.741]],["content/116",[16,3.229,21,2.813,22,1.698,25,3.536,40,4.474,73,1.675,79,2.714,84,2.865,85,11.174,86,1.242,91,2.865,93,3.594,94,7.2,108,2.865,109,3.299,114,4.651,116,1.482,124,1.982,130,3.229,131,4.074,135,2.374,145,2.068,153,2.301,160,3.097,162,3.452,164,3.035,167,2.266,190,2.197,216,2.669,222,6.64,245,1.348,279,4.853,300,3.035,307,2.197,312,3.429,319,2.961,374,3,377,3.161,386,7.38,417,5.16,422,3.718,430,2.813,449,2.231,454,2.865,456,2.413,459,3.229,613,3.097,627,4.046,720,2.667,811,10.364,877,2.101,879,4.046,998,5.373,1019,4.316,1119,3.536,1178,3.624,1223,3.624,1321,5.089,1376,4.337,1402,3.9,1432,4.337,1522,3.928,1685,3.928,1697,4.046,1807,4.853,1846,3.928,1880,9.883,1896,3.161,1969,3.928,2095,6.204,2144,12.634,2246,4.316,2363,9.133,2384,11.133,2388,10.461,2745,6.204,3115,5.728,3308,2.716,3327,2.413,3329,4.651,3360,5.628,3375,6.975,3378,10.364,3379,9.786,3419,7.703,3428,8.67,3516,4.853,3564,4.853,3662,3.718,3679,3.819,3723,9.293,3752,4.853,3756,4.853,3757,5.373,3758,5.373,3759,5.373,3760,5.089,3761,8.132,3762,5.728,3766,4.651,3770,5.728,3772,9.389,3773,8.862,3774,11.33,3779,12.531,3780,9.39,3781,9.39,3782,6.204,3783,9.39,3784,9.39,3785,6.204,3791,4.474,3792,6.204,3797,4.651,3798,6.927,3799,6.927,3800,6.927,3801,6.927,3802,6.927,3803,6.927,3804,6.927,3805,6.927,3806,6.927,3807,12.649,3808,14.106,3809,6.927,3810,6.927,3811,6.927,3812,10.484,3813,6.204,3814,6.204]],["keywords/116",[]],["title/117",[164,396.796,418,348.594,3815,811.045]],["content/117",[2,5.091,21,5.04,22,3.543,66,3.539,73,3.495,84,3.605,85,9.493,86,1.713,91,3.605,95,5.253,108,5.134,115,4.151,116,1.864,124,3.551,130,4.062,131,3.998,162,4.344,164,3.819,179,3.188,212,2.765,222,3.819,233,2.723,303,7.48,312,4.728,319,2.799,336,3.605,344,5.664,374,4.136,377,3.977,386,4.245,422,4.678,430,3.539,454,3.605,455,6.106,456,3.036,459,4.062,499,2.941,509,7.208,554,5.253,626,5.091,630,3.242,721,3.401,726,2.895,833,7.153,877,2.643,879,7.25,978,7.734,1019,5.431,1174,7.806,1284,3.674,1348,5.629,1369,5.629,1399,5.253,1402,3.242,1685,4.942,1697,5.091,1806,5.629,1896,6.597,1969,4.942,2217,7.806,2283,3.674,2316,5.851,2318,4.942,2360,5.091,2363,7.562,2384,9.119,2397,6.76,2654,5.629,3308,3.216,3327,3.036,3329,5.851,3344,4.062,3358,7.806,3375,9.179,3417,14.911,3428,7.208,3516,6.106,3564,6.106,3579,4.806,3662,7.759,3679,7.97,3723,6.403,3752,6.106,3756,6.106,3757,6.76,3758,6.76,3759,6.76,3760,6.403,3761,12.218,3766,5.851,3770,7.208,3779,7.208,3813,7.806,3815,11.117,3816,7.208,3817,8.715,3818,8.715,3819,8.715,3820,8.715,3821,8.715,3822,12.411,3823,6.106,3824,8.715,3825,8.715,3826,8.715,3827,8.715,3828,8.715,3829,8.715,3830,8.715,3831,5.851,3832,8.715,3833,8.715,3834,8.715,3835,8.715,3836,8.715,3837,8.715,3838,8.715]],["keywords/117",[]],["title/118",[3839,1298.223]],["content/118",[10,7.029,16,7.947,20,4.685,73,3.41,145,2.782,160,6.306,164,6.18,219,4.685,223,6.06,233,4.407,250,7.029,256,5.625,275,4.992,374,4.035,508,6.436,630,5.247,743,9.109,744,6.306,1189,5.526,1216,9.109,1218,9.881,1571,7.199,1676,9.109,1878,12.633,2027,9.881,2359,10.362,2557,11.664,3840,11.664,3841,12.633,3842,14.103,3843,14.103,3844,14.103,3845,12.633,3846,14.103]],["keywords/118",[]],["title/119",[217,433.675,1711,610.095,3200,551.044,3308,203.791]],["content/119",[]],["keywords/119",[]],["title/120",[300,467.512,3847,955.587]],["content/120",[3,3.174,8,5.449,22,2.68,48,6.029,53,3.316,66,4.44,73,2.644,74,4.209,86,1.719,91,4.523,98,3.556,116,2.339,141,4.466,145,2.156,198,6.029,216,3.659,222,4.791,245,3.374,252,5.449,275,3.87,308,2.717,374,3.128,376,8.743,382,4,447,4.067,449,3.522,624,2.339,664,6.59,675,4.209,741,6.59,744,6.486,879,6.387,941,5.581,947,6.2,1049,6.813,1169,6.59,1178,5.72,1185,4.895,1322,7.23,1333,4.361,1340,8.481,1346,6.91,1376,4.523,1434,8.481,1439,6.59,1463,7.341,1578,5.325,1583,5.449,1697,6.387,1704,6.59,1712,7.066,1715,6.813,1837,7.66,1846,6.2,1987,9.793,2068,7.066,2250,7.66,2255,9.042,2354,7.341,2706,7.061,2736,5.449,2832,9.042,3104,11.997,3200,7.66,3308,2.833,3442,8.481,3450,7.66,3848,9.793,3849,10.933,3850,10.933,3851,9.793,3852,10.933,3853,10.933,3854,10.933,3855,10.933,3856,10.933,3857,10.933,3858,9.793,3859,10.933,3860,10.933,3861,10.933,3862,8.033,3863,7.341,3864,10.933,3865,10.933,3866,10.933]],["keywords/120",[]],["title/121",[3867,1066.856,3868,827.555]],["content/121",[7,2.662,16,3.111,18,1.682,21,4.14,22,3.031,23,1.528,53,3.092,54,4.855,55,4.482,64,3.179,68,4.297,86,1.766,93,3.494,96,4.311,98,3.031,100,2.402,116,3.695,117,4.482,124,2.916,125,2.288,131,2.15,134,2.761,135,2.288,140,5.08,141,4.589,145,2.439,153,4.597,156,4.023,160,2.984,162,3.327,164,2.925,173,4.482,175,5.979,190,2.118,193,4.904,201,4.16,212,4.391,216,2.609,232,4.904,233,4.325,239,2.431,244,4.482,245,2.406,252,3.327,256,2.662,273,4.482,281,4.904,292,4.482,300,2.925,307,2.118,319,1.463,333,2.57,353,3.899,365,2.925,374,3.96,377,3.046,406,5.52,430,2.711,431,2.925,473,4.677,481,3.407,485,4.16,510,5.178,524,2.325,605,2.868,624,2.645,625,2.925,627,3.899,664,4.023,680,5.763,720,3.924,744,4.557,764,2.814,787,4.482,794,5.78,798,3.234,871,4.751,877,2.025,894,7.141,913,5.62,928,7.141,958,5.52,980,4.311,985,3.785,1012,4.904,1028,9.592,1119,3.407,1181,4.16,1184,5.979,1185,2.252,1198,5.472,1205,4.904,1264,4.023,1284,2.814,1315,2.925,1319,3.899,1333,2.662,1334,4.023,1335,5.178,1369,4.311,1380,3.899,1395,3.492,1440,3.681,1463,4.482,1466,2.761,1502,5.178,1534,3.681,1565,4.855,1571,5.203,1578,3.251,1593,2.814,1676,4.311,1706,3.046,1710,6.844,1712,7.26,1839,4.904,1844,5.52,1846,5.78,2026,3.179,2035,5.178,2052,5.178,2068,3.251,2344,4.311,2350,3.583,2354,6.844,2499,5.954,2549,5.979,2706,4.311,2736,3.327,2744,8.43,2808,5.178,2836,4.904,2922,5.979,2940,4.311,2962,4.677,3028,9.13,3163,5.52,3184,5.178,3200,7.141,3308,4.072,3315,4.482,3346,10.169,3362,5.52,3442,7.907,3447,4.311,3502,4.311,3563,4.677,3572,4.904,3579,3.681,3719,5.52,3869,6.675,3870,6.675,3871,5.52,3872,6.675,3873,6.675,3874,6.675,3875,5.979,3876,6.675,3877,6.675,3878,6.675,3879,6.675,3880,6.675,3881,6.675,3882,10.193,3883,6.675,3884,6.675,3885,6.675,3886,5.178,3887,6.675,3888,6.675,3889,6.675,3890,6.675,3891,6.675,3892,6.675,3893,6.675,3894,5.52,3895,6.675,3896,6.675,3897,6.675,3898,6.675,3899,5.979,3900,6.675,3901,6.675,3902,4.904,3903,6.675,3904,6.675,3905,6.675,3906,6.675,3907,5.979,3908,6.675,3909,6.675,3910,6.675,3911,6.675,3912,6.675,3913,6.675,3914,6.675,3915,6.675,3916,6.675,3917,6.675,3918,6.675,3919,5.979,3920,6.675,3921,6.675,3922,6.675,3923,6.675,3924,6.675,3925,6.675,3926,5.979,3927,6.675,3928,5.979,3929,6.675]],["keywords/121",[]],["title/122",[86,107.292,3309,451.297,3930,905.483]],["content/122",[7,5.352,13,4.356,16,4.541,20,3.236,21,3.956,23,2.23,34,4.528,54,4.64,64,4.64,68,4.107,73,2.356,76,8.726,77,5.872,86,1.59,98,2.388,100,3.505,115,4.64,117,6.541,125,3.34,131,3.138,135,3.34,140,4.855,145,1.921,159,5.525,184,4.541,190,3.091,191,4.64,195,6.071,215,4.541,216,2.056,233,4.796,239,2.323,256,3.885,275,4.75,279,6.825,316,4.269,511,6.071,543,3.34,554,5.872,605,5.766,624,2.084,635,4.356,707,5.872,720,3.75,725,4.131,726,3.236,766,3.75,809,7.158,877,2.955,879,5.691,941,4.972,977,5.23,1129,9.401,1177,5.525,1189,3.817,1315,4.269,1322,4.855,1333,3.885,1335,7.557,1402,3.624,1578,4.745,1618,5.872,1696,5.691,1699,6.541,1702,7.557,1712,4.745,1854,4.269,1859,6.825,1988,6.825,2028,7.158,2068,8.448,2147,5.872,2292,6.535,2322,8.057,2340,5.372,3187,8.726,3200,9.401,3308,4.285,3315,6.541,3316,7.557,3418,6.541,3729,8.057,3851,8.726,3931,8.726,3932,9.742,3933,9.742,3934,9.742,3935,8.726,3936,13.418,3937,13.418,3938,15.349,3939,9.742,3940,9.742,3941,9.742,3942,9.742,3943,13.418,3944,9.742,3945,9.742,3946,9.742,3947,9.742,3948,9.742,3949,9.742,3950,9.742,3951,13.418,3952,8.726,3953,9.742,3954,9.742,3955,9.742,3956,9.742,3957,9.742,3958,9.742,3959,9.742,3960,8.726,3961,9.742,3962,8.726,3963,9.742]],["keywords/122",[]],["title/123",[380,748.84,3964,905.483,3965,905.483]],["content/123",[16,7.978,17,6.835,18,2.667,23,3.918,66,4.298,68,4.461,98,2.594,100,3.808,108,6.626,124,3.028,125,3.628,127,4.933,134,6.626,141,4.37,147,5.836,179,3.872,193,7.776,198,5.836,216,2.233,233,5.578,245,2.059,288,8.753,289,3.516,308,3.981,316,4.638,333,4.075,359,6.182,374,4.062,380,8.753,381,5.275,384,8.753,404,4.147,415,6.182,416,4.933,430,4.298,456,3.686,481,5.402,574,5.155,633,7.776,635,4.732,637,6.182,718,8.21,720,4.075,725,4.37,798,3.358,809,7.776,834,6.835,877,3.21,913,5.836,914,6.595,1322,5.275,1332,7.776,1346,5.041,1394,8.753,1402,5.281,1583,5.275,1696,6.182,1856,9.48,1859,7.415,1933,7.776,2336,6.835,2546,7.776,3498,6.379,3966,10.584,3967,10.584,3968,10.584,3969,7.776,3970,14.196,3971,16.018,3972,10.584,3973,9.48,3974,17.116,3975,10.584,3976,10.584,3977,10.584,3978,10.584,3979,9.48,3980,10.584,3981,10.584,3982,10.584,3983,10.584,3984,10.584,3985,10.584,3986,8.21,3987,10.584,3988,10.584,3989,10.584]],["keywords/123",[]],["title/124",[1311,588.253,3990,1066.856]],["content/124",[8,5.774,13,5.179,23,2.652,73,2.801,116,2.478,145,2.285,154,4.238,157,9.58,160,5.179,190,3.675,192,10.376,195,7.219,209,7.482,233,5.234,239,2.763,245,2.254,256,4.62,265,4.31,269,7.778,277,6.57,308,3.745,312,3.789,336,4.792,359,6.767,415,6.767,456,4.035,484,7.51,499,3.909,596,4.46,605,4.978,668,8.986,726,5.006,827,5.913,879,6.767,920,8.511,941,7.691,977,6.219,1134,6.219,1177,6.57,1181,7.219,1185,3.909,1223,6.061,1315,6.603,1333,4.62,1373,7.219,1376,4.792,1395,6.061,1430,9.58,1522,6.57,1673,8.116,1704,6.982,1846,6.57,2068,5.642,2143,10.376,2147,6.982,2269,8.986,2314,8.116,2716,9.58,2940,7.482,3200,8.116,3308,3.002,3354,9.58,3665,8.116,3677,8.986,3919,10.376,3969,11.071,3973,10.376,3991,11.584,3992,11.584,3993,11.584,3994,10.376,3995,11.584,3996,15.069,3997,11.584,3998,11.584,3999,11.584,4000,11.584]],["keywords/124",[]],["title/125",[29,610.095,3308,203.791,4001,786.514,4002,704.484]],["content/125",[0,8.118,2,1.496,3,3.984,6,2.458,7,1.826,8,4.326,9,3.551,10,3.764,16,2.134,17,1.654,18,2.187,19,1.452,20,0.851,21,1.04,22,1.122,23,2.396,25,1.307,27,2.089,28,3.074,29,9.599,34,1.545,45,1.145,47,9.599,52,1.882,53,0.777,62,1.654,66,1.04,68,3.659,70,7.178,73,1.107,74,1.762,79,1.794,81,2.458,86,1.669,89,2.006,91,3.124,93,2.975,94,5.342,95,4.552,96,1.654,98,2.363,100,4.252,104,1.762,106,2.957,107,3.074,108,1.059,110,2.395,111,1.654,116,1.857,117,1.72,118,5.043,120,4.815,124,2.758,125,0.878,127,5.213,130,1.194,131,2.433,134,1.059,135,0.878,136,3.868,141,3.443,142,0.892,145,1.489,147,3.423,149,6.533,152,2.957,153,0.851,157,2.118,158,1.596,159,5.935,161,5.858,162,1.276,164,3.309,167,2.03,170,1.247,179,4.092,180,1.654,183,2.118,185,1.855,186,2.118,190,0.812,191,4.134,208,1.389,210,4.815,215,1.194,216,1.31,217,1.412,219,0.851,221,4.561,222,1.122,223,1.967,228,2.118,229,2.337,232,3.364,233,3.867,236,1.987,239,1.801,245,0.891,246,1.544,249,2.957,250,3.764,251,4.101,252,1.276,253,3.364,265,3.229,269,4.168,274,1.544,275,3.705,281,1.882,282,2.759,286,1.452,288,3.786,289,4.425,294,1.654,295,2.294,299,1.496,300,1.122,307,0.812,308,2.396,312,1.497,319,2.07,328,1.145,333,0.986,336,1.059,350,2.181,360,1.654,374,3.811,375,1.882,381,1.276,382,3.175,384,5.134,386,2.23,402,0.851,404,1.003,415,2.674,416,2.134,417,0.937,430,1.04,431,1.122,456,0.892,474,1.34,484,2.282,499,1.545,508,2.089,511,1.596,512,2.458,514,1.544,524,0.892,526,1.021,543,2.128,574,2.23,596,1.762,624,1.615,625,1.122,630,2.809,633,1.882,635,1.145,675,1.762,725,2.672,726,2.509,744,1.145,764,1.08,797,1.247,798,3.058,799,2.596,804,2.294,809,1.882,827,1.307,828,1.987,833,1.101,874,1.169,877,2.633,878,2.294,885,8.118,913,2.524,937,2.294,968,1.794,977,3.332,988,1.882,1119,3.169,1120,1.987,1134,1.375,1135,2.72,1177,3.52,1178,3.951,1182,1.794,1183,1.794,1185,2.548,1186,2.294,1189,1.003,1199,1.412,1205,1.882,1206,2.118,1216,1.654,1221,4.009,1251,4.815,1284,3.659,1315,2.72,1316,5.07,1319,2.674,1320,1.307,1322,1.276,1333,3.462,1346,1.22,1347,1.987,1349,1.412,1350,1.34,1372,1.496,1373,2.853,1376,2.568,1380,1.496,1392,1.882,1394,2.118,1395,1.34,1396,4.101,1402,2.309,1403,1.882,1410,3.364,1434,4.815,1438,1.794,1440,1.412,1466,1.059,1500,1.794,1511,1.375,1522,1.452,1525,1.496,1534,4.786,1535,1.654,1556,1.22,1558,1.72,1565,2.957,1571,3.169,1576,3.551,1578,1.247,1593,1.93,1609,1.72,1612,1.987,1618,2.759,1630,1.72,1673,3.208,1676,1.654,1679,1.596,1686,2.674,1690,2.118,1706,1.169,1710,3.074,1715,1.596,1784,1.794,1803,1.987,1821,1.194,1833,2.118,1837,1.794,1846,1.452,1854,1.122,1890,1.654,1892,1.412,1896,2.833,1911,2.674,1963,2.294,1966,1.596,1988,3.208,2017,2.118,2028,1.882,2029,1.882,2065,1.882,2068,1.247,2072,1.987,2133,2.118,2147,1.544,2148,2.294,2204,2.294,2244,1.987,2246,1.596,2250,3.208,2273,1.596,2283,1.08,2284,2.294,2287,2.118,2299,2.118,2303,2.118,2323,4.101,2344,2.957,2352,1.794,2356,3.074,2357,1.794,2393,2.294,2481,5.56,2506,1.882,2541,1.987,2551,4.101,2617,2.118,2629,2.118,2643,1.496,2654,2.957,2664,1.987,2736,1.276,2838,2.294,2853,3.208,2938,2.118,2940,1.654,3184,1.987,3195,2.118,3197,2.294,3223,1.987,3279,2.118,3308,3.451,3309,2.282,3315,1.72,3344,1.194,3362,2.118,3363,2.957,3431,1.794,3438,2.118,3439,1.654,3449,2.118,3451,2.118,3491,2.294,3498,2.759,3502,1.654,3544,2.294,3546,1.987,3547,2.118,3563,1.794,3567,2.118,3682,2.118,3683,4.561,3693,1.882,3707,3.786,3713,2.294,3794,2.294,3823,1.794,3848,2.294,3935,2.294,4002,2.294,4003,2.561,4004,2.561,4005,2.561,4006,2.561,4007,2.561,4008,2.561,4009,2.561,4010,2.561,4011,2.561,4012,2.561,4013,2.561,4014,2.561,4015,2.561,4016,2.561,4017,2.561,4018,2.561,4019,2.561,4020,2.561,4021,2.561,4022,2.561,4023,2.561,4024,2.561,4025,4.578,4026,2.561,4027,2.561,4028,2.561,4029,15.006,4030,2.561,4031,2.561,4032,2.294,4033,2.561,4034,2.561,4035,2.561,4036,2.294,4037,2.561,4038,2.561,4039,2.561,4040,2.561,4041,2.294,4042,2.561,4043,2.561,4044,2.561,4045,2.561,4046,2.561,4047,2.561,4048,2.561,4049,2.561,4050,4.101,4051,16.769,4052,4.578,4053,2.561,4054,2.561,4055,2.561,4056,2.294,4057,2.561,4058,2.561,4059,2.561,4060,2.561,4061,2.561,4062,2.561,4063,2.561,4064,2.561,4065,2.561,4066,2.561,4067,2.561,4068,2.561,4069,9.25,4070,2.561,4071,7.178,4072,2.561,4073,2.561,4074,2.561,4075,2.561,4076,2.561,4077,6.208,4078,9.639,4079,2.561,4080,2.561,4081,2.561,4082,2.561,4083,2.294,4084,2.561,4085,2.561,4086,14.089,4087,2.561,4088,8.68,4089,2.561,4090,2.561,4091,2.561,4092,2.561,4093,2.561,4094,7.552,4095,2.561,4096,2.561,4097,2.561,4098,2.294,4099,7.552,4100,2.561,4101,2.561,4102,2.561,4103,2.561,4104,2.561,4105,2.561,4106,2.561,4107,2.561,4108,2.561,4109,2.561,4110,4.578,4111,4.578,4112,5.56,4113,4.578,4114,4.578,4115,4.578,4116,4.578,4117,4.578,4118,4.578,4119,2.561,4120,4.578,4121,4.578,4122,4.578,4123,4.578,4124,6.208,4125,2.561,4126,2.561,4127,4.101,4128,2.561,4129,2.561,4130,2.561,4131,4.578,4132,4.578,4133,2.561,4134,2.561,4135,2.561,4136,2.561,4137,1.452,4138,2.561,4139,2.561,4140,4.578,4141,2.561,4142,2.561,4143,2.561,4144,2.561,4145,2.561,4146,2.118,4147,2.561,4148,2.561,4149,2.561,4150,2.561,4151,2.561,4152,2.561,4153,2.561,4154,1.987,4155,2.561,4156,2.561,4157,2.561,4158,2.561,4159,7.552,4160,6.208,4161,2.561,4162,3.786,4163,2.561,4164,2.561,4165,2.561,4166,4.578,4167,4.578,4168,2.561,4169,2.561,4170,2.561,4171,4.578,4172,1.987,4173,2.561,4174,8.68,4175,7.972,4176,2.561,4177,4.578,4178,2.561,4179,2.561,4180,2.561,4181,2.561,4182,2.561,4183,2.561,4184,2.561,4185,2.561,4186,2.561,4187,2.294,4188,2.561,4189,2.294,4190,2.561,4191,2.561,4192,2.294,4193,2.561,4194,1.987,4195,4.578,4196,2.561,4197,2.561,4198,2.294,4199,2.561,4200,2.561,4201,2.118,4202,2.561,4203,2.561,4204,2.561,4205,2.561,4206,2.561,4207,2.561,4208,2.561,4209,2.561,4210,2.561,4211,2.561,4212,2.561,4213,2.561,4214,2.561,4215,2.561,4216,2.294,4217,2.561,4218,2.561,4219,2.561,4220,2.561,4221,2.561]],["keywords/125",[]],["title/126",[2706,507.965,3308,203.791,3363,507.965,4222,474.032]],["content/126",[]],["keywords/126",[]],["title/127",[344,413.24,3447,584.8,4222,545.735]],["content/127",[18,2.274,27,4.119,41,4.035,53,2.737,66,5.167,67,7,73,2.182,74,3.474,75,6.059,77,5.439,79,3.536,84,5.263,86,1.507,93,3.094,94,8.166,131,4.746,134,3.733,142,3.143,156,5.439,160,4.035,167,2.952,211,5.623,222,3.955,233,2.82,245,1.756,275,4.503,289,2.998,319,2.795,337,5.439,344,4.119,358,2.212,374,3.64,382,3.301,409,4.577,449,4.098,456,5.573,498,7.463,543,3.094,623,3.045,624,1.93,637,5.271,644,6.493,664,7.667,665,5.623,674,7.463,725,2.778,743,5.828,744,4.035,798,2.863,833,3.878,877,2.737,880,8.216,933,10.521,979,5.271,1178,4.721,1258,6.867,1284,3.804,1334,5.439,1466,3.733,1593,3.804,1697,5.271,1699,6.059,1782,4.395,1887,5.439,1892,4.976,2026,4.298,2027,6.323,2283,3.804,2322,7.463,2336,5.828,2643,5.271,2826,8.216,2905,6.323,3308,3.296,3319,6.323,3335,8.083,3344,5.93,3360,4.844,3447,11.303,3499,8.083,3546,7,3547,7.463,3584,8.083,3647,7,4137,5.118,4222,9.642,4223,9.024,4224,9.024,4225,9.024,4226,12.393,4227,9.024,4228,8.083,4229,11.395,4230,11.395,4231,12.722,4232,12.722,4233,9.024,4234,12.722,4235,9.024,4236,9.024,4237,12.722,4238,13.197,4239,7,4240,9.024,4241,9.024,4242,11.395,4243,9.024,4244,9.024,4245,9.024,4246,9.024]],["keywords/127",[]],["title/128",[156,418.984,222,304.637,337,418.984,1903,406.071,4222,418.984]],["content/128",[6,3.95,18,1.854,23,1.684,25,6.695,53,3.979,54,3.505,68,3.102,84,5.426,86,1.3,93,3.761,98,2.689,116,2.347,124,2.105,137,3.505,145,1.451,156,6.612,180,4.752,190,3.48,206,5.225,212,2.334,216,1.553,265,2.737,275,2.605,285,4.752,297,5.406,307,3.48,308,1.829,311,6.591,312,4.29,319,2.794,337,4.435,357,2.883,409,5.596,416,3.43,449,3.534,453,3.95,456,5.68,524,2.563,543,5.59,613,6.953,623,4.906,626,4.298,630,2.737,637,4.298,644,7.938,700,3.224,720,2.833,749,11.278,764,5.529,975,8.136,979,7.662,1013,4.752,1119,3.756,1185,2.483,1215,5.708,1284,3.102,1315,3.224,1320,5.6,1346,6.248,1500,5.155,1526,4.94,1535,4.752,1556,3.505,1709,3.584,1806,4.752,1903,8.493,2141,6.591,2283,3.102,2350,3.95,2504,5.406,2654,7.085,2968,9.826,3070,4.585,3308,3.767,3309,3.667,3327,3.821,3360,5.889,3400,5.406,3447,4.752,3564,5.155,3868,5.708,4194,5.708,4222,4.435,4226,8.06,4230,6.591,4238,9.826,4247,7.751,4248,7.358,4249,7.358,4250,7.358,4251,13.117,4252,6.591,4253,10.971,4254,10.971,4255,10.848,4256,17.364,4257,14.014,4258,12.65,4259,9.826,4260,6.085,4261,13.023,4262,11.278,4263,13.487,4264,14.607,4265,13.117,4266,5.708,4267,7.358,4268,7.358,4269,6.591,4270,6.591,4271,9.073,4272,10.971,4273,7.358]],["keywords/128",[]],["title/129",[1712,441.023,3402,528.917,4222,545.735]],["content/129",[3,1.957,17,4.355,18,1.699,25,3.442,53,5.255,68,4.33,73,2.484,84,4.249,89,2.955,93,3.521,98,1.653,116,1.442,127,3.143,131,2.172,135,2.312,141,2.076,153,3.412,160,4.593,162,3.361,184,3.143,185,3.07,195,7.754,206,4.893,212,2.139,216,1.423,222,2.955,223,2.898,239,1.608,245,1.312,262,4.724,285,4.355,286,3.824,289,3.412,299,3.939,300,2.955,307,2.139,312,2.206,319,2.844,358,1.653,370,3.62,374,2.939,409,5.006,416,3.143,417,2.467,431,2.955,449,3.309,456,4.846,499,4.198,512,3.62,514,4.064,543,5.408,574,3.284,624,2.662,626,3.939,630,2.509,644,8.053,680,3.143,725,2.076,744,3.015,749,5.231,798,2.139,811,4.954,820,2.843,880,4.355,913,5.664,947,3.824,979,3.939,1284,2.843,1315,2.955,1320,3.442,1346,6.627,1402,2.509,1511,3.62,1593,2.843,1683,5.231,1696,3.939,1706,3.077,1712,6.06,1784,4.724,1892,3.718,2244,5.231,2269,5.231,2344,6.634,2357,4.724,2628,4.724,2643,3.939,2826,6.634,2828,6.04,3109,5.231,3308,3.605,3311,5.231,3327,4.334,3344,4.788,3363,4.355,3379,4.355,3396,5.12,3402,7.268,3447,4.355,3450,4.724,3647,13.438,3721,6.04,3731,5.12,3823,4.724,3926,6.04,3994,6.04,4071,5.577,4222,7.499,4247,6.202,4257,9.652,4258,10.792,4259,6.04,4260,5.577,4270,6.04,4271,8.495,4274,6.743,4275,6.743,4276,10.272,4277,6.743,4278,6.743,4279,6.04,4280,6.743,4281,6.743,4282,9.142,4283,9.201,4284,6.743,4285,6.04,4286,6.743,4287,5.577,4288,6.743,4289,6.743,4290,6.743,4291,6.743,4292,6.634,4293,6.743,4294,6.743,4295,10.272,4296,12.443,4297,6.743,4298,6.743,4299,6.04,4300,6.743,4301,6.743,4302,6.743,4303,6.743,4304,10.272,4305,6.743,4306,6.743,4307,6.743,4308,6.743,4309,15.777,4310,6.743,4311,6.743,4312,6.743,4313,6.743,4314,6.743,4315,6.743,4316,6.743,4317,6.743,4318,6.743,4319,6.743,4320,6.743,4321,6.743,4322,6.743,4323,6.743,4324,6.743,4325,6.743,4326,6.743,4327,6.743,4328,6.743,4329,12.443,4330,6.743,4331,6.743,4332,6.743,4333,5.577]],["keywords/129",[]],["title/130",[1311,715.826]],["content/130",[22,3.161,45,5.765,68,5.435,73,3.118,116,2.758,131,4.153,212,5.119,222,5.65,223,5.541,256,5.142,266,5.884,308,3.205,374,3.689,480,9.473,514,7.771,623,4.351,700,5.65,726,4.283,1183,9.034,1284,5.435,1333,5.142,1402,4.797,1438,9.034,1463,8.657,1706,5.884,1712,6.28,1833,10.663,1887,9.724,1903,7.532,2094,9.473,2138,6.921,2180,10.663,2273,8.035,2360,7.532,2543,11.549,2643,7.532,2897,9.473,3308,4.181,3309,6.426,3356,10.002,3363,10.42,3488,11.549,3647,10.002,4222,9.724,4247,6.426,4279,11.549,4333,10.663,4334,12.894,4335,9.473,4336,12.894,4337,12.894,4338,12.894]],["keywords/130",[]],["title/131",[1292,607.94,1432,374.584,4339,702.378]],["content/131",[]],["keywords/131",[]],["title/132",[3648,1162.823]],["content/132",[3,3.174,7,5.786,18,3.656,41,4.888,89,4.791,111,7.061,113,7.341,124,3.128,125,3.748,152,7.061,187,8.033,212,3.469,216,3.061,217,6.029,223,4.698,233,3.417,252,5.449,256,4.361,265,5.397,276,6.59,308,2.717,374,3.128,377,4.99,382,4,453,5.869,482,10.164,483,3.934,623,5.851,625,6.357,635,4.888,670,8.033,720,4.209,726,3.632,827,5.581,871,5.096,1169,6.59,1189,4.284,1284,4.609,1556,5.208,1578,5.325,1584,8.481,1618,6.59,1712,7.93,1803,8.481,1848,7.66,1892,7.999,1976,8.481,2068,5.325,2094,8.033,2147,6.59,2728,8.481,2808,8.481,2835,7.341,3308,2.833,3348,9.793,3379,7.061,3405,9.793,3445,8.033,3566,8.481,3573,9.793,3701,7.061,3765,11.406,3789,8.481,3969,8.033,4339,8.481,4340,10.933,4341,7.341,4342,10.933,4343,10.933,4344,10.933,4345,10.933,4346,10.933,4347,9.793,4348,10.933,4349,10.933,4350,10.933,4351,10.933,4352,10.933,4353,5.338,4354,10.933,4355,10.933,4356,10.933,4357,10.933,4358,10.933,4359,10.933,4360,10.933]],["keywords/132",[]],["title/133",[266,413.24,744,404.835,4353,278.756]],["content/133",[8,6.999,66,5.703,74,5.407,86,2.015,116,3.004,216,2.964,250,6.999,266,7.761,285,9.07,319,2.016,447,5.224,676,10.318,1021,8.464,1315,6.154,1782,6.84,2352,9.839,3308,4.406,3344,6.546,3502,9.07,3899,12.579,4162,11.614,4353,4.323,4361,14.044,4362,14.044,4363,14.044,4364,14.044,4365,12.579,4366,14.044,4367,14.044,4368,14.044,4369,14.044,4370,9.839,4371,10.318]],["keywords/133",[]],["title/134",[289,354.397,4339,827.555]],["content/134",[34,4.699,54,6.633,91,5.761,106,8.994,107,9.349,110,7.285,118,7.285,127,6.491,145,3.337,167,5.534,319,1.999,429,12.473,459,6.491,624,2.979,664,8.393,1119,7.108,1182,9.756,1315,6.102,1534,7.678,1558,11.359,2246,8.677,2283,5.87,2318,7.897,2346,9.756,3223,10.802,3665,9.756,3670,12.473,3694,11.516,4339,13.124,4372,13.925,4373,13.925,4374,13.925,4375,13.925,4376,13.925]],["keywords/134",[]],["title/135",[1709,519.621,4377,1066.856]],["content/135",[20,4.107,25,8.02,53,5.239,66,5.021,73,2.989,84,5.115,86,1.862,89,5.418,98,3.031,139,11.074,142,4.307,147,6.817,154,4.523,167,5.139,185,3.695,216,2.609,230,8.662,244,8.301,245,2.406,275,4.377,308,3.073,312,4.044,374,3.537,382,5.748,416,5.763,492,7.985,508,5.643,543,4.238,623,5.302,624,3.361,630,4.6,877,3.75,1135,7.569,1169,7.452,1177,7.012,1334,7.452,1350,9.037,1372,7.222,1410,11.545,1438,8.662,1477,6.311,2283,5.212,2557,10.225,3291,10.55,3765,8.662,4353,5.317,4378,12.364,4379,11.074,4380,12.364,4381,12.364,4382,12.364,4383,10.225]],["keywords/135",[]],["title/136",[700,467.512,3969,783.844]],["content/136",[6,7.891,18,2.811,27,5.091,45,4.987,73,2.697,75,7.489,84,4.615,86,1.948,116,2.386,147,6.151,153,3.705,159,6.326,167,4.808,178,9.991,179,4.081,212,3.539,245,2.86,250,5.56,300,4.888,319,2.608,413,7.815,417,4.081,512,7.891,543,3.824,596,5.659,608,3.949,623,4.96,633,8.196,638,9.91,834,10.619,920,12.081,928,11.52,947,6.326,1020,6.151,1128,9.991,1350,5.836,1593,4.702,1685,6.326,1803,8.653,2283,4.702,2330,8.196,2616,7.204,3163,9.225,3327,3.885,3724,11.403,3731,5.56,3740,7.815,3969,10.801,4353,5.381,4379,9.991,4384,11.155,4385,11.155,4386,11.155,4387,11.155,4388,11.155,4389,11.155,4390,11.155,4391,11.155,4392,11.155,4393,11.155,4394,11.155,4395,11.155,4396,11.155,4397,11.155,4398,7.489,4399,11.155,4400,11.155,4401,9.991,4402,11.155,4403,11.155,4404,11.155,4405,11.155]],["keywords/136",[]],["title/137",[1311,715.826]],["content/137",[7,5.824,13,6.528,23,3.343,86,1.73,137,6.955,149,8.529,152,9.43,195,9.099,219,4.85,252,7.277,404,5.721,454,6.04,508,6.664,623,4.927,798,4.632,977,7.838,1185,4.927,1583,7.277,1782,7.112,2094,10.728,2283,6.155,4353,4.495,4406,14.602,4407,14.602,4408,14.602,4409,14.602,4410,14.602]],["keywords/137",[]],["title/138",[4353,278.756,4411,607.94,4412,811.045]],["content/138",[]],["keywords/138",[]],["title/139",[4353,399.662]],["content/139",[7,5.969,20,3.808,55,7.697,62,7.404,72,7.404,86,1.358,89,5.024,116,3.564,118,5.998,134,4.742,148,8.423,149,6.696,208,3.477,217,6.321,239,2.734,244,10.048,245,3.242,261,7.144,275,4.058,305,5.998,328,5.125,344,5.232,374,3.28,508,5.232,624,3.564,725,4.607,726,3.808,885,8.893,985,6.501,1016,5.343,1049,9.326,1135,5.024,1216,7.404,1321,8.423,1402,5.568,1556,7.129,1558,7.697,1571,5.851,1697,6.696,1981,6.909,2030,8.032,2255,9.481,2283,4.832,2619,10.268,2666,9.481,2836,8.423,2957,8.893,3308,3.878,3363,7.404,3699,8.423,3791,9.666,3962,10.268,4353,5.786,4413,11.464,4414,11.464,4415,11.464,4416,6.909,4417,11.464,4418,11.464,4419,11.464,4420,11.464,4421,11.464,4422,11.464,4423,11.464,4424,11.464,4425,11.464,4426,11.464,4427,9.481,4428,11.464,4429,11.464]],["keywords/139",[]],["title/140",[185,318.859,358,261.53]],["content/140",[86,1.723,131,4.683,319,2.665,623,4.905,725,4.475,726,4.829,1198,7.804,1525,8.492,1704,8.762,1784,10.185,2138,7.804,2544,8.244,3308,3.767,3327,5.064,3699,10.681,3753,12.022,3766,9.76,3831,9.76,4263,12.022,4353,4.475,4430,12.757,4431,12.022,4432,12.164,4433,14.537]],["keywords/140",[]],["title/141",[185,318.859,608,377.653]],["content/141",[23,3.201,53,4.242,98,3.428,124,4.001,131,4.504,239,3.335,263,11.565,265,5.202,319,2.621,374,4.001,377,6.382,473,9.798,700,6.128,764,5.895,1440,7.711,2138,7.507,2292,6.811,3310,9.032,3327,4.871,3483,9.105,3797,11.388,4069,11.565,4263,11.565,4353,5.222,4430,10.275,4432,9.798,4434,13.984,4435,13.984,4436,13.984,4437,8.261,4438,13.984]],["keywords/141",[]],["title/142",[185,318.859,418,410.72]],["content/142",[116,3.165,209,9.557,269,9.935,319,2.519,374,4.234,404,5.797,624,3.165,675,5.697,1049,9.221,1224,8.918,2138,7.943,2340,8.159,2390,9.935,2836,10.872,2957,11.478,3327,5.154,3766,9.935,3831,9.935,3902,10.872,4194,11.478,4353,4.555,4439,14.797,4440,13.254]],["keywords/142",[]],["title/143",[145,178.591,374,259.07,980,584.8]],["content/143",[72,8.426,81,7.003,85,7.863,98,3.198,115,6.214,116,3.964,136,8.13,148,9.586,212,4.139,246,7.863,253,9.586,265,4.853,374,3.733,524,4.544,574,6.354,637,7.621,725,5.45,775,5.5,798,5.156,985,7.399,1016,6.081,1135,5.717,1556,6.214,1702,10.12,2283,5.5,2292,6.354,2358,9.141,2363,6.826,2616,8.426,2618,10.12,3350,9.141,3507,12.404,3699,9.586,4137,7.399,4353,5.45,4411,12.442,4412,11.686,4441,10.12,4442,13.047,4443,10.79,4444,10.79]],["keywords/143",[]],["title/144",[86,107.292,3346,665.279,4445,905.483]],["content/144",[53,4.086,84,5.573,86,1.964,319,2.919,354,9.438,2023,7.869,2826,8.701,3327,5.775,3329,9.045,3344,6.279,3507,12.583,3766,9.045,3871,11.141,4137,10.185,4353,4.147,4370,9.438,4411,11.131,4430,9.898,4440,12.067,4446,13.472,4447,13.472,4448,13.472,4449,11.141,4450,12.067,4451,13.472,4452,13.472,4453,13.472,4454,11.141,4455,16.579]],["keywords/144",[]],["title/145",[86,107.292,3346,665.279,4456,702.378]],["content/145",[23,3.072,34,4.527,84,5.55,86,1.96,131,4.322,135,4.599,239,3.2,245,2.611,319,2.899,354,9.4,624,2.87,630,4.991,977,7.202,985,9.379,1376,5.55,1966,8.361,2138,7.202,2657,9.4,3327,4.673,3344,6.254,4137,9.379,4353,4.13,4370,9.4,4411,11.103,4430,9.858,4432,9.4,4449,11.096,4454,11.096,4457,13.417,4458,13.417,4459,13.417,4460,12.018,4461,13.417,4462,12.018,4463,13.417]],["keywords/145",[]],["title/146",[53,274.647,86,107.292,543,310.397]],["content/146",[84,5.484,86,2.113,98,3.25,223,5.696,265,4.931,312,4.336,319,2.869,354,9.287,454,5.484,555,9.739,1376,5.484,2292,6.456,2499,7.743,2617,10.963,2657,9.287,2825,7.517,3327,4.617,3344,6.178,3483,8.811,3507,9.287,3738,10.963,4137,10.112,4353,5.489,4370,9.287,4411,11.021,4430,9.739,4432,9.287,4449,10.963,4454,10.963,4464,13.256,4465,13.256,4466,13.256,4467,13.256,4468,13.256,4469,13.256]],["keywords/146",[]],["title/147",[1306,909.555]],["content/147",[53,4.882,84,5.313,86,1.907,98,3.149,113,8.623,116,2.747,179,4.699,208,3.896,281,9.437,289,4.267,319,2.877,417,4.699,543,4.403,624,2.747,1135,5.628,1350,8.421,1376,5.313,1395,6.72,1402,4.778,1445,8.999,3327,5.606,3346,9.437,3402,7.502,3415,8.999,3507,12.316,3760,9.437,4137,7.284,4353,3.954,4411,8.623,4450,11.504,4462,11.504,4470,10.622,4471,12.844,4472,12.844,4473,12.844,4474,16.095,4475,12.844,4476,12.844,4477,12.844,4478,12.844,4479,12.844,4480,12.844,4481,12.844]],["keywords/147",[]],["title/148",[1311,715.826]],["content/148",[7,6.419,13,5.742,34,4.334,86,1.522,98,3.149,99,11.504,116,3.443,159,9.128,229,6.556,233,4.014,239,3.839,275,4.547,485,8.003,499,4.334,508,5.862,574,6.256,596,4.945,624,3.443,629,7.741,675,6.196,726,4.267,775,6.785,797,7.839,874,5.862,1181,8.003,1333,5.123,1432,5.313,1534,7.082,1571,6.556,2253,10.622,2292,6.256,2650,8.999,2836,9.437,3308,4.17,3354,10.622,3729,10.622,3765,8.999,3952,11.504,4083,11.504,4353,5.412,4411,10.806,4482,12.844,4483,12.844,4484,12.844,4485,10.622,4486,11.504]],["keywords/148",[]],["title/149",[239,187.584,605,337.97,1284,331.546,2948,577.87]],["content/149",[]],["keywords/149",[]],["title/150",[246,545.735,1715,564.238,2250,634.395]],["content/150",[16,5.288,53,3.441,62,7.328,79,4.445,81,6.091,98,2.781,124,3.246,180,7.328,191,5.404,195,7.07,201,7.07,216,2.394,219,3.769,233,3.546,256,4.525,266,7.567,299,6.627,312,3.711,374,3.246,543,3.889,624,2.427,744,5.073,745,7.07,766,4.368,826,8.075,827,5.791,846,8.336,1122,7.949,1163,7.07,1183,10.415,1185,3.828,1316,7.618,1318,9.383,1322,7.409,1334,6.838,1338,7.328,1349,6.256,1375,8.801,1380,6.627,1566,7.328,1571,5.791,1676,7.328,1706,5.178,1782,5.526,1846,6.434,1859,7.949,1890,7.328,2297,9.383,2318,6.434,2336,7.328,2948,8.336,2957,8.801,3361,10.163,3451,9.383,3480,10.163,3563,7.949,3649,9.383,3816,9.383,3858,10.163,3868,8.801,3986,8.801,4056,13.315,4266,8.801,4487,14.866,4488,11.346,4489,11.346,4490,11.346,4491,11.346,4492,11.346,4493,11.346,4494,11.346,4495,11.346,4496,11.346,4497,11.346,4498,11.346,4499,11.346,4500,11.346,4501,11.346,4502,11.346,4503,11.346,4504,11.346,4505,11.346,4506,11.346,4507,11.346]],["keywords/150",[]],["title/151",[93,269.615,700,344.662,3308,203.791,4353,242.131]],["content/151",[]],["keywords/151",[]],["title/152",[1432,374.584,3797,607.94,4401,811.045]],["content/152",[18,2.244,23,2.038,64,4.241,74,3.427,84,5.213,86,1.493,89,5.522,93,4.319,98,2.182,108,3.683,116,1.904,166,10.421,167,2.912,206,4.241,208,2.7,212,2.824,266,4.063,286,5.049,305,4.658,319,2.954,342,8.828,409,4.534,417,3.257,431,3.901,456,3.101,483,3.203,543,3.052,676,6.541,680,4.15,700,3.901,743,5.75,744,5.634,833,3.826,985,5.049,989,5.75,1012,6.541,1198,4.779,1258,6.817,1376,3.683,1432,3.683,1697,5.2,1721,5.366,1782,4.336,2316,5.977,2577,7.974,3150,7.974,3308,3.265,3309,4.437,3327,5.539,3344,5.873,3359,10.677,3384,8.138,3396,4.437,3402,5.2,3418,5.977,3498,5.366,3528,7.363,3731,4.437,3773,8.828,3793,7.974,3797,5.977,3863,5.977,4172,6.906,4247,4.437,4262,6.906,4282,6.541,4292,5.75,4335,12.802,4353,4.896,4370,6.238,4437,6.137,4441,9.774,4443,7.363,4508,13.152,4509,8.903,4510,8.903,4511,7.974,4512,7.974,4513,8.903,4514,7.974,4515,11.286,4516,8.903,4517,8.903,4518,8.903,4519,8.903,4520,8.903,4521,8.903,4522,7.363,4523,7.974,4524,8.903,4525,14.244,4526,7.974,4527,7.974,4528,7.974,4529,7.974,4530,7.974,4531,11.286,4532,11.286,4533,7.974,4534,7.974,4535,7.974,4536,7.974,4537,7.974,4538,5.75]],["keywords/152",[]],["title/153",[217,383.313,700,304.637,2269,539.245,2409,622.673,2690,487.052]],["content/153",[41,4.687,53,3.18,84,4.337,93,5.464,94,5.351,98,3.908,116,3.017,126,8.132,131,3.377,142,3.651,145,2.782,162,5.225,191,4.993,206,4.993,215,4.886,216,2.212,219,3.482,229,5.351,263,8.67,289,3.482,319,2.89,382,3.835,524,3.651,623,3.537,700,6.985,828,8.132,862,8.67,980,6.77,1178,5.485,1198,7.571,1223,5.485,1333,4.181,1376,4.337,1395,5.485,1436,7.345,1571,5.351,1576,10.941,1966,6.532,2194,7.345,2283,5.946,3308,3.655,3327,3.651,3396,8.868,3467,8.67,3483,5.627,3545,12.527,3577,6.77,3731,5.225,4416,6.318,4432,7.345,4443,8.67,4508,13.183,4538,6.77,4539,10.483,4540,10.483,4541,10.483,4542,10.483,4543,10.483,4544,9.39,4545,7.702,4546,15.272,4547,12.634,4548,15.272,4549,8.132,4550,12.634,4551,12.634,4552,12.634,4553,8.132,4554,12.634,4555,9.39]],["keywords/153",[]],["title/154",[623,265.389,3308,203.791,3310,507.965,4353,242.131]],["content/154",[]],["keywords/154",[]],["title/155",[3360,572.688,4556,783.844]],["content/155",[18,2.232,20,2.942,27,4.041,66,3.596,74,3.409,86,2.061,93,3.036,98,2.171,116,1.894,131,4.697,135,3.036,147,4.883,185,2.647,190,4.626,206,4.218,216,1.869,239,2.994,319,2.764,328,3.959,333,3.409,344,4.041,374,2.534,404,3.469,447,3.294,524,3.084,623,4.92,624,2.685,630,4.67,680,7.394,720,3.409,721,3.94,741,5.337,764,3.733,798,2.809,833,5.394,979,5.173,985,8.997,1013,5.719,1020,4.883,1021,5.337,1218,6.204,1373,5.518,1511,4.754,1534,6.921,1558,5.945,1593,3.733,1600,5.719,1612,6.869,1903,5.173,2068,4.313,2092,6.506,2138,4.754,2340,4.883,2355,9.737,2356,5.945,2363,4.633,2656,5.945,2815,5.173,2962,6.204,3310,5.719,3327,5.526,3360,9.337,3400,6.506,3416,7.932,3419,6.506,3483,4.754,3701,5.719,3731,7.907,3797,5.945,3902,6.506,4069,7.323,4071,7.323,4247,7.907,4353,4.489,4437,8.472,4522,7.323,4556,12.78,4557,8.855,4558,8.855,4559,8.855,4560,8.855,4561,8.855,4562,8.855,4563,8.855,4564,8.855,4565,8.855,4566,6.869,4567,8.855,4568,7.323,4569,7.932,4570,8.855,4571,7.932,4572,8.855,4573,8.855,4574,8.855,4575,8.855,4576,8.855,4577,8.855,4578,8.855,4579,8.855,4580,8.855,4581,8.855,4582,8.855,4583,8.855,4584,8.855,4585,8.855,4586,8.855,4587,8.855,4588,8.855,4589,8.855]],["keywords/155",[]],["title/156",[4341,871.625]],["content/156",[8,4.332,21,3.53,23,1.99,25,4.437,27,3.967,84,5.125,86,1.71,93,2.98,125,2.98,130,4.052,131,4.649,147,4.793,153,2.888,166,10.245,188,3.967,206,4.14,212,2.758,216,1.834,239,2.073,245,1.691,266,3.967,305,4.548,316,3.809,319,2.899,409,3.128,417,3.18,430,3.53,456,4.315,499,2.933,543,4.948,574,4.234,623,5.309,624,1.859,630,3.234,667,7.189,680,4.052,741,5.239,744,5.539,833,5.323,914,5.417,985,4.929,1135,3.809,1534,4.793,1583,4.332,1969,4.929,2068,4.234,2499,5.077,2616,5.614,2706,5.614,2823,7.786,3308,3.21,3310,8.001,3327,5.48,3344,5.774,3359,9.691,3360,4.666,3384,8.001,3396,4.332,3402,5.077,3418,5.836,3483,4.666,3498,5.239,3546,6.743,3579,4.793,3585,6.743,3731,4.332,3753,10.245,3766,5.836,3773,8.679,3831,5.836,4247,4.332,4262,6.743,4335,12.702,4341,10.563,4353,4.843,4370,6.09,4416,5.239,4437,8.1,4511,7.786,4512,7.786,4514,7.786,4515,11.096,4522,7.189,4523,7.786,4525,14.092,4526,7.786,4527,7.786,4528,7.786,4529,7.786,4530,7.786,4531,11.096,4532,11.096,4533,7.786,4534,7.786,4535,7.786,4536,7.786,4537,7.786,4538,5.614,4556,6.386,4590,8.692,4591,8.692,4592,8.692,4593,8.692,4594,8.692,4595,8.692,4596,8.692,4597,7.786,4598,8.692,4599,8.692,4600,8.692,4601,7.786,4602,8.692,4603,8.692,4604,8.692]],["keywords/156",[]],["title/157",[2624,716.286,4437,519.621]],["content/157",[23,4.003,53,3.851,74,4.888,86,1.504,98,3.112,162,6.328,179,4.645,244,8.524,245,2.47,360,10.32,456,4.422,574,6.184,624,2.716,725,3.909,741,7.652,833,5.456,1198,9.386,1477,6.48,1571,8.156,2068,6.184,2338,8.2,2340,7,2365,10.728,2624,10.728,3308,3.29,3350,8.895,3360,6.815,3498,7.652,3701,10.32,4222,7.652,4353,5.649,4398,8.524,4437,8.516,4470,10.5,4556,9.328,4605,12.696,4606,11.372,4607,12.696,4608,12.696,4609,12.696,4610,12.696,4611,12.696,4612,12.696,4613,12.696,4614,12.696,4615,12.696,4616,12.696]],["keywords/157",[]],["title/158",[4353,328.435,4617,1066.856]],["content/158",[7,7.099,16,6.154,41,5.903,54,6.289,74,5.083,75,8.864,100,4.751,116,3.503,124,3.777,136,8.227,149,7.712,216,3.455,252,6.58,275,5.796,308,3.281,430,5.362,508,6.025,624,3.503,775,5.565,798,4.188,871,6.154,874,6.025,1334,7.957,1395,6.907,1445,9.25,1609,8.864,2385,11.826,2624,8.864,2728,12.701,3308,3.421,3444,11.826,3654,10.241,4353,4.065,4416,7.957,4437,6.431,4569,11.826,4618,10.241,4619,13.203,4620,13.203,4621,13.203,4622,13.203,4623,13.203,4624,13.203,4625,13.203]],["keywords/158",[]],["title/159",[1172,564.238,3308,234.617,4353,278.756]],["content/159",[8,5.258,13,4.717,19,5.983,23,3.243,40,6.814,86,1.678,93,4.856,115,6.747,130,7.454,131,4.563,154,3.859,173,7.083,180,6.814,190,3.347,211,6.574,275,3.735,377,4.815,416,4.917,431,4.623,449,3.398,499,3.56,623,4.78,624,2.257,630,3.925,726,3.505,741,6.358,798,3.347,833,4.533,947,5.983,975,7.411,1198,9.176,1224,6.358,1333,4.208,1395,5.52,1578,5.138,1593,4.447,1721,6.358,1911,8.274,2068,5.138,2400,8.537,2544,8.033,2643,6.162,2690,7.391,2961,8.183,3308,2.734,3360,9.176,3415,7.391,3701,6.814,3772,5.983,3797,7.083,3886,8.183,3902,7.751,4247,5.258,4353,5.946,4371,7.751,4416,8.537,4431,8.725,4437,8.685,4441,8.183,4556,12.56,4568,8.725,4606,9.45,4626,9.45,4627,10.55,4628,10.55,4629,9.45,4630,9.45,4631,10.55,4632,10.55,4633,10.55,4634,10.55,4635,8.725,4636,10.55,4637,10.55,4638,10.55,4639,10.55,4640,10.55,4641,10.55,4642,10.55,4643,10.55]],["keywords/159",[]],["title/160",[3308,234.617,4353,278.756,4644,905.483]],["content/160",[2,6.196,3,2.456,6,2.825,7,4.231,13,3.782,16,3.943,17,3.399,20,1.748,22,1.29,23,1.937,41,3.782,45,2.353,48,2.902,53,1.596,64,2.507,66,4.308,70,4.352,73,1.272,77,3.172,79,3.314,84,2.177,86,2.091,89,2.306,91,2.177,93,4.874,94,2.686,100,1.894,115,2.507,116,2.599,118,4.426,130,3.943,131,1.695,135,1.804,137,5.052,141,2.604,145,1.038,148,3.867,149,4.941,153,1.748,164,2.306,167,1.721,170,4.12,184,2.453,190,2.684,208,2.566,212,1.67,216,1.111,217,2.902,219,1.748,221,3.867,223,2.261,230,5.927,243,4.082,245,1.646,246,3.172,252,4.216,260,5.464,265,1.958,266,5.545,275,5.29,289,4.723,307,2.684,308,2.103,312,1.721,314,4.082,336,3.5,344,3.861,350,2.507,359,3.074,374,2.42,381,2.623,382,3.88,416,2.453,447,4.52,456,1.833,458,3.279,459,2.453,482,3.687,511,3.279,524,1.833,526,2.099,543,1.804,623,5.955,624,2.269,625,3.707,626,3.074,627,3.074,635,2.353,665,3.279,700,2.306,726,2.81,775,2.218,823,4.714,826,2.563,833,3.635,837,7.577,871,3.943,873,3.867,874,2.402,881,4.082,976,4.714,1122,3.687,1178,2.753,1189,2.062,1224,3.172,1287,3.867,1306,3.687,1315,4.648,1318,4.352,1322,2.623,1372,3.074,1412,3.687,1432,2.177,1436,3.687,1442,4.082,1445,3.687,1466,2.177,1477,2.686,1525,4.941,1534,5.849,1556,2.507,1563,4.082,1574,4.082,1578,4.12,1592,6.015,1679,3.279,1685,4.797,1686,3.074,1697,6.196,1704,3.172,1707,4.352,1709,4.12,1712,2.563,1715,3.279,1782,2.563,1809,4.082,1810,3.687,1887,3.172,1892,2.902,1896,2.402,1903,3.074,1911,3.074,1967,4.352,1981,3.172,1985,6.215,1988,3.687,2230,3.687,2283,5.993,2292,4.12,2330,3.867,2336,3.399,2338,3.399,2340,6.699,2350,2.825,2354,3.533,2356,3.533,2397,4.082,2506,6.215,2544,2.984,2548,4.082,2657,3.687,2697,4.082,3168,3.867,3308,4.679,3309,4.216,3310,3.399,3339,5.464,3356,4.082,3359,3.533,3364,4.714,3370,4.352,3419,3.867,3442,6.562,3447,3.399,3483,2.825,3502,3.399,3570,4.714,3683,8.927,3701,5.464,3718,4.714,3765,5.927,3771,4.352,3816,4.352,3823,3.687,3863,5.68,4050,4.714,4098,9.501,4187,4.714,4194,4.082,4247,2.623,4255,4.352,4269,4.714,4341,3.533,4353,2.604,4398,3.533,4427,6.996,4437,2.563,4444,4.352,4456,4.082,4486,4.714,4571,9.501,4626,7.577,4635,4.352,4645,5.263,4646,5.263,4647,5.263,4648,5.263,4649,5.263,4650,5.263,4651,4.352,4652,5.263,4653,5.263,4654,4.714,4655,5.263,4656,5.263,4657,5.263,4658,5.263,4659,5.263,4660,4.714,4661,5.263,4662,5.263,4663,4.714,4664,4.352,4665,5.263,4666,5.263,4667,5.263,4668,4.714,4669,5.263,4670,5.263,4671,5.263,4672,4.714,4673,5.263,4674,5.263,4675,5.263,4676,5.263,4677,4.714,4678,5.263,4679,5.263,4680,5.263,4681,8.772,4682,5.263,4683,5.263,4684,5.263,4685,5.263,4686,4.714,4687,5.263,4688,5.263,4689,5.263,4690,8.459,4691,5.263,4692,5.263,4693,5.263,4694,5.263,4695,5.263,4696,5.263,4697,5.263,4698,5.263,4699,5.263,4700,5.263,4701,5.263,4702,5.263,4703,5.263,4704,5.263,4705,5.263,4706,5.263,4707,5.263,4708,5.263,4709,5.263,4710,5.263,4711,5.263,4712,5.263,4713,5.263,4714,5.263,4715,5.263,4716,5.263,4717,5.263,4718,5.263,4719,5.263,4720,5.263,4721,5.263,4722,4.714,4723,5.263]],["keywords/160",[]],["title/161",[216,225.142,3840,882.296]],["content/161",[3,2.523,7,3.467,10,4.332,16,4.052,18,2.191,41,3.886,45,6.453,55,5.836,73,2.102,86,1.03,98,3.538,113,9.691,117,5.836,134,3.596,141,2.676,142,3.028,158,7.719,170,4.234,190,3.93,208,2.637,209,5.614,212,2.758,215,4.052,216,2.614,217,6.831,219,2.888,230,6.09,231,11.096,233,4.916,239,2.955,245,2.809,246,5.239,247,7.786,249,5.614,252,4.332,256,4.941,275,3.077,277,4.929,279,6.09,285,8.001,297,6.386,299,7.236,336,3.596,386,4.234,456,3.028,508,3.967,543,2.98,605,5.323,670,6.386,675,3.346,703,6.386,744,3.886,745,5.417,794,4.929,798,2.758,799,4.929,827,4.437,846,6.386,874,3.967,877,3.757,989,5.614,1018,5.239,1119,4.437,1135,3.809,1185,2.933,1189,3.406,1315,3.809,1319,5.077,1320,4.437,1333,3.467,1350,6.481,1402,3.234,1477,4.437,1522,4.929,1572,7.786,1685,4.929,1706,3.967,1848,8.679,1890,5.614,2168,6.743,2182,7.189,2218,7.786,2287,7.189,2338,5.614,2340,4.793,2448,6.743,2606,7.189,2616,5.614,2650,6.09,2739,7.189,2819,7.786,3688,7.786,3789,6.743,3823,6.09,3840,13.011,3841,7.786,3845,14.896,3960,14.092,3986,6.743,4545,6.386,4553,6.743,4668,7.786,4724,8.692,4725,8.692,4726,8.692,4727,8.692,4728,8.692,4729,7.786,4730,8.692,4731,8.692,4732,8.692,4733,12.388,4734,8.692,4735,7.786,4736,14.434,4737,16.63,4738,8.692,4739,8.692,4740,8.692,4741,8.692,4742,8.692,4743,8.692,4744,7.786,4745,8.692,4746,12.388,4747,8.692,4748,8.692,4749,12.388,4750,8.692,4751,8.692,4752,8.692,4753,8.692,4754,12.388,4755,8.692,4756,8.692,4757,8.692,4758,8.692]],["keywords/161",[]],["title/162",[1896,413.24,2736,451.297,4759,811.045]],["content/162",[]],["keywords/162",[]],["title/163",[879,459.424,1896,358.946,4760,786.514,4761,704.484]],["content/163",[2,6.035,7,3.269,10,2.523,22,2.01,23,1.159,79,1.983,86,0.6,116,2.21,127,2.359,128,3.926,131,1.63,136,3.154,142,1.763,143,2.791,153,1.681,154,1.852,158,3.154,159,2.87,170,2.465,179,1.852,185,2.45,190,1.606,203,3.926,216,1.068,222,2.218,229,4.184,233,1.582,239,1.207,261,5.108,265,3.843,266,2.31,294,3.269,306,2.717,312,1.655,319,3.051,324,7.591,337,3.05,357,5.472,358,3.199,365,4.527,381,2.523,404,1.983,411,2.583,417,1.852,418,4.572,422,2.717,460,2.465,499,2.766,512,4.4,543,1.735,561,4.815,608,4.204,613,5.834,624,1.754,644,6.062,698,3.926,721,3.286,723,6.376,726,1.681,775,2.134,797,2.465,798,1.606,871,2.359,908,3.546,913,4.52,920,8.726,977,2.717,978,3.154,1088,3.719,1221,3.269,1260,7.238,1284,2.134,1402,1.883,1583,2.523,1686,2.956,1703,3.719,1709,3.993,1784,3.546,1849,4.533,1896,2.31,2051,3.926,2068,2.465,2137,5.294,2283,2.134,2292,2.465,2338,3.269,2504,3.719,2555,3.269,2736,5.92,2825,2.87,2940,3.269,2961,3.926,3327,1.763,3375,2.791,3400,3.719,3483,2.717,3577,3.269,3661,3.05,3731,2.523,3738,4.186,3751,3.398,3772,2.87,3773,3.546,3931,4.533,4146,4.186,4247,2.523,4282,3.719,4660,4.533,4759,4.533,4761,10.638,4762,5.061,4763,5.061,4764,5.061,4765,5.061,4766,5.061,4767,5.061,4768,5.061,4769,5.061,4770,5.061,4771,4.533,4772,7.342,4773,8.197,4774,7.342,4775,5.061,4776,5.061,4777,5.061,4778,10.331,4779,5.061,4780,5.061,4781,5.061,4782,5.061,4783,5.061,4784,5.061,4785,5.061,4786,5.061,4787,5.061,4788,5.061,4789,5.061,4790,5.061,4791,5.061,4792,13.967,4793,8.197,4794,5.061,4795,5.061,4796,4.186,4797,5.061,4798,4.533,4799,4.186,4800,5.061]],["keywords/163",[]],["title/164",[3662,572.688,3679,588.253]],["content/164",[3,2.763,6,7.088,18,2.399,21,6.157,23,2.179,45,4.255,64,4.533,73,2.301,79,3.729,84,3.937,86,2.109,95,5.736,98,2.333,100,4.751,113,6.39,116,2.036,124,3.778,130,4.436,141,2.93,154,3.482,159,5.398,179,3.482,184,4.436,185,2.845,188,4.344,212,3.019,215,4.436,216,2.009,219,3.162,245,1.852,259,8.525,275,3.369,328,4.255,350,4.533,376,5.736,431,4.171,623,3.212,624,2.036,638,7.958,761,5.931,775,4.012,809,6.993,833,4.09,877,2.887,975,4.98,1402,3.541,1466,5.462,1511,5.109,1535,6.147,1569,7.871,1578,4.636,1675,8.525,1709,7.976,1711,7.383,1715,5.931,1782,4.636,1806,8.528,1854,4.171,2230,6.668,2250,6.668,2359,6.993,2506,6.993,2544,5.398,2621,6.39,2656,6.39,2736,6.581,3206,7.871,3308,3.421,3355,7.383,3356,7.383,3375,10.419,3489,6.993,3662,9.799,3679,9.815,3722,7.871,3751,6.39,3752,11.473,3756,6.668,3831,6.39,4239,7.383,4353,5.041,4437,4.636,4798,8.525,4799,7.871,4801,9.518,4802,9.518,4803,9.518,4804,9.518,4805,9.518,4806,9.518,4807,9.518,4808,9.518,4809,9.518,4810,8.525,4811,13.204,4812,9.518,4813,9.518,4814,12.538,4815,9.518,4816,9.518,4817,9.518,4818,9.518]],["keywords/164",[]],["title/165",[4819,953.834]],["content/165",[18,2.426,21,3.91,22,2.36,27,4.394,66,3.91,79,3.772,81,8.189,86,1.577,91,3.983,95,5.803,98,2.36,100,3.465,124,3.808,125,3.301,131,3.101,134,3.983,136,6,142,3.354,149,5.624,153,3.199,154,4.869,158,6,164,4.219,216,2.032,222,5.833,262,6.746,265,3.582,316,4.219,319,2.363,375,7.074,381,4.799,411,4.915,524,3.354,725,2.964,775,6.43,797,4.69,879,5.624,888,7.963,913,5.309,947,7.548,975,5.038,990,6,1125,6.746,1178,5.038,1183,9.325,1215,7.469,1283,5.803,1287,7.074,1369,6.219,1402,3.582,1409,6.465,1566,6.219,1592,5.46,1678,8.624,1679,6,1685,5.46,1709,4.69,1715,8.294,1782,4.69,1806,6.219,1809,7.469,1846,5.46,1854,4.219,1896,4.394,1969,7.548,2656,8.936,2736,6.634,2940,6.219,3206,11.008,3308,3.449,3375,10.446,3483,7.145,3653,11.008,3662,8.189,3679,8.411,3751,6.465,3831,10.242,3894,7.963,3907,8.624,3979,8.624,3986,7.469,4192,8.624,4292,6.219,4353,2.964,4819,13.454,4820,9.629,4821,9.629,4822,9.629,4823,9.629,4824,9.629,4825,9.629,4826,9.629,4827,9.629,4828,15.255,4829,9.629,4830,9.629,4831,9.629,4832,9.629,4833,9.629,4834,9.629,4835,9.629]],["keywords/165",[]],["title/166",[1686,528.917,1896,413.24,3489,665.279]],["content/166",[20,3.821,23,2.634,40,7.43,86,1.777,124,3.291,125,3.943,131,4.832,162,5.734,193,8.452,198,6.343,208,3.489,216,2.428,222,5.041,223,4.943,249,7.43,250,5.734,256,4.588,266,5.25,275,4.072,526,4.588,624,2.461,721,3.529,761,7.168,775,4.849,797,5.603,798,3.65,871,5.362,1221,7.43,1319,6.72,1350,6.019,1376,4.759,1402,4.28,1526,7.724,1592,6.524,1709,5.603,1711,8.923,1715,10.401,1887,6.933,1896,5.25,2026,7.145,2338,7.43,2390,7.724,2736,8.319,3308,2.981,3375,8.271,3396,5.734,3431,8.06,3482,8.923,3653,9.514,3661,6.933,3662,6.175,3679,6.343,4137,6.524,4239,8.923,4353,3.541,4545,8.452,4771,13.436,4819,8.452,4836,13.721,4837,11.504,4838,8.06,4839,11.504,4840,11.504,4841,8.923,4842,11.504,4843,14.951,4844,11.504,4845,11.504,4846,11.504,4847,11.504,4848,11.504,4849,11.504,4850,10.304]],["keywords/166",[]],["title/167",[483,467.128]],["content/167",[22,3.487,154,5.204,216,3.002,245,2.768,265,5.292,289,5.693,376,8.573,430,5.777,480,10.451,483,6.166,485,8.864,629,8.573,721,4.327,739,8.573,766,5.476,871,6.63,879,8.309,1185,4.8,1264,8.573,2736,7.09,2834,11.764,3024,11.764,3577,9.187,4112,12.741,4796,11.764,4851,14.225,4852,14.225,4853,14.225,4854,14.225]],["keywords/167",[]],["title/168",[3751,871.625]],["content/168",[7,5.373,314,10.45,871,6.279,1185,4.546,1466,5.573,2547,12.067,2736,6.714,3375,9.142,3661,8.119,3662,7.232,3679,9.142,3751,9.045,3752,9.438,4266,10.45,4353,4.147,4618,10.45,4796,11.141,4814,11.141,4819,9.898,4836,10.45,4855,12.067,4856,11.141,4857,12.067,4858,14.85,4859,12.067,4860,12.067,4861,12.067,4862,13.472,4863,13.472,4864,13.472,4865,13.472,4866,13.472,4867,13.472,4868,13.472,4869,13.472,4870,13.472,4871,13.472,4872,13.472,4873,13.472,4874,13.472,4875,13.472,4876,13.472,4877,13.472]],["keywords/168",[]],["title/169",[3756,909.555]],["content/169",[5,11.64,116,2.78,142,4.526,153,4.317,154,4.754,162,6.477,314,10.08,455,9.105,775,6.835,871,6.057,1185,4.385,1466,5.376,1709,6.329,1807,9.105,2736,8.081,3375,8.94,3661,7.832,3662,6.976,3679,8.94,3751,8.725,4545,9.548,4618,10.08,4814,10.747,4819,9.548,4836,10.08,4855,11.64,4856,10.747,4857,11.64,4858,14.523,4859,11.64,4860,11.64,4861,11.64,4878,16.214,4879,12.995,4880,12.995,4881,12.995,4882,12.995,4883,12.995,4884,12.995,4885,12.995,4886,12.995,4887,12.995,4888,12.995,4889,12.995,4890,12.995,4891,12.995,4892,12.995,4893,12.995,4894,12.995]],["keywords/169",[]],["title/170",[1311,715.826]],["content/170",[11,9.477,13,6.048,23,3.805,98,3.316,131,4.357,137,6.443,198,7.458,208,4.103,216,2.855,223,5.813,229,6.904,239,3.226,245,2.632,265,5.032,308,3.362,328,6.048,526,5.395,744,6.048,775,7.006,1189,5.3,1283,8.153,1308,8.153,1430,13.746,1432,6.876,1556,6.443,1592,7.671,1706,6.173,2028,9.938,2294,12.116,2303,11.187,2736,6.742,3375,7.458,3483,7.261,3577,8.736,4629,12.116,4836,12.893,4850,12.116,4856,11.187,4895,13.527,4896,13.527]],["keywords/170",[]],["title/171",[265,292.594,266,358.946,775,331.546,797,383.078]],["content/171",[]],["keywords/171",[]],["title/172",[66,433.273,3309,531.726]],["content/172",[16,3.43,22,1.804,45,3.29,49,4.752,66,2.988,81,3.95,86,1.723,89,3.224,93,5.331,115,3.505,116,2.347,124,2.105,131,2.37,137,6.248,142,3.821,145,1.451,153,2.444,154,4.013,158,4.585,159,4.173,185,3.279,188,3.358,190,2.334,212,2.334,216,2.315,223,3.162,239,1.755,242,4.94,243,5.708,245,2.829,252,5.468,261,4.585,266,3.358,275,2.605,289,3.644,299,4.298,309,4.435,324,5.406,357,2.883,359,4.298,417,2.692,431,3.224,449,2.37,508,3.358,524,2.563,528,6.591,541,6.085,554,4.435,605,3.162,623,5.503,624,1.574,635,3.29,644,3.756,675,2.833,697,5.889,700,4.807,721,2.581,725,2.265,764,4.625,775,5.529,798,3.48,799,4.173,833,4.714,930,6.591,989,4.752,1135,4.807,1178,3.85,1185,4.426,1201,6.591,1204,6.085,1350,3.85,1395,3.85,1401,4.94,1403,5.406,1435,6.591,1593,3.102,1595,4.94,1600,7.085,1630,4.94,1683,5.708,1702,8.51,1705,4.298,1712,5.343,1715,4.585,1903,10.143,1952,5.708,2283,5.529,2346,5.155,2358,5.155,2400,4.435,2455,5.708,2556,6.085,2606,6.085,2618,5.708,2624,4.94,2650,5.155,2716,6.085,2810,6.085,2824,5.708,2825,4.173,2835,4.94,2841,5.708,3291,4.94,3308,3.399,3309,8.128,3339,4.752,3445,8.06,3447,10.532,3481,6.085,3517,6.591,3577,4.752,3791,4.752,3863,7.366,3868,5.708,4041,6.591,4137,4.173,4201,6.085,4335,8.06,4341,10.949,4353,5.02,4365,6.591,4383,9.073,4398,4.94,4416,4.435,4437,5.343,4485,9.073,4508,6.085,4686,6.591,4838,5.155,4897,7.358,4898,7.358,4899,7.358,4900,5.406,4901,6.085,4902,7.358,4903,7.358,4904,8.51,4905,10.971,4906,7.358,4907,7.358,4908,7.358,4909,7.358,4910,7.358,4911,7.358,4912,7.358,4913,7.358,4914,6.591,4915,7.358,4916,7.358,4917,6.591,4918,7.358,4919,7.358,4920,7.358,4921,7.358,4922,7.358,4923,7.358,4924,7.358,4925,7.358,4926,7.358,4927,7.358,4928,7.358,4929,6.591,4930,13.023,4931,7.358,4932,7.358,4933,7.358,4934,7.358,4935,7.358,4936,7.358,4937,7.358]],["keywords/172",[]],["title/173",[4938,1007.024]],["content/173",[7,3.253,16,3.802,18,2.055,50,6.745,52,5.993,53,2.474,85,4.916,91,3.374,100,4.258,104,5.882,108,3.374,116,2.979,118,4.267,127,3.802,128,6.327,134,3.374,137,3.885,140,4.065,167,2.668,185,2.438,188,3.722,191,3.885,208,4.224,212,2.588,216,2.497,222,7.109,266,7.404,269,5.476,289,5.075,377,3.722,413,5.715,430,3.313,453,4.378,524,2.841,526,3.253,543,4.774,623,3.993,624,2.531,680,3.802,726,2.71,744,3.647,874,3.722,910,10.258,1135,6.103,1185,2.752,1338,5.268,1376,3.374,1395,4.267,1399,8.394,1403,5.993,1409,5.476,1466,3.374,1477,4.163,1563,6.327,1583,4.065,1595,5.476,1623,5.993,1691,7.306,1709,3.973,1716,7.306,1782,3.973,1854,7.109,1985,5.993,2169,7.306,2180,6.745,2194,5.715,2283,6.44,2341,5.715,2350,4.378,2650,8.291,2651,6.745,2654,5.268,2824,6.327,2825,4.626,3223,6.327,3301,6.745,3339,8.995,3430,7.306,3460,8.291,3502,5.268,3566,6.327,3572,5.993,3665,5.715,3677,6.327,3719,6.745,3791,5.268,3863,5.476,3871,6.745,4137,6.711,4432,5.715,4544,7.306,4553,6.327,4566,9.18,4651,6.745,4681,6.745,4772,7.306,4838,5.715,4914,7.306,4938,11.851,4939,6.745,4940,16.92,4941,15.278,4942,17.456,4943,12.005,4944,8.157,4945,8.157,4946,8.157,4947,13.927,4948,8.157,4949,8.157,4950,8.157,4951,8.157,4952,8.157,4953,8.157,4954,8.157,4955,8.157,4956,8.157,4957,8.157,4958,8.157,4959,11.834,4960,8.157,4961,8.157,4962,8.157,4963,8.157,4964,8.157,4965,8.157,4966,8.157,4967,8.157,4968,11.834,4969,8.157,4970,10.6,4971,8.157,4972,7.306]],["keywords/173",[]],["title/174",[4939,1073.638]],["content/174",[1,7.075,6,5.421,13,6.149,20,4.569,34,3.408,86,1.197,93,3.462,98,3.371,100,3.634,116,2.942,118,7.195,124,2.889,128,7.834,145,1.992,149,5.899,184,4.707,187,10.105,215,6.41,221,12.907,239,4.005,266,6.277,267,11.374,275,4.868,289,3.355,308,2.51,317,6.087,377,4.609,453,5.421,543,3.462,623,5.666,665,6.293,726,3.355,775,4.257,799,5.727,1016,4.707,1126,7.834,1314,7.834,1333,4.028,1380,5.899,1447,6.78,1477,5.155,1558,6.78,1706,4.609,1710,9.234,1986,9.046,2023,5.899,2092,7.42,2338,6.522,2350,5.421,2548,7.834,2568,9.046,2624,6.78,2643,5.899,2810,11.374,3070,6.293,3291,6.78,3490,7.834,3498,6.087,3579,5.568,3791,6.522,4146,8.352,4198,9.046,4216,9.046,4663,9.046,4664,11.374,4810,9.046,4838,10.957,4938,12.131,4939,8.352,4943,10.5,4973,10.099,4974,13.753,4975,10.099,4976,10.099,4977,10.099,4978,10.099,4979,10.099,4980,10.099,4981,10.099,4982,10.099,4983,13.753,4984,10.099,4985,10.099,4986,10.099,4987,12.319,4988,10.099,4989,9.046,4990,10.099,4991,10.099,4992,8.352,4993,10.099,4994,10.099,4995,9.046,4996,10.099,4997,10.099,4998,10.099]],["keywords/174",[]],["title/175",[4992,1073.638]],["content/175",[23,2.941,33,7.566,50,10.623,79,3.585,86,1.522,108,3.785,109,6.118,115,4.358,160,4.091,170,4.456,179,4.699,188,4.175,216,3.133,222,5.629,245,1.78,266,4.175,275,5.255,276,5.514,277,5.189,305,4.787,308,2.274,328,4.091,336,3.785,386,7.23,390,6.722,411,4.67,430,3.716,453,4.911,480,6.722,485,5.701,561,4.264,605,5.52,624,1.957,675,3.522,676,6.722,680,4.264,721,4.247,726,3.039,794,5.189,826,4.456,877,2.775,910,10.807,1169,7.742,1185,3.087,1190,6.722,1224,5.514,1316,6.143,1369,5.909,1399,5.514,1526,6.143,1578,4.456,1697,5.344,1748,7.566,2030,8.999,2094,6.722,2147,5.514,2215,8.195,2314,6.41,2340,5.045,2384,6.722,2544,5.189,2654,8.296,2728,7.097,2832,7.566,2919,7.566,3184,7.097,3299,7.566,3314,8.195,3368,11.514,3438,7.566,3439,5.909,3475,7.566,3483,6.895,3592,6.143,3707,10.623,3791,5.909,4127,8.195,4239,7.097,4398,6.143,4416,5.514,4681,7.566,4774,14.417,4838,6.41,4970,11.505,4992,12.276,4999,9.149,5000,9.149,5001,9.149,5002,9.149,5003,9.149,5004,9.149,5005,9.149,5006,9.149,5007,9.149,5008,9.149,5009,9.149,5010,9.149,5011,9.149,5012,9.149,5013,9.149,5014,9.149,5015,9.149,5016,9.149,5017,9.149,5018,9.149,5019,9.149,5020,9.149,5021,9.149,5022,9.149,5023,9.149,5024,9.149,5025,9.149,5026,9.149,5027,9.149,5028,9.149,5029,14.844,5030,9.149,5031,9.149,5032,9.149,5033,9.149,5034,9.149,5035,9.149,5036,9.149,5037,8.195,5038,9.149]],["keywords/175",[]],["title/176",[524,371.602,1970,827.555]],["content/176",[1,6.611,6,5.065,13,4.219,18,3.803,19,5.351,22,2.313,28,6.336,41,4.219,79,3.697,86,1.933,106,6.094,125,3.235,134,3.904,149,7.667,153,3.135,156,5.687,164,4.135,167,3.086,185,2.82,190,2.994,212,4.164,216,1.991,228,7.804,230,6.611,245,2.554,246,5.687,262,6.611,266,7.446,267,7.804,289,3.135,350,4.495,430,3.832,474,4.937,499,3.184,524,4.572,526,3.763,635,4.219,700,4.135,725,2.905,726,3.135,739,5.687,761,5.88,775,6.362,793,8.452,797,6.393,877,2.862,910,6.336,977,5.065,1021,5.687,1177,5.351,1216,6.094,1307,5.88,1315,5.752,1322,4.703,1333,3.763,1334,5.687,1337,7.804,1350,4.937,1395,4.937,1399,5.687,1477,4.816,1500,6.611,1511,5.065,1571,4.816,1600,8.477,1705,5.512,1707,7.804,1782,4.596,1821,4.398,1854,4.135,2030,6.611,2147,5.687,2283,3.978,2340,5.203,2360,5.512,2546,9.644,2643,7.667,2657,6.611,2835,6.336,3195,7.804,3309,4.703,3339,9.747,3431,6.611,3445,6.933,3481,7.804,3490,7.32,3567,7.804,3577,9.747,3654,7.32,3665,6.611,3676,10.855,3789,7.32,3847,8.452,4032,8.452,4137,5.351,4189,8.452,4255,7.804,4341,6.336,4456,7.32,4485,7.804,4618,10.181,4635,7.804,4651,7.804,4838,9.196,4943,6.336,4972,8.452,4987,8.452,4989,8.452,5039,9.436,5040,9.436,5041,9.436,5042,9.436,5043,9.436,5044,9.436,5045,9.436,5046,9.436,5047,9.436,5048,9.436,5049,9.436,5050,9.436,5051,9.436,5052,9.436,5053,9.436,5054,9.436,5055,9.436]],["keywords/176",[]],["title/177",[623,265.389,3308,203.791,4353,242.131,4371,577.87]],["content/177",[]],["keywords/177",[]],["title/178",[449,343.638,3772,605.017]],["content/178",[23,2.884,27,5.75,41,5.633,93,6.273,110,6.592,115,6.001,116,2.695,145,2.485,153,4.185,170,6.137,179,4.609,245,2.452,389,6.28,449,6.207,483,4.533,499,4.251,543,4.319,623,4.251,624,3.402,700,5.521,975,8.32,1179,9.257,1223,6.592,1319,7.36,1566,8.137,1592,7.145,1595,8.459,1709,6.137,1782,6.137,1806,8.137,1911,7.36,2283,6.703,2363,6.592,2815,7.36,2835,8.459,3291,8.459,3327,4.389,3579,6.947,3772,10.701,4630,11.285,4735,11.285,5037,11.285,5056,12.599,5057,12.599,5058,12.599,5059,11.285,5060,12.599,5061,12.599]],["keywords/178",[]],["title/179",[1709,632.31]],["content/179",[18,3.68,34,2.996,41,3.97,84,6.041,86,2.063,91,3.673,94,4.532,98,3.083,134,5.203,135,4.311,147,4.896,179,3.248,185,3.759,208,2.693,245,1.728,286,5.035,312,2.904,319,2.913,374,2.54,377,4.052,389,4.425,404,3.479,449,4.051,451,10.231,456,3.093,624,2.69,675,3.418,680,5.862,794,5.035,1021,5.351,1088,11.67,1090,11.67,1179,6.524,1313,7.343,1375,6.887,1402,4.679,1477,4.532,1511,8.526,1565,4.229,1566,5.734,1593,5.301,2092,6.524,2365,5.961,2664,9.755,2815,5.186,2826,5.734,2897,6.524,2905,6.221,2962,6.221,3279,7.343,3291,5.961,3308,4.344,3327,5.84,3350,6.221,3384,5.734,3415,6.221,3516,6.221,3528,7.343,3724,9.755,3740,8.811,3772,9.008,4416,5.351,4538,9.432,4566,12.321,5062,8.879,5063,8.879,5064,8.879,5065,8.879,5066,8.879,5067,8.879,5068,9.755,5069,12.576,5070,12.576,5071,8.879,5072,12.576,5073,12.576,5074,15.884,5075,12.576,5076,7.343,5077,7.343,5078,12.576,5079,7.953,5080,7.953,5081,8.879,5082,12.576,5083,7.953,5084,8.879,5085,8.879,5086,8.879,5087,8.879,5088,8.879,5089,8.879]],["keywords/179",[]],["title/180",[389,647.04]],["content/180",[20,4.201,23,2.895,27,5.772,41,5.655,84,5.232,86,1.889,93,5.983,109,6.024,110,6.617,206,6.024,245,2.461,319,2.712,374,3.619,417,4.627,449,5.903,543,4.336,623,5.379,1221,8.168,1315,5.542,1592,7.172,1782,6.16,1896,5.772,2283,6.719,2350,6.789,2544,7.172,2815,7.388,3327,4.405,3579,6.974,3731,6.304,3772,9.899,4036,11.328,4137,7.172,4292,10.295,4566,12.365,4568,10.46,4943,8.491,5068,9.811,5090,12.647,5091,12.647,5092,12.647,5093,12.647,5094,12.647,5095,10.46,5096,11.328,5097,12.647,5098,12.647]],["keywords/180",[]],["title/181",[975,679.208]],["content/181",[13,4.628,34,3.493,41,4.628,53,3.14,66,4.204,86,1.227,93,5.43,114,6.95,115,4.931,116,2.214,135,3.549,142,3.606,167,4.574,185,3.094,206,4.931,211,8.715,223,4.448,319,2.792,417,5.116,449,6.197,481,5.284,524,3.606,613,4.628,624,2.992,635,4.628,680,6.519,744,4.628,798,3.284,826,5.042,827,7.138,871,4.825,975,7.317,979,6.047,1166,8.03,1395,5.416,1578,5.042,1592,5.871,1595,9.39,1659,9.272,1721,6.239,2228,14.652,2327,8.561,2777,13.158,2825,5.871,3070,10.57,3327,4.871,3360,7.507,3572,7.606,3654,8.03,3701,6.686,3731,6.97,3772,10.047,4162,8.561,4247,7.894,4257,12.286,4264,14.187,4292,11.443,5095,8.561,5099,9.272,5100,9.272,5101,10.352,5102,10.352,5103,10.352,5104,10.352,5105,10.352,5106,10.352]],["keywords/181",[]],["title/182",[449,343.638,3344,497.261]],["content/182",[86,1.493,110,6.592,137,6.001,142,4.389,153,4.185,162,6.28,190,3.997,211,9.909,239,3.005,245,2.452,382,4.609,447,4.687,635,5.633,979,7.36,1175,8.827,1185,4.251,1477,6.431,1593,5.311,1709,6.137,1976,9.773,2026,9.514,2283,6.703,2316,8.459,2336,8.137,2357,8.827,2363,6.592,2815,7.36,3344,9.31,3431,8.827,3740,8.827,3771,10.42,3772,9.018,3902,9.257,4201,10.42,4371,9.257,5107,12.599,5108,12.599,5109,12.599,5110,12.599,5111,12.599,5112,12.599,5113,11.285,5114,9.773,5115,12.599]],["keywords/182",[]],["title/183",[211,664.795,623,359.982]],["content/183",[21,4.44,23,2.503,41,4.888,86,1.719,89,4.791,93,4.973,114,7.341,115,6.91,116,2.339,124,3.128,142,5.053,170,7.066,185,3.268,206,5.208,211,9.04,319,2.862,376,6.59,386,5.325,389,5.449,417,5.307,449,5.244,481,7.405,484,5.449,623,3.689,664,6.59,851,8.481,975,5.72,979,6.387,1019,6.813,1185,3.689,1216,7.061,1350,5.72,1593,6.115,2026,6.91,2228,15.651,2356,7.341,2365,7.341,2499,6.387,2777,11.253,3291,7.341,3327,5.053,3344,8.083,3731,7.23,3772,9.233,4247,8.114,4261,12.994,4262,11.253,4285,12.994,4292,11.655,4545,8.033,5095,9.042,5099,9.793,5116,10.933,5117,14.507,5118,14.507]],["keywords/183",[]],["title/184",[389,647.04]],["content/184",[21,3.91,34,3.249,58,6,84,5.506,85,5.803,86,1.808,93,3.301,94,4.915,109,4.586,124,2.755,131,3.101,135,4.563,229,4.915,245,1.874,275,3.408,286,5.46,307,3.055,319,2.936,336,3.983,374,2.755,377,4.394,386,4.69,389,7.603,409,5.921,417,3.522,456,3.354,624,2.06,874,4.394,1088,9.779,1306,6.746,1319,5.624,1432,5.506,1522,5.46,1558,6.465,1571,4.915,1593,4.059,2026,6.34,2363,5.038,2815,5.624,3308,3.953,3327,6.378,3344,8.698,3378,7.074,3396,7.603,3402,5.624,3772,8.651,4154,10.325,4282,9.779,4292,9.852,4299,11.922,4441,7.469,4460,8.624,4538,9.852,4841,7.469,5068,7.469,5077,7.963,5119,9.629,5120,13.31,5121,15.859,5122,14.74,5123,9.629,5124,9.629,5125,9.629,5126,9.629,5127,9.629,5128,9.629,5129,9.629,5130,8.624,5131,9.629,5132,9.629,5133,9.629]],["keywords/184",[]],["title/185",[4154,827.555,5114,827.555]],["content/185",[34,3.868,41,5.125,85,9.02,86,1.358,93,3.93,109,5.46,116,2.452,125,3.93,131,3.693,135,3.93,162,8.305,179,4.194,185,4.473,202,9.481,211,7.144,239,2.734,245,2.231,285,7.404,319,2.698,386,5.584,389,5.714,409,5.385,542,8.032,644,5.851,667,9.481,1258,6.976,1334,6.909,1349,6.321,1520,11.609,1522,6.501,1709,5.584,1969,6.501,2026,7.129,2027,10.486,2273,7.144,2350,6.154,2363,7.83,2825,6.501,2897,8.423,3308,3.878,3315,7.697,3344,8.234,3378,8.423,3379,7.404,3396,7.459,3402,6.696,3585,11.609,3814,10.268,4154,13.703,4292,7.404,4371,8.423,4538,7.404,5068,8.893,5077,9.481,5113,10.268,5114,8.893,5121,14.609,5122,10.268,5130,10.268,5134,11.464,5135,11.464,5136,11.464]],["keywords/185",[]],["title/186",[3740,747.456,5076,882.296]],["content/186",[84,5.192,86,1.88,116,2.685,117,8.427,185,3.751,236,9.736,312,4.105,319,2.839,333,4.832,377,7.24,524,4.372,543,4.303,626,7.332,725,3.864,1019,7.821,1402,4.669,1511,6.738,1623,12.779,1705,7.332,1782,6.113,2026,5.978,2230,8.794,2363,6.567,2664,9.736,2815,7.332,3308,4.11,3327,4.372,3339,8.106,3344,7.394,3359,8.427,3384,8.106,3507,8.794,3724,9.736,3740,8.794,4538,8.106,5076,14.385,5079,11.242,5080,11.242,5083,11.242,5137,15.864,5138,12.551,5139,12.551,5140,12.551,5141,15.864,5142,12.551,5143,12.551,5144,12.551]],["keywords/186",[]],["title/187",[2292,519.621,4900,783.844]],["content/187",[]],["keywords/187",[]],["title/188",[5145,1007.024]],["content/188",[3,3.285,7,1.862,16,2.176,17,3.015,18,3.389,20,1.551,22,1.144,27,2.131,34,2.59,40,3.015,45,2.087,48,2.574,53,4.502,72,3.015,74,1.797,85,10.71,86,1.158,93,1.6,94,2.383,95,2.814,100,1.68,111,4.956,116,1.642,124,1.336,125,1.6,127,4.555,134,4.042,135,1.6,142,1.626,153,2.549,154,1.708,158,2.909,159,4.352,164,3.363,170,2.274,181,6.347,190,1.481,208,1.416,216,0.985,223,2.006,239,1.83,245,3.577,252,2.327,265,1.737,274,8.104,289,5.601,293,3.861,296,4.182,305,2.442,307,1.481,319,2.728,333,1.797,344,2.131,346,2.046,357,5.567,358,2.395,367,7.229,377,2.131,381,3.825,382,1.708,402,4.467,411,3.917,416,2.176,447,1.737,449,2.472,481,2.383,511,2.909,512,6.713,524,2.673,543,3.35,554,2.814,624,0.999,665,2.909,674,3.861,675,1.797,680,4.555,700,2.046,784,3.271,820,3.235,822,4.625,877,2.964,907,3.861,913,5.388,978,2.909,990,2.909,1133,3.621,1178,2.442,1185,2.59,1333,1.862,1340,3.621,1375,3.621,1376,3.175,1380,2.727,1400,3.861,1442,3.621,1466,5.563,1525,2.727,1534,4.232,1613,7.58,1615,7.58,1686,2.727,1696,2.727,1712,6.091,1799,4.182,1854,3.363,1887,2.814,1903,8.669,1981,2.814,2068,2.274,2137,3.015,2194,3.271,2246,2.909,2283,1.968,2292,6.091,2302,6.874,2350,2.506,2358,3.271,2360,4.483,2363,5.922,2570,3.271,2614,4.182,2643,2.727,2673,3.621,2897,3.43,2905,3.271,3127,3.861,3302,4.182,3309,2.327,3359,3.134,3374,5.639,3502,3.015,3543,4.182,3592,8.396,3693,3.43,3767,4.182,3791,3.015,3863,3.134,4175,10.342,4226,3.43,4228,4.182,4398,3.134,4470,3.861,4799,3.861,4900,12.915,4901,6.347,4904,5.953,4943,8.396,5145,11.022,5146,4.668,5147,4.182,5148,6.874,5149,4.668,5150,4.668,5151,4.668,5152,4.668,5153,4.668,5154,4.668,5155,4.668,5156,10.342,5157,14.527,5158,4.668,5159,4.668,5160,6.874,5161,9.772,5162,7.674,5163,4.668,5164,3.861,5165,4.668,5166,9.772,5167,7.674,5168,4.668,5169,4.668,5170,4.668,5171,4.668,5172,7.674,5173,15.744,5174,8.753,5175,11.201,5176,7.674,5177,4.668,5178,7.674,5179,4.668,5180,11.318,5181,12.044,5182,8.753,5183,8.753,5184,8.753,5185,8.753,5186,4.668,5187,4.668,5188,4.668,5189,4.668,5190,7.674,5191,4.668,5192,4.668,5193,4.668,5194,4.668,5195,4.668,5196,4.668,5197,6.874,5198,7.674,5199,4.668,5200,4.182,5201,4.668,5202,4.668,5203,4.668,5204,4.668,5205,4.668,5206,4.668,5207,4.668,5208,4.668,5209,4.668,5210,4.668,5211,4.668,5212,4.668,5213,7.674,5214,4.668,5215,4.668,5216,4.668,5217,4.668,5218,4.668,5219,4.668,5220,4.668,5221,7.674,5222,4.668,5223,4.668,5224,4.668]],["keywords/188",[]],["title/189",[5225,1073.638]],["content/189",[3,2.547,18,3.143,24,4.934,53,4.616,79,2.158,85,7.516,86,1.296,89,2.414,93,5.416,95,3.32,98,1.35,111,3.557,114,3.698,116,2.668,124,2.51,131,2.826,134,2.279,138,3.859,153,2.914,154,2.015,170,2.683,193,6.446,198,3.037,201,3.432,208,1.671,215,2.567,223,2.367,245,3.548,274,7.516,289,5.055,305,2.882,307,1.747,319,2.811,333,2.12,336,2.279,357,5.335,358,3.338,367,7.412,402,4.819,417,4,447,2.049,453,2.957,474,2.882,483,1.982,512,6.694,524,1.919,543,4.275,624,1.178,633,4.047,638,3.32,665,3.432,675,2.12,725,1.696,775,5.257,784,3.859,798,1.747,820,4.609,822,6.59,871,2.567,877,1.671,907,7.256,908,3.859,989,3.557,1125,3.859,1185,4.208,1349,3.037,1409,3.698,1412,3.859,1466,4.523,1511,2.957,1599,4.934,1613,8.482,1615,8.482,1672,4.273,1712,4.273,1806,3.557,1807,3.859,1809,4.273,1903,9.51,2137,5.666,2208,4.934,2273,3.432,2292,2.683,2319,4.273,2360,3.217,2363,2.882,2546,4.047,2613,4.273,2622,9.043,2654,3.557,3168,4.047,3309,2.745,3374,4.047,3418,3.698,3498,3.32,3592,11.205,3693,4.047,3862,8.034,4172,4.273,4175,10.313,4226,11.181,4383,7.256,4398,3.698,4416,3.32,4444,9.043,4900,11.181,4901,4.555,4904,4.273,4929,4.934,4930,9.794,4943,8.373,5145,11.254,5147,4.934,5148,4.934,5156,9.043,5157,4.934,5160,4.934,5164,7.256,5173,15.979,5174,4.934,5175,11.17,5181,12.995,5182,9.794,5183,9.794,5184,9.794,5185,9.794,5197,12.198,5225,13.066,5226,5.508,5227,5.508,5228,11.17,5229,5.508,5230,10.935,5231,10.935,5232,5.508,5233,5.508,5234,8.774,5235,10.935,5236,8.774,5237,5.508,5238,10.935,5239,8.774,5240,5.508,5241,5.508,5242,5.508,5243,5.508,5244,12.47,5245,8.774,5246,5.508,5247,5.508,5248,8.774,5249,5.508,5250,5.508,5251,5.508,5252,5.508,5253,8.774,5254,5.508,5255,5.508,5256,5.508,5257,8.774,5258,5.508]],["keywords/189",[]],["title/190",[1311,715.826]],["content/190",[6,7.77,10,5.431,18,2.746,23,3.314,25,5.562,48,6.009,53,3.305,79,4.269,81,5.85,86,1.926,93,3.736,94,5.562,97,8.453,107,7.317,116,3.096,118,5.701,131,3.51,134,4.508,143,6.009,145,2.149,149,6.365,161,8.453,174,7.038,179,3.987,208,3.305,216,2.3,223,4.683,239,2.599,265,4.054,269,7.317,286,8.209,289,4.808,359,6.365,375,8.007,524,3.796,624,2.331,635,4.872,721,2.564,764,4.594,833,4.683,894,7.635,1334,6.568,1399,6.568,1510,8.453,1534,6.009,1566,7.038,1592,8.209,1712,7.917,1821,7.576,1896,4.973,2246,6.791,2296,9.761,2344,7.038,2350,5.85,2365,9.719,2448,8.453,2500,9.761,2555,7.038,2825,6.18,3490,8.453,3502,9.349,3693,8.007,3700,9.012,3863,7.317,3894,9.012,4172,8.453,4252,9.761,4900,13.244,4904,8.453,5059,9.761,5145,12.608,5156,9.012,5225,13.442,5228,9.761,5259,10.897,5260,10.897,5261,10.897,5262,10.897,5263,10.897,5264,10.897,5265,10.897,5266,9.761]],["keywords/190",[]],["title/191",[623,265.389,2544,446.034,3308,203.791,4353,242.131]],["content/191",[]],["keywords/191",[]],["title/192",[3396,647.04]],["content/192",[3,3.102,18,3.601,27,6.521,74,4.114,86,1.693,93,3.663,98,2.62,108,4.421,109,6.805,124,3.057,130,6.659,140,8.564,145,2.108,179,7.084,206,5.09,216,2.255,312,3.495,319,2.944,333,4.114,357,5.598,358,2.62,409,5.792,608,3.783,623,6.043,680,6.659,833,4.592,979,6.242,990,6.659,1198,7.67,1258,7.502,1402,3.975,1432,4.421,1535,6.902,1704,6.441,2504,10.497,2818,9.572,3070,8.903,3319,11.277,3327,3.722,3396,8.022,3545,7.851,3579,5.892,3592,9.593,3598,9.572,3731,5.326,4247,5.326,4258,11.083,4549,11.083,4841,8.289,5266,9.572,5267,10.686,5268,14.288,5269,10.686,5270,10.686]],["keywords/192",[]],["title/193",[53,323.594,3862,783.844]],["content/193",[3,2.249,16,2.201,22,1.157,23,1.773,34,1.593,41,2.111,45,2.111,53,4.682,73,1.142,86,1.767,93,4.634,98,1.157,108,3.205,116,1.01,124,1.351,137,2.249,142,1.645,154,1.727,167,1.544,173,3.17,179,5.954,180,3.05,185,1.411,190,1.498,191,2.249,206,4.691,215,2.201,219,2.573,229,2.41,285,3.05,308,1.174,319,2.989,333,1.818,350,2.249,358,1.899,365,3.395,374,1.351,404,1.85,409,5.555,416,2.201,417,4.169,418,2.982,431,2.069,449,3.172,459,2.201,473,7.984,483,4.527,512,2.535,524,3.431,543,3.907,561,3.611,608,2.742,613,3.463,623,4.245,624,1.01,676,3.469,680,3.611,726,1.569,794,2.678,825,3.905,877,1.432,979,2.758,1013,3.05,1014,3.17,1175,3.308,1198,6.117,1258,7.195,1348,3.05,1401,3.17,1402,2.882,1440,2.604,1500,3.308,1511,4.158,1517,2.846,1519,4.229,1535,3.05,1583,3.861,1593,1.99,1686,2.758,1699,3.17,1704,2.846,1709,2.3,1721,5.936,1806,3.05,1839,3.469,1857,3.905,1981,2.846,1988,3.308,2003,4.229,2019,14.883,2026,3.69,2246,2.942,2293,4.229,2324,4.229,2341,7.984,2356,3.17,2519,3.663,2599,13.139,2601,13.139,2613,3.663,2616,3.05,2621,3.17,2905,3.308,3070,4.827,3308,1.223,3309,2.353,3319,3.308,3327,4.709,3339,3.05,3360,4.158,3396,4.909,3419,3.469,3450,3.308,3563,5.427,3579,2.604,3592,7.651,3731,6.271,3862,8.373,4242,4.229,4247,6.271,4257,3.663,4258,7.64,4266,3.663,4271,3.905,4283,4.229,4287,3.905,4335,3.469,4347,4.229,4353,3.032,4437,4.797,4744,4.229,4917,4.229,4943,3.17,5100,4.229,5271,4.722,5272,4.722,5273,4.722,5274,9.849,5275,4.722,5276,4.722,5277,4.229,5278,15.888,5279,7.746,5280,13.52,5281,4.722,5282,13.52,5283,13.52,5284,15.888,5285,13.52,5286,15.888,5287,13.52,5288,14.909,5289,14.909,5290,4.722,5291,7.746,5292,7.746,5293,7.746,5294,7.746,5295,7.746,5296,7.746,5297,7.746,5298,7.746,5299,4.722,5300,7.746,5301,4.722,5302,4.722,5303,4.722,5304,4.722,5305,4.722,5306,4.722,5307,4.722]],["keywords/193",[]],["title/194",[3886,1007.024]],["content/194",[23,2.562,25,5.713,77,6.746,86,1.952,89,6.456,93,5.05,131,4.746,179,4.094,206,5.331,212,3.551,216,2.362,252,5.578,275,3.962,319,2.872,336,4.63,382,4.094,409,5.926,511,6.974,524,3.898,525,7.229,623,3.777,634,9.256,765,10.025,798,3.551,827,5.713,1016,5.217,1182,7.842,1189,4.385,1258,7.677,1886,9.256,2026,5.331,2030,7.842,2145,10.025,2499,6.538,2517,9.256,3308,2.9,3327,3.898,3396,5.578,3483,7.909,3579,6.171,3585,8.682,3731,5.578,3886,14.106,4247,5.578,4353,5.07,4437,8.022,4654,10.025,4722,10.025,4843,13.196,4995,10.025,5121,12.184,5308,11.192,5309,11.192,5310,11.192,5311,16.47,5312,11.192,5313,11.192,5314,11.192,5315,11.192,5316,11.192,5317,11.192,5318,11.192,5319,11.192]],["keywords/194",[]],["title/195",[2690,909.555]],["content/195",[34,3.408,53,3.063,84,4.178,86,1.63,93,3.462,108,4.178,115,4.81,131,3.253,135,3.462,191,4.81,239,2.409,286,5.727,319,2.928,333,3.888,336,4.178,374,2.889,543,3.462,574,4.919,623,5.666,624,2.16,644,7.02,675,3.888,784,7.075,827,5.155,828,7.834,977,5.421,1198,9.956,1440,5.568,1477,5.155,1563,7.834,1697,5.899,1705,5.899,2138,5.421,2283,5.797,2363,5.284,2365,6.78,2366,9.046,2616,6.522,2690,10.957,2815,5.899,3070,6.293,3308,4.052,3319,7.075,3327,3.518,3396,8.369,3466,11.374,3483,7.383,3545,12.336,3597,12.319,3665,7.075,3875,9.046,4353,4.815,4437,4.919,4538,6.522,4546,15.039,4547,12.319,4548,15.039,4549,7.834,4550,12.319,4551,12.319,4552,9.046,4554,9.046,4555,9.046,4677,9.046,4938,7.834,5200,12.319,5320,13.753,5321,10.099,5322,10.099,5323,10.099,5324,10.099]],["keywords/195",[]],["title/196",[3415,909.555]],["content/196",[2,4.741,3,2.356,6,4.357,8,4.045,16,3.783,22,1.99,23,2.699,27,3.704,34,4.686,47,6.296,53,5.416,66,3.296,86,0.962,93,5.55,98,1.99,108,3.358,116,1.736,135,4.042,140,5.877,142,4.107,145,1.601,153,3.917,154,2.969,160,3.629,162,4.045,173,5.449,185,3.524,190,2.575,206,6.615,215,3.783,216,1.713,222,3.557,289,3.917,305,6.169,319,2.846,333,3.125,374,2.322,402,2.696,409,6.078,417,2.969,449,4.473,451,5.687,456,2.827,481,4.143,512,7.455,524,2.827,543,2.782,623,3.979,624,1.736,629,4.892,642,6.712,664,4.892,798,3.741,833,3.488,975,4.246,1198,7.455,1258,7.105,1401,7.917,1432,3.358,1440,4.475,1477,4.143,1517,4.892,1556,3.866,1593,5.854,1712,3.953,1981,4.892,2026,3.866,2346,8.262,2360,4.741,2613,9.147,2618,6.296,2643,4.741,2697,6.296,2706,5.242,2815,4.741,2825,4.603,2961,11.824,3070,10.525,3308,3.055,3309,4.045,3327,5.309,3376,7.27,3402,4.741,3415,11.834,3498,4.892,3566,6.296,3579,7.658,3731,6.922,3862,10.204,3928,7.27,4222,7.107,4247,8.07,4282,5.963,4333,6.712,4353,2.499,4437,5.743,4553,6.296,4841,6.296,5277,7.27,5325,8.116,5326,8.116,5327,8.116,5328,8.116,5329,8.116,5330,8.116,5331,8.116,5332,17.429,5333,8.116,5334,8.116,5335,8.116,5336,8.116]],["keywords/196",[]],["title/197",[764,547.25]],["content/197",[20,4.047,25,4.334,34,2.865,41,3.797,53,3.695,74,3.269,86,1.844,93,2.911,104,3.269,125,2.911,131,2.735,135,2.911,145,2.403,154,3.106,162,6.072,206,4.045,286,4.816,319,2.974,333,3.269,357,4.773,404,3.327,409,5.93,417,5.212,484,4.232,485,5.291,524,2.958,543,2.911,624,1.816,635,3.797,725,2.614,764,3.58,833,6.689,877,2.576,1177,4.816,1181,5.291,1198,4.558,1349,4.682,1592,4.816,1696,4.96,2341,5.949,2455,9.45,2815,4.96,2950,7.606,3308,2.2,3310,10.644,3327,5.741,3334,7.606,3344,3.958,3360,4.558,3379,11.079,3396,6.072,3402,8.322,3579,7.856,3592,5.701,3699,8.951,3731,6.072,3773,5.949,3823,5.949,4247,6.072,4287,7.023,4353,3.75,4427,7.023,4437,5.934,4549,12.784,4601,15.365,4664,7.023,5096,7.606,5337,12.183,5338,8.492,5339,16.481,5340,14.247,5341,14.247,5342,15.566,5343,12.183,5344,8.492,5345,15.566,5346,12.183,5347,12.183,5348,8.492,5349,8.492,5350,8.492,5351,8.492,5352,8.492,5353,8.492,5354,8.492]],["keywords/197",[]],["title/198",[131,343.638,975,558.161]],["content/198",[18,2.633,21,4.244,93,3.582,108,6.584,131,5.485,135,3.582,137,4.977,162,8.487,206,4.977,297,7.678,319,2.552,333,4.023,359,6.104,409,5.064,431,4.579,447,3.888,511,6.512,526,4.168,605,4.49,623,3.526,624,3.404,628,8.642,630,3.888,833,4.49,975,10.192,1189,4.094,1198,8.543,1204,8.642,1251,8.106,1432,4.323,1566,6.749,1592,5.926,1705,6.104,1749,11.64,1977,7.016,2029,7.678,2092,7.678,2367,9.36,2616,6.749,2643,6.104,2651,8.642,2654,6.749,2706,6.749,2835,7.016,3308,3.647,3309,5.208,3339,6.749,3360,5.609,3379,9.09,3396,7.932,3425,15.252,3449,8.642,3482,8.106,3563,7.321,3577,6.749,4260,8.642,4353,4.9,4416,8.483,4437,8.294,4729,9.36,5114,8.106,5355,10.45,5356,10.45,5357,10.45,5358,10.45,5359,10.45,5360,10.45,5361,10.45,5362,10.45,5363,10.45,5364,10.45,5365,10.45,5366,14.075,5367,10.45,5368,10.45,5369,10.45]],["keywords/198",[]],["title/199",[2400,782.439]],["content/199",[2,4.661,23,3.149,41,3.568,53,4.172,86,1.792,93,2.735,97,6.19,100,2.871,116,1.707,131,2.57,142,2.779,154,2.919,185,2.385,206,3.801,219,2.651,229,4.073,239,1.903,252,3.977,275,4.123,319,2.968,357,6.578,386,3.886,402,3.869,409,2.871,444,5.591,455,5.591,499,2.692,596,5.295,623,4.641,624,1.707,629,4.809,637,4.661,764,3.364,784,11.764,789,10.432,822,4.809,833,6.498,877,2.42,1026,9.034,1135,3.497,1163,4.972,1198,7.383,1258,7.826,1333,3.182,1350,4.175,1376,4.818,1466,5.69,1511,4.283,1534,4.4,1556,3.801,1592,4.525,1593,3.364,1600,5.153,1685,4.525,2065,5.863,2072,6.19,2150,11.374,2327,6.599,2400,11.101,2570,11.764,2612,7.147,3151,7.147,3308,2.068,3309,3.977,3327,4.791,3344,5.428,3384,8.883,3445,5.863,3450,5.591,3541,6.19,3572,5.863,3731,6.855,3831,5.357,4226,10.105,4229,10.432,4247,3.977,4341,7.819,4353,5.169,4431,6.599,4437,7.365,4456,6.19,4597,7.147,4672,7.147,5164,6.599,5370,7.979,5371,7.979,5372,7.979,5373,7.979,5374,7.979,5375,7.979,5376,7.979,5377,7.979,5378,7.979,5379,7.979,5380,7.979,5381,11.647,5382,7.979,5383,7.979,5384,7.979,5385,7.979,5386,7.979,5387,7.979]],["keywords/199",[]]],"invertedIndex":[["",{"_index":319,"title":{},"content":{"6":{"position":[[296,1],[332,1],[343,1],[439,1],[532,1],[556,1],[769,1],[785,1],[793,1],[800,1],[806,1],[808,1],[816,1],[827,1],[860,1],[866,1],[870,3],[874,1],[900,1],[905,1],[913,1],[915,1],[917,1],[925,1],[929,1],[935,3],[939,1],[965,1],[969,1],[1005,1],[1011,1],[1036,1],[1045,1],[1069,1],[1074,1]]},"7":{"position":[[275,1],[290,2],[293,2],[302,1],[328,1],[343,1],[347,1],[358,1],[384,1],[389,1],[440,1],[454,2],[476,2],[491,1],[493,1],[495,2],[565,1],[613,1],[637,1],[661,1],[678,1],[733,1],[787,1],[840,1],[851,1],[886,1],[890,1],[902,1],[938,1],[942,1],[962,1],[964,2],[1000,1],[1034,1],[1089,1],[1155,1],[1157,2],[1166,1],[1179,1]]},"8":{"position":[[87,1],[97,1],[102,1],[171,1],[198,2]]},"9":{"position":[[431,1],[557,1],[581,1],[666,1],[730,1],[747,1],[781,1],[795,1]]},"10":{"position":[[140,2],[151,1],[168,1],[205,1],[311,1],[386,1],[417,1],[455,1],[465,1]]},"11":{"position":[[348,1],[358,1],[373,1],[414,1],[416,1],[453,1],[488,2],[491,2],[512,1]]},"12":{"position":[[230,1],[268,1],[304,1],[349,1],[359,1],[374,1],[376,1],[411,1],[447,2],[450,2],[472,1],[580,1]]},"13":{"position":[[532,1],[544,1],[568,1],[573,1],[585,1],[595,1],[614,1],[728,1],[734,1],[772,1],[798,1],[829,1],[841,1],[897,1],[1024,1],[1054,1],[1112,1],[1148,1],[1268,1],[1294,1],[1319,1],[1364,1],[1456,1],[1527,1],[1543,1],[1669,1],[1776,1],[1789,1]]},"14":{"position":[[1349,1],[1369,1],[1374,1],[1398,1],[1403,1],[1415,1],[1425,1],[1455,1],[1585,1],[1591,1],[1629,1],[1655,1],[1686,1],[1695,1],[1771,1],[1802,1],[1818,1],[1848,1],[1876,2],[1915,1],[2033,1],[2058,1],[2088,1],[2146,1],[2182,1],[2340,1],[2366,1],[2391,1],[2436,1],[2528,1],[2599,1],[2626,1],[2752,1],[2859,1],[2872,1]]},"15":{"position":[[718,1],[738,1],[743,1],[767,1],[772,1],[784,1],[794,1],[826,1],[954,1],[972,1],[978,1],[1016,1],[1076,1],[1085,1],[1181,68],[1250,1],[1334,1],[1354,1],[1375,1],[1393,1],[1409,1],[1439,1],[1456,68],[1544,2],[1583,1],[1701,1],[1726,1],[1756,1],[1814,1],[1850,1],[2012,1],[2038,1],[2063,1],[2108,1],[2200,1],[2271,1],[2300,1],[2426,1],[2533,1],[2546,1]]},"17":{"position":[[152,1],[204,1],[231,1],[242,1],[257,1],[342,1]]},"18":{"position":[[85,1]]},"19":{"position":[[257,1],[286,1],[344,1],[364,1]]},"20":{"position":[[240,1],[280,1],[588,1],[621,1],[644,1],[699,1],[708,1],[1071,1],[1091,1],[1106,1],[1112,1],[1176,1],[1209,1],[1220,1],[1279,1],[1289,1],[1350,1],[1381,1],[1460,1],[1483,1],[1537,1],[1573,1],[1616,1],[1660,1],[1762,1],[1770,1],[1797,1],[1884,1],[1902,1],[1915,1],[1920,1],[1954,1],[1972,1],[1989,1],[2026,1],[2028,1],[2030,1],[2066,2],[2069,1],[2110,3],[2114,1],[2116,1],[2134,1],[2156,2],[2159,1],[2193,1],[2195,1],[2205,1],[2296,1],[2414,1],[2489,1],[2503,1],[2598,1],[2619,1],[2627,1],[2649,1],[2734,1]]},"22":{"position":[[291,1],[293,2],[343,2],[420,1],[439,1],[453,2],[515,1],[544,2],[605,1],[699,1],[712,1],[724,1],[781,1],[783,2],[817,1],[908,1],[995,1],[1065,2],[1210,1],[1230,1],[1246,1],[1250,1],[1257,1],[1259,2],[1262,1],[1358,1],[1360,2],[1409,2],[1475,1],[1504,2],[1537,1],[1585,1],[1609,1],[1615,2],[1686,1],[1849,1],[1919,2],[1942,1],[1987,2],[2014,1],[2059,2],[2085,1],[2130,2],[2155,1],[2200,2],[2224,1],[2264,2],[2316,1],[2351,1],[2402,1],[2420,1],[2493,1],[2668,1],[2720,1],[2780,1],[2842,1],[2879,1],[2921,1],[2974,1],[3041,1]]},"23":{"position":[[220,1],[288,1],[368,1],[436,1],[503,1],[573,1]]},"24":{"position":[[457,1],[505,1],[555,1],[557,2],[596,1],[629,1],[665,1],[700,1],[727,1],[766,1],[809,1],[853,1],[899,1],[964,1],[1023,1],[1104,1],[1172,1],[1174,2],[1214,1],[1236,1],[1257,1],[1342,1],[1409,1],[1456,1],[1469,2],[1490,2],[1505,2],[1526,2],[1612,1],[1614,2],[1630,1],[1632,2],[1646,1],[1648,2],[1662,1],[1807,1],[1891,1],[2031,1],[2144,1],[2234,1]]},"25":{"position":[[182,1],[230,1],[280,1],[282,2],[321,1],[351,1],[385,1],[421,1],[446,1],[483,1],[527,1],[572,1],[619,1],[684,1],[743,1],[824,1],[892,1],[894,2],[934,1],[956,1],[977,1],[1062,1],[1129,1],[1176,1],[1189,2],[1210,2],[1225,2],[1246,2],[1329,1],[1331,2],[1345,1],[1347,2],[1366,1],[1368,2],[1382,1],[1531,1],[1615,1],[1755,1],[1868,1],[1958,1]]},"28":{"position":[[879,1],[938,1],[988,1],[1043,1],[1249,1],[1329,1],[1384,1],[1481,1],[1546,1],[1766,1],[1886,1],[1888,1],[1970,1],[2018,1],[2077,1],[3049,1],[3129,1],[3179,1],[3272,1],[3332,1],[3673,1],[3732,1]]},"30":{"position":[[1211,1],[1269,1],[1324,1],[1352,1],[1379,1],[1405,1],[1615,1],[1695,1],[1750,1],[1842,1],[1983,1],[2054,1],[2964,1],[3044,1],[3099,1],[3191,1],[3268,1],[3392,1],[3480,1],[3548,1],[3747,1],[4888,1],[4968,1],[5018,1],[5106,1],[5237,1],[5304,1],[6032,1],[6112,1],[6167,1],[6260,1],[6337,1],[6467,1],[6555,1],[6622,1],[6827,1],[8413,1],[8479,1],[8511,1],[8547,1],[8587,1],[8619,1],[8621,1],[8710,1],[8719,1],[8721,2],[8724,1],[8804,1],[8873,1],[8889,1],[8898,1],[8939,1],[8967,1],[8983,1],[8992,1],[9069,1],[9088,1],[9148,1],[9210,1],[9277,1],[9303,1],[9412,1],[9458,1],[9534,1],[9610,1],[9650,1],[9652,2],[9720,2],[9860,1],[9944,1],[10128,3],[10140,1],[10197,1],[10251,1],[10301,1],[10352,1]]},"32":{"position":[[484,1],[536,1],[586,1],[1609,1],[1660,1]]},"34":{"position":[[1032,1],[1064,1],[1136,1],[1225,1],[1241,1],[1263,1],[1319,2],[1346,1],[1422,1],[1487,1],[1510,2],[1595,1],[1653,1],[1710,1],[1760,1],[1809,1],[1818,1],[1870,1],[1885,1],[1959,2],[2068,1],[2087,1],[2114,1],[2204,1],[2233,1],[2241,1],[2259,1],[2276,1],[2291,2],[2345,2],[2361,1],[2435,2],[2522,1],[2537,2],[2582,1],[2630,1],[2639,1],[2710,1],[2752,1],[2819,1],[2840,1],[3184,1],[3310,1],[3701,1]]},"39":{"position":[[543,1],[545,2],[562,1],[590,1],[595,1],[675,1],[695,1],[738,1],[860,1],[876,1],[898,1],[937,1],[953,1],[985,1],[1062,1],[1085,1],[1100,1],[1173,1],[1283,1],[1300,1],[1327,1],[1415,1],[1453,1],[1461,1],[1479,1],[1496,1],[1508,1],[1565,2],[1581,1],[1654,1],[1734,1],[1746,1],[1782,1],[1873,1],[2015,1],[2054,1],[2078,1],[2087,1],[2214,1],[2279,1],[2305,1],[2406,1],[2454,1],[2478,1],[2616,1],[2640,1],[2684,1],[2743,1],[2808,1],[2874,1],[2987,1],[3105,1],[3107,2],[3139,1],[3173,1],[3255,1]]},"40":{"position":[[116,1],[1650,1],[2618,1]]},"43":{"position":[[357,1],[455,1],[480,1],[527,1],[542,1],[588,1]]},"44":{"position":[[210,1],[230,1],[232,2],[272,2],[457,1],[535,1],[608,1],[640,1],[662,2],[708,1],[1336,1],[1342,2],[1389,3],[1468,1],[1480,2]]},"45":{"position":[[1991,1],[2040,1],[2073,1],[2107,1],[2181,1],[2827,1],[2860,1],[2887,1],[2961,1]]},"46":{"position":[[592,1]]},"47":{"position":[[107,1],[145,1],[181,1]]},"51":{"position":[[128,1],[161,1],[175,1],[239,1],[275,1],[460,1],[486,1],[531,1],[578,1],[635,1],[670,1],[1090,1],[1125,1],[1160,3],[1177,1],[1207,1],[1224,2],[1227,3],[1275,1],[1277,2],[1320,1],[1363,2],[1383,1],[1435,1],[1685,1],[1718,1],[2091,1],[2266,1],[2298,2],[2301,4],[2317,1],[2349,1],[2393,2],[2396,6],[2416,1],[2489,1],[3652,1],[3694,1],[3708,1],[3722,1],[3747,2],[3750,4],[3971,1],[4122,1],[4160,1],[4181,1]]},"52":{"position":[[159,1],[200,1],[240,1],[282,1],[322,1],[365,1],[397,1],[745,1],[757,1],[798,1],[829,1],[883,1],[896,1],[918,1],[934,1],[980,1],[1011,2],[1014,3],[1033,2],[1036,4],[1049,1],[1091,2],[1094,1],[1096,1],[1098,1],[1114,1],[1127,1],[1146,1]]},"53":{"position":[[190,1],[339,1],[660,1],[712,2],[752,1],[867,1],[1094,2],[1144,1],[1149,1],[1283,1],[1347,1],[1574,1]]},"57":{"position":[[165,1]]},"60":{"position":[[136,1]]},"61":{"position":[[1525,1],[1576,1],[1578,1],[1580,1],[1704,1],[1765,1],[1779,1],[1792,1],[1794,3],[1798,1],[2149,1],[2206,1],[2254,1],[2315,1]]},"62":{"position":[[466,1],[543,2],[557,1],[581,1],[613,1],[640,1],[682,1],[770,1],[918,1],[965,1],[1037,1],[1094,1],[1096,1],[1098,1],[1100,1],[1151,1],[1223,1],[1250,1],[1336,1],[1422,1],[1507,2],[1513,3]]},"64":{"position":[[793,1],[836,1],[873,2],[907,2],[943,1],[958,1],[976,1],[994,1],[1026,1],[1484,1],[1513,1],[1540,1],[1559,1],[1561,3],[1585,1],[1604,1],[1640,1],[1666,1],[1698,1]]},"65":{"position":[[596,1],[625,1],[647,1],[665,1],[687,1],[829,1],[846,2],[879,1],[916,1],[1596,1],[1628,1],[1681,1],[1718,2],[1752,2],[1789,1],[1806,2],[1843,1],[1876,1],[2323,1],[2359,1],[2376,2],[2397,1],[2436,1]]},"68":{"position":[[499,1],[539,1],[589,1]]},"70":{"position":[[279,1],[453,1],[617,2],[636,1],[664,1],[699,1],[706,1],[710,1],[732,1],[963,1],[1023,1],[1030,1],[1070,1],[1110,1],[1137,1],[1174,1]]},"71":{"position":[[379,1],[553,1],[717,2],[736,1],[764,1],[799,1],[806,1],[810,1],[832,1],[1213,1],[1253,1],[1261,1],[1288,1],[1325,1]]},"74":{"position":[[570,1],[610,1],[628,1],[647,2],[665,1],[687,1]]},"76":{"position":[[217,1],[275,1],[347,1],[388,1],[430,1],[438,1],[502,1],[563,1],[629,1],[692,1],[719,1],[764,1],[1002,1],[1061,1],[1110,1],[1142,1],[1215,1],[1254,1],[1281,1],[1331,1],[1360,1],[1422,1],[1473,1],[1514,1],[1548,1],[1607,1],[1678,2],[1707,1],[1734,2],[1763,1],[1952,1],[1967,1],[1971,1],[2010,1],[2037,1],[2067,1],[2097,1],[2143,1],[2172,1],[2191,1],[2207,1],[2216,1],[2280,1],[2344,1],[2459,2],[2478,1],[2490,1],[2496,2],[2520,3],[2609,1],[2645,1],[2714,1],[2733,1],[2749,1],[2787,1],[2831,1],[2868,1],[2887,1],[2903,1],[2928,1],[2938,1],[2984,1],[3030,1],[3072,1],[3122,1],[3177,1],[3196,1],[3212,1],[3237,1],[3263,2],[3268,1]]},"78":{"position":[[167,1],[200,1],[231,1],[288,1],[307,1],[322,1],[429,1],[596,1]]},"88":{"position":[[601,1],[655,1],[705,1],[753,1],[778,1],[800,1],[956,1],[990,1],[1077,1],[1099,1],[1197,1],[1230,1],[1259,1],[1417,1],[1487,1],[1748,1],[1816,1],[2688,1],[2717,1],[2734,1],[2745,1],[3150,1]]},"90":{"position":[[369,1],[429,1],[489,1],[536,1],[593,1],[643,1],[675,1],[762,1],[832,1],[896,1],[923,1],[940,1],[1024,1],[1032,1],[1062,1],[1104,1],[1150,1],[1190,1],[1243,1],[1279,1],[1319,1],[1352,1],[1374,1],[1556,1],[1705,1],[1798,1],[1839,1],[2147,1],[2217,1],[2281,1],[2308,1],[2325,1],[2409,1],[2417,1],[2447,1],[2489,1],[2535,1],[2575,1],[2628,1],[2664,1],[2707,1],[2729,1],[2849,1],[2942,1],[2983,1],[3224,1],[3287,1],[3343,1],[3403,1],[3463,1],[3523,1],[3592,1],[3660,1],[3693,1],[3726,1],[3759,1],[3773,1],[3797,1],[3853,1],[3990,1],[4039,1],[4129,1],[4305,1],[4317,1],[4397,1],[4410,1],[4634,1]]},"91":{"position":[[417,1],[471,1],[547,1],[606,1],[631,1],[919,1],[1001,1],[1062,1],[1089,1],[1738,1],[1775,1],[1932,1],[1974,1],[2014,1],[2033,3],[2083,1],[2116,1],[2180,1],[2212,1],[2288,1],[2290,2],[2458,1],[2506,1],[2540,1],[2588,1],[2640,1],[2689,1],[2773,1],[2818,1],[2873,1],[2890,1],[2908,1],[2963,1],[3016,1],[3069,2],[3124,1],[3190,1],[3253,1],[3373,1],[3398,1],[3419,1],[3421,2],[3529,1],[3580,1],[3673,1],[3735,1],[3811,1],[3888,1],[3963,1],[4039,1],[4099,1],[4145,1],[4229,2],[4238,2],[4325,1],[4406,61],[5143,1],[5216,61],[5520,1],[5599,61]]},"92":{"position":[[271,1],[318,1],[352,1],[400,1],[452,1],[501,1],[585,1],[630,1],[685,1],[702,1],[720,1],[775,1],[828,1],[881,2],[936,1],[1002,1],[1065,1],[1179,61],[1737,61],[1896,61]]},"93":{"position":[[1503,1],[1527,1],[1540,1],[1542,2],[1627,1],[1629,2],[1678,2],[1707,1],[1770,1],[1847,1],[1912,1],[1975,1],[2093,1],[2162,1],[2220,2],[2249,1],[2355,1],[2404,2],[2445,1],[2483,1],[2556,1],[2577,1],[2600,1],[2763,1],[2795,1],[2830,1],[2927,1],[3005,1],[3198,1],[3225,2],[3238,1],[3259,2],[3306,1],[3400,1],[3505,1],[3626,1],[4016,1],[4070,1],[4120,1],[4168,1],[4193,1],[4215,1],[4345,1],[4387,1],[4427,1],[4446,3],[4496,1],[4529,1],[4586,1],[4626,1],[4666,1],[4668,2],[4687,1],[4689,2],[4743,1],[4753,3],[4762,1],[4764,1],[4797,1],[4819,1],[4821,2],[4835,1],[4866,1],[4910,1],[4950,1],[5064,1],[5158,1],[5168,3],[5177,1],[5179,1],[5212,1],[5234,1],[5236,2],[5250,1],[5281,1],[5325,1],[5365,1],[5492,1],[5587,1]]},"96":{"position":[[724,1],[794,1],[1143,1],[1208,1],[1221,1],[1282,3],[1673,1],[1759,1],[2219,1],[2307,1]]},"97":{"position":[[1554,1],[1583,1],[1627,1],[1629,1],[2007,1],[3584,1],[3602,1],[3633,1],[3710,1],[3759,1],[3761,1],[3763,2],[3822,1],[3836,1],[3878,1],[4247,4],[5053,1],[5058,1],[5107,1],[5109,4]]},"103":{"position":[[526,1],[563,1],[576,1],[581,1],[601,1],[609,1],[622,1],[627,1],[928,1],[1007,1],[1029,1],[1079,1],[1145,1],[1199,1],[1229,2],[1257,1],[1297,1],[1360,1],[1400,1],[1610,2],[1714,1],[1750,1],[2069,1]]},"105":{"position":[[529,1],[585,1],[629,1],[653,1],[713,1],[780,1],[804,1],[861,1],[885,1],[895,1],[959,1],[1022,1],[1046,1],[1053,1],[1092,1],[1138,1],[1169,1],[1171,1],[1330,1],[1411,1],[1482,1],[1532,1],[1574,1],[1597,1],[1683,1],[1772,2],[1807,1],[1898,1],[2707,1],[2908,1],[3180,1]]},"109":{"position":[[255,1],[294,1],[322,1],[405,1],[423,1],[448,1],[466,1]]},"110":{"position":[[268,1],[470,1],[498,1]]},"111":{"position":[[334,1],[401,2],[444,2],[494,1]]},"112":{"position":[[615,1],[686,1]]},"113":{"position":[[287,2],[354,2],[421,2],[460,1],[462,2],[519,2],[577,2],[601,2],[724,1],[736,1],[738,2],[805,2],[871,2],[956,1],[998,2],[1061,2],[1127,2],[1182,2],[1237,2],[1275,1],[1277,2],[1362,1],[1422,2],[1503,1],[1505,2],[1605,1],[1619,2],[1739,2],[1795,1],[1906,2],[1970,2],[2036,2],[2110,2],[2190,1],[2262,2],[2406,1]]},"115":{"position":[[119,1],[121,2],[215,2],[250,1],[378,1],[450,2],[527,2],[600,2],[675,2],[705,1],[730,2],[733,1],[811,3],[838,1],[1119,1],[1124,1],[1137,1],[1163,2],[1166,1],[1168,1],[1170,18],[1239,1],[1466,1],[1471,1],[1484,1],[1510,2],[1513,1],[1515,1],[1517,18],[1619,1],[1749,1],[1754,1],[1767,1],[1793,2],[1796,1],[1798,1],[1800,18],[1896,1],[2034,1],[2207,1],[2212,1],[2225,1],[2251,2],[2254,1],[2256,1],[2258,18],[2383,1],[2444,1]]},"116":{"position":[[219,1],[221,2],[310,2],[350,1],[478,1],[567,1],[593,2],[665,2],[724,1],[750,2],[753,1],[831,3],[859,1],[1071,1],[1076,1],[1089,1],[1115,2],[1118,1],[1120,1],[1122,18],[1191,1],[1371,1],[1376,1],[1389,1],[1415,2],[1418,1],[1420,1],[1422,18],[1524,1],[1654,1],[1659,1],[1672,1],[1698,2],[1701,1],[1703,1],[1705,18],[1801,1],[1939,1],[2065,1],[2070,1],[2083,1],[2109,2],[2112,1],[2114,1],[2116,18],[2241,1],[2302,1]]},"117":{"position":[[1011,1],[1013,2],[1139,1],[1362,1],[1412,2],[1521,2],[1581,1],[1607,2],[1610,1],[1612,2],[1715,2],[1748,1],[1851,3],[1879,1]]},"121":{"position":[[2212,1],[2224,1]]},"125":{"position":[[4277,3],[5268,1],[5385,1],[5387,1],[5625,1],[5816,1],[5933,1],[8614,1],[8649,1],[8679,1],[8695,1],[9085,1],[9118,1],[9146,1],[11693,1]]},"127":{"position":[[592,1],[633,1],[641,1],[680,2],[709,1],[711,1],[811,1],[1242,1],[1283,1],[1291,1],[1306,1],[1362,1],[1364,1]]},"128":{"position":[[256,2],[270,1],[278,1],[299,1],[481,1],[544,1],[592,1],[667,1],[781,1],[840,1],[1129,2],[1142,1],[1150,1],[1170,1],[1290,1],[1358,1],[1425,1],[1537,1]]},"129":{"position":[[428,1],[444,1],[566,1],[595,1],[1440,1],[1449,1],[1462,1],[1501,1],[1522,1],[1524,1],[1540,1],[1553,1],[1561,1],[1568,2],[1571,2],[1644,1],[1752,2],[1934,1],[1978,1],[2284,3],[2374,4],[2392,1],[2517,1],[2560,1],[2619,1]]},"133":{"position":[[328,1]]},"134":{"position":[[81,3]]},"136":{"position":[[221,3],[363,1],[373,1],[469,3],[492,1]]},"140":{"position":[[18,1],[41,1],[55,1]]},"141":{"position":[[18,1],[52,1],[76,1]]},"142":{"position":[[34,1],[47,1]]},"144":{"position":[[152,1],[213,1],[215,2],[251,2],[278,1],[290,1],[298,1],[323,2],[376,2],[425,1]]},"145":{"position":[[128,1],[148,1],[156,1],[181,2],[265,2],[325,2],[385,2],[447,3],[451,1]]},"146":{"position":[[156,1],[176,1],[178,2],[239,1],[283,2],[379,2],[438,2],[505,1]]},"147":{"position":[[263,1],[312,1],[324,1],[326,2],[389,2],[447,2],[501,2],[567,2],[654,1]]},"152":{"position":[[485,1],[487,2],[575,2],[633,2],[692,1],[719,1],[723,2],[730,2],[774,2],[832,2],[889,2],[944,1],[983,2],[986,2],[1041,2],[1104,1],[1116,1],[1126,1],[1173,1],[1219,1],[1311,1],[1370,1],[1407,1],[1453,1],[1476,1],[1537,1],[1574,1],[1622,1],[1653,1],[1655,1]]},"153":{"position":[[546,1],[562,1],[597,1],[621,1],[662,1],[681,1],[716,1],[741,1],[757,1],[759,2],[824,2],[888,2],[955,2],[1005,1],[1026,1]]},"155":{"position":[[1355,1],[1357,2],[1400,1],[1417,1],[1419,2],[1461,1],[1479,1],[1481,2],[1524,1],[1542,1],[1544,2],[1603,1]]},"156":{"position":[[639,1],[641,2],[694,1],[926,1],[928,2],[1016,2],[1069,1],[1092,2],[1145,2],[1209,1],[1256,1],[1302,1],[1394,1],[1453,1],[1490,1],[1536,1],[1559,1],[1620,1],[1657,1],[1705,1],[1736,1],[1738,1]]},"163":{"position":[[910,1],[974,1],[978,1],[991,1],[1004,1],[1006,1],[1070,1],[1074,1],[1095,1],[1097,1],[1099,1],[1101,1],[1103,1],[1105,1],[1107,1],[1109,1],[1111,1],[1113,1],[1115,1],[1117,1],[1119,1],[1121,1],[1123,1],[1125,1],[1127,1],[1129,1],[1131,1],[1133,1],[1135,1],[1137,1],[1139,1],[1141,1],[1143,1],[1145,1],[1147,1],[1149,1],[1151,1],[1153,1],[1155,1],[1157,1],[1159,1],[1161,1],[1165,1],[1180,1],[1182,1],[1184,1],[1186,1],[1188,1],[1190,1],[1192,1],[1194,1],[1196,1],[1198,1],[1200,1],[1202,1],[1204,1],[1206,1],[1208,1],[1210,1],[1212,1],[1214,1],[1216,1],[1218,1],[1220,1],[1222,1],[1224,1],[1226,1],[1228,1],[1230,1],[1232,1],[1234,1],[1236,1],[1238,1],[1240,1],[1242,1],[1244,1],[1246,1],[1251,1],[1270,1],[1272,1],[1274,1],[1276,1],[1278,1],[1280,1],[1282,1],[1284,1],[1286,1],[1288,1],[1290,1],[1292,1],[1294,1],[1296,1],[1298,1],[1300,1],[1302,1],[1304,1],[1306,1],[1308,1],[1310,1],[1312,1],[1314,1],[1316,1],[1318,1],[1320,1],[1322,1],[1324,1],[1326,1],[1328,1],[1330,1],[1332,1],[1334,1],[1336,1],[1341,1],[1359,1],[1361,1],[1363,1],[1365,1],[1367,1],[1369,1],[1371,1],[1373,1],[1375,1],[1377,1],[1379,1],[1381,1],[1383,1],[1385,1],[1387,1],[1389,1],[1391,1],[1393,1],[1395,1],[1397,1],[1399,1],[1401,1],[1403,1],[1405,1],[1407,1],[1409,1],[1411,1],[1413,1],[1415,1],[1417,1],[1419,1],[1421,1],[1423,1],[1425,1],[1430,1],[1445,1],[1447,1],[1449,1],[1451,1],[1453,1],[1455,1],[1457,1],[1459,1],[1461,1],[1463,1],[1465,1],[1467,1],[1469,1],[1471,1],[1473,1],[1475,1],[1477,1],[1479,1],[1481,1],[1483,1],[1485,1],[1487,1],[1489,1],[1491,1],[1493,1],[1495,1],[1497,1],[1499,1],[1501,1],[1503,1],[1505,1],[1507,1],[1509,1],[1511,1],[1516,1],[1529,1],[1531,1],[1533,1],[1535,1],[1537,1],[1539,1],[1541,1],[1543,1],[1545,1],[1547,1],[1549,1],[1551,1],[1553,1],[1555,1],[1557,1],[1559,1],[1561,1],[1563,1],[1565,1],[1567,1],[1569,1],[1571,1],[1573,1],[1575,1],[1577,1],[1579,1],[1581,1],[1583,1],[1585,1],[1587,1],[1589,1],[1591,1],[1593,1],[1595,1],[1597,1],[1611,1],[1613,1],[1615,3],[1619,1],[1709,1],[1826,1],[1832,1],[1845,1],[1941,2],[1944,1],[1946,1],[2067,1],[2130,1]]},"165":{"position":[[638,1],[656,1],[677,1],[699,1]]},"179":{"position":[[431,1],[433,2],[484,2],[563,1],[575,1],[586,1],[606,2],[686,2],[743,1],[887,1],[951,1],[971,1],[983,1],[985,2],[1089,2],[1167,1],[1266,1],[1291,1],[1293,2],[1400,2],[1457,2],[1517,2],[1607,1]]},"180":{"position":[[398,1],[456,1],[458,2],[501,1],[521,1]]},"181":{"position":[[90,1],[136,1],[138,2],[203,1],[212,1],[258,1],[260,2],[331,1],[340,1],[349,1]]},"183":{"position":[[315,1],[361,1],[363,2],[402,1],[452,1],[461,1],[507,1],[509,2],[548,1],[598,1],[607,1],[616,1]]},"184":{"position":[[164,1],[173,1],[202,1],[213,1],[215,2],[255,2],[283,2],[305,1],[321,1],[379,1],[523,1],[532,1],[548,1],[580,1],[591,1],[599,1],[601,1],[603,1],[632,1],[661,1],[728,1],[1022,2],[1144,1]]},"185":{"position":[[669,1],[701,1],[703,2],[818,1],[829,1],[856,2]]},"186":{"position":[[203,2],[319,1],[344,1],[346,2],[415,2],[499,2],[562,2],[664,1]]},"188":{"position":[[836,1],[904,1],[1067,1],[1074,1],[1081,1],[1087,1],[1091,1],[1120,1],[1126,1],[1132,1],[1136,1],[1184,1],[1257,1],[1318,1],[1378,1],[1555,1],[1651,1],[2025,1],[2063,1],[2104,1],[2142,1],[2185,1],[2431,1],[2474,1],[2914,1],[2969,1],[3010,1]]},"189":{"position":[[971,1],[1033,1],[1137,1],[1143,1],[1149,1],[1153,1],[1182,1],[1188,1],[1194,1],[1198,1],[1211,1],[1271,1],[1407,1],[1413,1],[1419,1],[1423,1],[1452,1],[1458,1],[1464,1],[1468,1],[1481,1],[1543,1],[1745,1],[2094,1],[2134,1],[2375,1],[2417,1],[2664,1],[2704,1]]},"192":{"position":[[128,1],[146,1],[160,1],[182,1],[203,1],[205,2],[259,2],[300,1],[308,1],[321,2],[324,2],[382,1],[390,1],[403,2],[406,2],[462,2],[527,1],[534,1],[556,2],[559,1]]},"193":{"position":[[919,1],[937,1],[939,2],[985,2],[1033,2],[1104,1],[1106,2],[1158,2],[1208,2],[1237,2],[1288,2],[1337,1],[1351,1],[1365,1],[1379,1],[1386,2],[1423,1],[1435,1],[1458,1],[1470,1],[1495,1],[1503,1],[1520,1],[1530,2],[1587,2],[1637,2],[1692,2],[1736,1],[1762,1],[1774,1],[1782,1],[1795,2],[1809,1],[1817,1],[1830,2],[1841,1],[1849,1],[1862,2],[1877,1],[1926,1],[1961,1],[2224,1],[2242,1],[2244,2],[2313,2],[2373,2],[2508,1],[2517,1],[2531,1],[2545,1],[2559,1],[2576,1],[2590,1],[2615,1],[2629,1],[2656,1],[2664,1],[2681,1],[2691,1],[2717,1],[2729,1],[2737,1],[2750,2],[2764,1],[2772,1],[2785,2],[2796,1],[2804,1],[2817,2],[2832,1],[2881,1],[2916,1],[3190,1],[3208,1],[3210,2],[3279,1],[3288,1],[3302,1],[3316,1],[3330,1],[3347,1],[3359,1],[3382,1],[3394,1],[3419,1],[3427,1],[3444,1],[3454,1],[3456,2],[3593,1],[3602,1],[3616,1],[3630,1],[3644,1],[3661,1],[3673,1],[3696,1],[3708,1],[3733,1],[3741,1],[3758,1],[3768,1]]},"194":{"position":[[231,1],[255,1],[273,1],[297,1],[321,1],[329,1],[355,1],[381,1],[392,1],[399,2],[410,1],[429,1]]},"195":{"position":[[177,2],[228,1],[244,1],[246,2],[294,1],[318,1],[320,2],[376,1],[395,1],[397,2],[462,2],[519,2],[608,1],[633,1],[645,1],[647,2],[697,2],[759,2],[821,1],[842,1]]},"196":{"position":[[970,1],[978,1],[984,2],[1041,2],[1100,2],[1129,2],[1132,1],[1137,1],[1139,1],[1160,1],[1188,1],[1549,1],[1557,1],[1576,1],[1599,1],[1751,1],[1759,1],[1778,1],[1801,1]]},"197":{"position":[[306,1],[341,1],[343,2],[400,1],[408,1],[435,1],[469,1],[485,1],[487,1],[489,2],[547,1],[556,1],[584,1],[618,1],[627,1],[629,1],[631,2],[691,2],[745,2],[809,2],[870,2],[968,1],[970,2],[1026,2],[1079,2],[1130,1],[1145,1],[1164,1],[1166,2],[1221,2],[1258,2],[1321,1],[1332,1],[1339,2],[1348,1],[1360,1],[1367,2],[1414,1]]},"198":{"position":[[1007,1],[1027,1],[1029,2],[1142,1],[1162,1]]},"199":{"position":[[151,1],[162,1],[167,2],[198,1],[228,1],[234,2],[246,1],[260,1],[315,1],[326,1],[331,2],[388,1],[396,1],[402,2],[408,1],[422,1],[1099,2],[1170,2],[1270,1],[1282,1],[1287,2],[1354,1],[1358,2],[1364,1],[1366,1],[1413,1],[1425,1],[1430,2],[1510,1],[1514,2],[1520,1],[1522,1],[1571,1],[1583,1],[1588,2],[1651,2],[1690,1],[1694,2],[1700,1],[1702,1]]}},"keywords":{}}],["0",{"_index":357,"title":{},"content":{"6":{"position":[[829,3]]},"8":{"position":[[110,4],[195,2]]},"9":{"position":[[664,1],[702,1],[769,1]]},"13":{"position":[[730,1]]},"14":{"position":[[1587,1]]},"15":{"position":[[956,1],[974,1]]},"20":{"position":[[1657,2],[1725,1]]},"22":{"position":[[1248,1],[1922,2]]},"24":{"position":[[1380,1],[1403,2],[1427,1],[1450,2],[1472,1],[1493,3],[1529,3]]},"25":{"position":[[1100,1],[1123,2],[1147,1],[1170,2],[1192,1],[1213,3],[1249,3]]},"30":{"position":[[5639,1]]},"34":{"position":[[1185,1]]},"43":{"position":[[757,1]]},"44":{"position":[[111,1],[499,1],[527,3],[546,3],[1118,2]]},"76":{"position":[[780,2],[1954,1],[1969,1],[2499,2],[2930,1],[3239,1]]},"85":{"position":[[273,3]]},"90":{"position":[[4847,2],[5001,1]]},"91":{"position":[[3103,3]]},"92":{"position":[[915,3]]},"103":{"position":[[678,3],[1100,3]]},"110":{"position":[[474,2]]},"128":{"position":[[734,1]]},"163":{"position":[[838,1],[846,1],[866,1],[886,1],[906,1],[976,1]]},"172":{"position":[[183,2]]},"188":{"position":[[1069,2],[1083,1],[1603,1],[1701,1],[3125,1],[3573,2],[3583,1]]},"189":{"position":[[1139,1],[1409,1],[2818,1],[3117,2],[3127,1]]},"192":{"position":[[313,2],[319,1]]},"197":{"position":[[1337,1],[1365,1]]},"199":{"position":[[164,2],[200,2],[328,2],[1284,2],[1427,2],[1585,2]]}},"keywords":{}}],["0.00044165797556096868",{"_index":734,"title":{},"content":{"18":{"position":[[338,23]]}},"keywords":{}}],["0.00093418904454400551",{"_index":732,"title":{},"content":{"18":{"position":[[276,23]]}},"keywords":{}}],["0.00098431254720448159",{"_index":733,"title":{},"content":{"18":{"position":[[307,23]]}},"keywords":{}}],["0.0010319531629488911",{"_index":731,"title":{},"content":{"18":{"position":[[246,22]]}},"keywords":{}}],["0.0016320202164526894",{"_index":730,"title":{},"content":{"18":{"position":[[216,22]]}},"keywords":{}}],["0.0053519259698605499",{"_index":759,"title":{},"content":{"19":{"position":[[561,22]]}},"keywords":{}}],["0.02",{"_index":2786,"title":{},"content":{"81":{"position":[[183,5]]}},"keywords":{}}],["0.022622210057414487",{"_index":757,"title":{},"content":{"19":{"position":[[502,21]]}},"keywords":{}}],["0.026950946344858676",{"_index":758,"title":{},"content":{"19":{"position":[[531,21]]}},"keywords":{}}],["0.027303529817677398",{"_index":756,"title":{},"content":{"19":{"position":[[473,21]]}},"keywords":{}}],["0.034774627850375328",{"_index":773,"title":{},"content":{"20":{"position":[[451,21]]}},"keywords":{}}],["0.035851524605672758",{"_index":774,"title":{},"content":{"20":{"position":[[480,21]]}},"keywords":{}}],["0.043551495607375035",{"_index":770,"title":{},"content":{"20":{"position":[[364,21]]}},"keywords":{}}],["0.043598",{"_index":1926,"title":{},"content":{"44":{"position":[[849,8]]}},"keywords":{}}],["0.044894389686214398",{"_index":771,"title":{},"content":{"20":{"position":[[393,21]]}},"keywords":{}}],["0.051424517867144637",{"_index":772,"title":{},"content":{"20":{"position":[[422,21]]}},"keywords":{}}],["0.08",{"_index":2782,"title":{},"content":{"79":{"position":[[182,5]]}},"keywords":{}}],["0.08304813163696423",{"_index":1669,"title":{},"content":{"34":{"position":[[3864,19]]}},"keywords":{}}],["0.09",{"_index":2783,"title":{},"content":{"80":{"position":[[204,5]]}},"keywords":{}}],["0.10578734457846127",{"_index":755,"title":{},"content":{"19":{"position":[[445,20]]}},"keywords":{}}],["0.180602",{"_index":1924,"title":{},"content":{"44":{"position":[[836,8]]}},"keywords":{}}],["0.2.17",{"_index":4152,"title":{},"content":{"125":{"position":[[7904,6]]}},"keywords":{}}],["0.2.21",{"_index":4151,"title":{},"content":{"125":{"position":[[7884,6]]}},"keywords":{}}],["0.30",{"_index":2779,"title":{},"content":{"78":{"position":[[978,5]]}},"keywords":{}}],["0.4.4",{"_index":3956,"title":{},"content":{"122":{"position":[[1219,5]]}},"keywords":{}}],["0.451493",{"_index":1155,"title":{},"content":{"25":{"position":[[2493,8]]}},"keywords":{}}],["0.455224",{"_index":1108,"title":{},"content":{"24":{"position":[[2770,8]]},"25":{"position":[[2484,8]]}},"keywords":{}}],["0.462687",{"_index":1107,"title":{},"content":{"24":{"position":[[2761,8]]}},"keywords":{}}],["0.464945",{"_index":1109,"title":{},"content":{"24":{"position":[[2779,8]]}},"keywords":{}}],["0.476015",{"_index":1110,"title":{},"content":{"24":{"position":[[2788,8]]}},"keywords":{}}],["0.483395",{"_index":1156,"title":{},"content":{"25":{"position":[[2502,8]]}},"keywords":{}}],["0.501845",{"_index":1151,"title":{},"content":{"25":{"position":[[2421,8]]}},"keywords":{}}],["0.512915",{"_index":1157,"title":{},"content":{"25":{"position":[[2511,8]]}},"keywords":{}}],["0.522388",{"_index":1100,"title":{},"content":{"24":{"position":[[2689,8]]}},"keywords":{}}],["0.529851",{"_index":1150,"title":{},"content":{"25":{"position":[[2412,8]]}},"keywords":{}}],["0.531365",{"_index":1160,"title":{},"content":{"25":{"position":[[2545,8]]}},"keywords":{}}],["0.533582",{"_index":1149,"title":{},"content":{"25":{"position":[[2403,8]]}},"keywords":{}}],["0.535055",{"_index":1154,"title":{},"content":{"25":{"position":[[2461,8],[2470,8],[2589,8],[2598,8]]}},"keywords":{}}],["0.538745",{"_index":1161,"title":{},"content":{"25":{"position":[[2554,8]]}},"keywords":{}}],["0.542435",{"_index":1152,"title":{},"content":{"25":{"position":[[2430,8]]}},"keywords":{}}],["0.544776",{"_index":1099,"title":{},"content":{"24":{"position":[[2680,8]]}},"keywords":{}}],["0.582090",{"_index":1158,"title":{},"content":{"25":{"position":[[2527,8]]}},"keywords":{}}],["0.585821",{"_index":1162,"title":{},"content":{"25":{"position":[[2571,8]]}},"keywords":{}}],["0.589552",{"_index":1153,"title":{},"content":{"25":{"position":[[2443,8]]}},"keywords":{}}],["0.590406",{"_index":1102,"title":{},"content":{"24":{"position":[[2707,8]]}},"keywords":{}}],["0.597015",{"_index":1115,"title":{},"content":{"24":{"position":[[2857,8]]}},"keywords":{}}],["0.601476",{"_index":1101,"title":{},"content":{"24":{"position":[[2698,8]]}},"keywords":{}}],["0.604478",{"_index":1104,"title":{},"content":{"24":{"position":[[2729,8],[2848,8]]}},"keywords":{}}],["0.608209",{"_index":1112,"title":{},"content":{"24":{"position":[[2813,8]]},"25":{"position":[[2452,8],[2580,8]]}},"keywords":{}}],["0.611940",{"_index":1103,"title":{},"content":{"24":{"position":[[2720,8]]}},"keywords":{}}],["0.615672",{"_index":1111,"title":{},"content":{"24":{"position":[[2804,8]]}},"keywords":{}}],["0.626866",{"_index":1159,"title":{},"content":{"25":{"position":[[2536,8]]}},"keywords":{}}],["0.6894803101560001",{"_index":1663,"title":{},"content":{"34":{"position":[[3472,18]]}},"keywords":{}}],["0.797048",{"_index":1113,"title":{},"content":{"24":{"position":[[2822,8]]}},"keywords":{}}],["0.804428",{"_index":1105,"title":{},"content":{"24":{"position":[[2738,8]]}},"keywords":{}}],["0.811808",{"_index":1116,"title":{},"content":{"24":{"position":[[2866,8]]}},"keywords":{}}],["0.830258",{"_index":1114,"title":{},"content":{"24":{"position":[[2831,8]]}},"keywords":{}}],["0.841328",{"_index":1106,"title":{},"content":{"24":{"position":[[2747,8]]}},"keywords":{}}],["0.848708",{"_index":1117,"title":{},"content":{"24":{"position":[[2875,8]]}},"keywords":{}}],["0.870236869207003",{"_index":2122,"title":{},"content":{"51":{"position":[[2116,17]]}},"keywords":{}}],["0.905159",{"_index":1922,"title":{},"content":{"44":{"position":[[823,8]]}},"keywords":{}}],["0.937329",{"_index":1927,"title":{},"content":{"44":{"position":[[862,8]]}},"keywords":{}}],["0.959372",{"_index":1928,"title":{},"content":{"44":{"position":[[875,8]]}},"keywords":{}}],["0.960837",{"_index":1930,"title":{},"content":{"44":{"position":[[888,8],[901,8]]}},"keywords":{}}],["0.9608561656706882",{"_index":1948,"title":{},"content":{"44":{"position":[[1646,18]]}},"keywords":{}}],["005",{"_index":3052,"title":{},"content":{"90":{"position":[[4403,6]]}},"keywords":{}}],["00:00:00",{"_index":2441,"title":{},"content":{"62":{"position":[[1634,8]]}},"keywords":{}}],["01",{"_index":2440,"title":{},"content":{"62":{"position":[[1628,2],[1631,2]]},"76":{"position":[[1256,3]]},"90":{"position":[[4311,5]]}},"keywords":{}}],["02",{"_index":3053,"title":{},"content":{"90":{"position":[[4416,5]]}},"keywords":{}}],["025",{"_index":3048,"title":{},"content":{"90":{"position":[[4324,6]]}},"keywords":{}}],["02f}s".format(end",{"_index":2759,"title":{},"content":{"78":{"position":[[382,25]]}},"keywords":{}}],["03",{"_index":2442,"title":{},"content":{"62":{"position":[[1651,2]]}},"keywords":{}}],["05",{"_index":807,"title":{},"content":{"20":{"position":[[1093,3]]},"90":{"position":[[4466,5],[4583,5],[4689,6]]}},"keywords":{}}],["055",{"_index":3059,"title":{},"content":{"90":{"position":[[4519,6]]}},"keywords":{}}],["05:13:42",{"_index":1501,"title":{},"content":{"30":{"position":[[10185,8]]}},"keywords":{}}],["05:30:51",{"_index":1503,"title":{},"content":{"30":{"position":[[10239,8]]}},"keywords":{}}],["05:48:30",{"_index":1504,"title":{},"content":{"30":{"position":[[10289,8]]}},"keywords":{}}],["06",{"_index":645,"title":{},"content":{"14":{"position":[[1427,3]]}},"keywords":{}}],["06:08:32",{"_index":1505,"title":{},"content":{"30":{"position":[[10340,8]]}},"keywords":{}}],["06:25:21",{"_index":1506,"title":{},"content":{"30":{"position":[[10378,8]]}},"keywords":{}}],["07",{"_index":562,"title":{},"content":{"13":{"position":[[597,3]]},"15":{"position":[[796,3]]},"90":{"position":[[4628,5]]}},"keywords":{}}],["085",{"_index":3060,"title":{},"content":{"90":{"position":[[4532,6]]}},"keywords":{}}],["0:.2f}%".format(expected_drawdown",{"_index":859,"title":{},"content":{"20":{"position":[[2692,41]]}},"keywords":{}}],["0:00:58.715714",{"_index":2038,"title":{},"content":{"46":{"position":[[682,14]]}},"keywords":{}}],["0:20:29",{"_index":3170,"title":{},"content":{"91":{"position":[[5292,7],[5306,7]]}},"keywords":{}}],["0:20:51",{"_index":3185,"title":{},"content":{"92":{"position":[[1813,7],[1827,7]]}},"keywords":{}}],["0:21:38",{"_index":3161,"title":{},"content":{"91":{"position":[[4482,7],[4496,7]]}},"keywords":{}}],["0:22:51",{"_index":3180,"title":{},"content":{"92":{"position":[[1255,7],[1269,7]]}},"keywords":{}}],["0:26:26",{"_index":3174,"title":{},"content":{"91":{"position":[[5675,7],[5689,7]]}},"keywords":{}}],["0:26:56",{"_index":3186,"title":{},"content":{"92":{"position":[[1972,7],[1986,7]]}},"keywords":{}}],["0:horizon*2+1",{"_index":3038,"title":{},"content":{"90":{"position":[[3903,16]]}},"keywords":{}}],["0x00",{"_index":4778,"title":{},"content":{"163":{"position":[[1718,5],[1724,5],[1730,6]]}},"keywords":{}}],["0x00000006",{"_index":4770,"title":{},"content":{"163":{"position":[[993,10]]}},"keywords":{}}],["0x00007f499effd700",{"_index":5208,"title":{},"content":{"188":{"position":[[3704,18]]}},"keywords":{}}],["0x06",{"_index":4777,"title":{},"content":{"163":{"position":[[1711,6]]}},"keywords":{}}],["0x18e59dc28d0>",{"_index":2115,"title":{},"content":{"51":{"position":[[1830,17]]}},"keywords":{}}],["0xab555145c708dad2",{"_index":3696,"title":{},"content":{"110":{"position":[[436,20]]}},"keywords":{}}],["1",{"_index":358,"title":{"44":{"position":[[29,1]]},"46":{"position":[[16,2]]},"70":{"position":[[10,2]]},"78":{"position":[[8,2]]},"91":{"position":[[11,2]]},"96":{"position":[[6,2]]},"108":{"position":[[5,2]]},"115":{"position":[[8,2]]},"140":{"position":[[8,2]]}},"content":{"6":{"position":[[868,1]]},"7":{"position":[[423,2]]},"9":{"position":[[452,2],[499,2],[745,1]]},"11":{"position":[[196,1],[434,1],[494,2]]},"12":{"position":[[392,1],[453,2]]},"13":{"position":[[1940,2]]},"14":{"position":[[708,2],[852,2],[1845,2],[1904,2],[3012,2]]},"15":{"position":[[353,2],[468,1],[1436,2],[1572,2],[2683,2]]},"20":{"position":[[216,1],[646,3],[1073,2],[1282,1],[1569,3],[1818,1],[1918,1]]},"22":{"position":[[1682,3],[1990,2],[2267,1]]},"24":{"position":[[1508,3]]},"25":{"position":[[1228,3]]},"28":{"position":[[1296,2],[1331,2],[1334,2],[3096,2],[3131,2],[3134,2]]},"30":{"position":[[1662,2],[1697,2],[1700,2],[3011,2],[3046,2],[3049,2],[4935,2],[4970,2],[4973,2],[5643,2],[6079,2],[6114,2],[6117,2],[9344,2]]},"32":{"position":[[1590,2],[1800,2],[1880,2]]},"33":{"position":[[919,3],[1213,2]]},"34":{"position":[[1258,1],[1872,1],[2348,1],[3148,2]]},"38":{"position":[[563,2],[934,1]]},"39":{"position":[[893,1],[1087,1],[1131,3],[1568,1],[1612,3],[1959,3],[2032,2],[3156,2],[3159,2],[3217,2],[3220,3]]},"40":{"position":[[2278,1],[3563,1]]},"43":{"position":[[583,2],[631,3],[728,1]]},"44":{"position":[[116,1],[501,2],[531,3]]},"45":{"position":[[1609,1],[2009,2]]},"52":{"position":[[1136,2]]},"61":{"position":[[1706,1]]},"62":{"position":[[142,2],[598,2],[601,2],[1395,3],[1572,3]]},"65":{"position":[[627,1],[695,2],[2340,2],[2343,2]]},"70":{"position":[[307,1],[481,1],[1025,1]]},"71":{"position":[[407,1],[581,1],[1400,1]]},"76":{"position":[[2462,1],[3266,1]]},"79":{"position":[[55,1]]},"80":{"position":[[48,1]]},"85":{"position":[[277,3],[290,4]]},"88":{"position":[[1458,3],[1480,3],[1787,3],[2849,3]]},"90":{"position":[[920,2],[979,2],[982,3],[1048,1],[1627,1],[1776,1],[2057,2],[2102,2],[2305,2],[2364,2],[2367,3],[2433,1],[2920,1],[3159,2],[4399,3],[4492,1],[4636,2],[4640,4]]},"91":{"position":[[3067,1],[3400,3],[4021,3]]},"92":{"position":[[879,1]]},"93":{"position":[[2180,2]]},"97":{"position":[[1774,2]]},"98":{"position":[[457,1]]},"105":{"position":[[1173,3],[1177,3],[1181,3],[1189,3],[1970,2],[2004,3],[2041,3],[2936,2]]},"109":{"position":[[425,1]]},"110":{"position":[[487,2]]},"111":{"position":[[404,1]]},"127":{"position":[[813,1]]},"129":{"position":[[2503,1]]},"163":{"position":[[840,1],[848,1],[868,1],[888,1],[908,1]]},"188":{"position":[[1034,2],[1076,2],[3623,2]]},"189":{"position":[[1123,2],[1145,1],[1393,2],[1415,1],[3154,2]]},"192":{"position":[[395,2]]},"193":{"position":[[1787,2],[2742,2]]}},"keywords":{}}],["1%the",{"_index":1588,"title":{},"content":{"33":{"position":[[1162,5]]}},"keywords":{}}],["1'",{"_index":1802,"title":{},"content":{"40":{"position":[[644,3]]}},"keywords":{}}],["1)*(t",{"_index":572,"title":{},"content":{"13":{"position":[[879,5]]},"14":{"position":[[1748,5],[2904,7]]},"15":{"position":[[1138,5],[2578,7]]}},"keywords":{}}],["1)*t",{"_index":600,"title":{},"content":{"13":{"position":[[1822,6]]}},"keywords":{}}],["1)\\cdot",{"_index":466,"title":{},"content":{"9":{"position":[[439,7]]}},"keywords":{}}],["1.0",{"_index":4483,"title":{},"content":{"148":{"position":[[325,3]]}},"keywords":{}}],["1.0.2",{"_index":4403,"title":{},"content":{"136":{"position":[[984,6]]}},"keywords":{}}],["1.0.3",{"_index":4405,"title":{},"content":{"136":{"position":[[1031,6]]}},"keywords":{}}],["1.0049",{"_index":506,"title":{},"content":{"10":{"position":[[592,7],[620,6]]}},"keywords":{}}],["1.01",{"_index":1660,"title":{},"content":{"34":{"position":[[3369,5]]},"39":{"position":[[3229,5]]}},"keywords":{}}],["1.02",{"_index":1667,"title":{},"content":{"34":{"position":[[3760,5]]},"39":{"position":[[2568,5]]}},"keywords":{}}],["1.21",{"_index":325,"title":{},"content":{"6":{"position":[[355,5],[842,5]]}},"keywords":{}}],["1.28",{"_index":4351,"title":{},"content":{"132":{"position":[[531,4]]}},"keywords":{}}],["1.31",{"_index":4482,"title":{},"content":{"148":{"position":[[262,4]]}},"keywords":{}}],["1.32",{"_index":4707,"title":{},"content":{"160":{"position":[[3761,5]]}},"keywords":{}}],["1.45",{"_index":326,"title":{},"content":{"6":{"position":[[361,5],[848,5]]}},"keywords":{}}],["1.69",{"_index":327,"title":{},"content":{"6":{"position":[[367,5],[854,5]]}},"keywords":{}}],["1.72",{"_index":2498,"title":{},"content":{"64":{"position":[[2070,4]]}},"keywords":{}}],["1.854949900247809",{"_index":1668,"title":{},"content":{"34":{"position":[[3820,17]]}},"keywords":{}}],["1.85x",{"_index":1670,"title":{},"content":{"34":{"position":[[3923,5]]}},"keywords":{}}],["1.94",{"_index":2807,"title":{},"content":{"82":{"position":[[982,5]]}},"keywords":{}}],["1/12",{"_index":2584,"title":{},"content":{"70":{"position":[[358,6],[378,6],[398,6],[418,4],[494,6],[514,6],[534,6],[554,6],[1043,5],[1049,5],[1055,5],[1061,5],[1072,6],[1079,5],[1085,5],[1091,5]]},"71":{"position":[[439,6],[459,6],[479,6],[499,6],[613,6],[633,6],[653,6],[673,6],[1221,5],[1227,5],[1233,5],[1239,5]]},"79":{"position":[[87,5],[93,5],[99,5],[105,5],[123,5],[129,5],[135,5],[141,5]]},"80":{"position":[[109,5],[115,5],[121,5],[127,5],[139,6],[146,5],[162,5],[168,6]]}},"keywords":{}}],["1/3",{"_index":2583,"title":{},"content":{"70":{"position":[[320,5],[339,5],[574,5],[593,3],[1032,5],[1038,4],[1097,4],[1102,4]]},"71":{"position":[[420,5],[519,3],[594,5],[693,3],[1215,5],[1245,4]]},"79":{"position":[[111,5],[117,5],[147,5]]},"80":{"position":[[133,5],[152,4],[157,4]]}},"keywords":{}}],["1/9",{"_index":2776,"title":{},"content":{"78":{"position":[[830,4],[835,4],[840,5],[862,4],[867,4],[872,5]]},"82":{"position":[[188,4],[193,4],[214,5],[220,4],[225,4]]}},"keywords":{}}],["1/`change`)^12",{"_index":2700,"title":{},"content":{"76":{"position":[[1185,15]]}},"keywords":{}}],["10",{"_index":1264,"title":{},"content":{"28":{"position":[[1948,4]]},"34":{"position":[[3186,2],[3375,3],[3766,3]]},"39":{"position":[[2574,3],[3235,3]]},"76":{"position":[[2492,3]]},"78":{"position":[[794,3]]},"91":{"position":[[968,6]]},"93":{"position":[[5085,2]]},"103":{"position":[[583,2],[624,2]]},"121":{"position":[[2318,2]]},"167":{"position":[[203,2]]}},"keywords":{}}],["10):datetime(2016",{"_index":3092,"title":{},"content":{"91":{"position":[[1026,18]]}},"keywords":{}}],["10,000",{"_index":2787,"title":{},"content":{"82":{"position":[[57,6]]}},"keywords":{}}],["10.0",{"_index":3225,"title":{},"content":{"93":{"position":[[2382,5]]}},"keywords":{}}],["10.5",{"_index":3465,"title":{},"content":{"101":{"position":[[72,4]]}},"keywords":{}}],["10.65",{"_index":4869,"title":{},"content":{"168":{"position":[[281,6]]}},"keywords":{}}],["100",{"_index":353,"title":{},"content":{"6":{"position":[[787,3],[802,3],[818,3],[862,3]]},"15":{"position":[[306,4]]},"20":{"position":[[2429,3],[2506,3],[2651,3]]},"22":{"position":[[1688,3]]},"23":{"position":[[158,4]]},"34":{"position":[[3088,3],[3364,4],[3755,4]]},"39":{"position":[[2563,4],[3224,4]]},"50":{"position":[[218,3]]},"91":{"position":[[4384,4],[5194,4],[5577,4]]},"92":{"position":[[1157,4],[1715,4],[1874,4]]},"121":{"position":[[2214,3]]}},"keywords":{}}],["100%coupon",{"_index":639,"title":{},"content":{"14":{"position":[[1259,10]]}},"keywords":{}}],["100.00",{"_index":621,"title":{},"content":{"13":{"position":[[2293,7]]}},"keywords":{}}],["100.09",{"_index":695,"title":{},"content":{"15":{"position":[[3031,7]]}},"keywords":{}}],["100.6",{"_index":362,"title":{},"content":{"6":{"position":[[907,5]]}},"keywords":{}}],["1000",{"_index":2777,"title":{},"content":{"78":{"position":[[892,5]]},"82":{"position":[[267,5]]},"181":{"position":[[92,5],[179,5],[306,5],[437,4]]},"183":{"position":[[317,5],[709,5]]}},"keywords":{}}],["1000*p",{"_index":1723,"title":{},"content":{"39":{"position":[[583,6]]}},"keywords":{}}],["10000",{"_index":2562,"title":{},"content":{"68":{"position":[[525,6],[565,6]]},"70":{"position":[[1127,6],[1154,6]]},"71":{"position":[[1278,6],[1305,6]]},"82":{"position":[[897,6]]}},"keywords":{}}],["100000",{"_index":371,"title":{},"content":{"6":{"position":[[1038,6]]}},"keywords":{}}],["1007n",{"_index":4889,"title":{},"content":{"169":{"position":[[425,6]]}},"keywords":{}}],["102.2",{"_index":320,"title":{},"content":{"6":{"position":[[298,6],[771,5]]}},"keywords":{}}],["1024",{"_index":3496,"title":{},"content":{"102":{"position":[[1009,4],[1238,4]]},"103":{"position":[[1174,4],[1778,5],[1784,5],[2101,5]]},"105":{"position":[[1245,6],[1258,6],[1271,6],[1317,6],[2238,5],[2279,5],[2321,5],[2481,6]]}},"keywords":{}}],["103.2805",{"_index":606,"title":{},"content":{"13":{"position":[[1943,10]]}},"keywords":{}}],["103.3260",{"_index":616,"title":{},"content":{"13":{"position":[[2167,10]]}},"keywords":{}}],["103.37421610015554",{"_index":618,"title":{},"content":{"13":{"position":[[2226,18]]}},"keywords":{}}],["103.3796",{"_index":609,"title":{},"content":{"13":{"position":[[1999,10]]}},"keywords":{}}],["103.4099",{"_index":614,"title":{},"content":{"13":{"position":[[2111,10]]}},"keywords":{}}],["103.4752",{"_index":611,"title":{},"content":{"13":{"position":[[2055,10]]}},"keywords":{}}],["105.9959",{"_index":656,"title":{},"content":{"14":{"position":[[3127,10]]}},"keywords":{}}],["106.0071",{"_index":654,"title":{},"content":{"14":{"position":[[3071,10]]}},"keywords":{}}],["106.0168",{"_index":660,"title":{},"content":{"14":{"position":[[3239,10]]}},"keywords":{}}],["106.02850857209883",{"_index":662,"title":{},"content":{"14":{"position":[[3298,18]]}},"keywords":{}}],["106.0562",{"_index":652,"title":{},"content":{"14":{"position":[[3015,10]]}},"keywords":{}}],["106.0665",{"_index":658,"title":{},"content":{"14":{"position":[[3183,10]]}},"keywords":{}}],["108.8087",{"_index":692,"title":{},"content":{"15":{"position":[[2910,10]]}},"keywords":{}}],["108.8612",{"_index":684,"title":{},"content":{"15":{"position":[[2686,10]]}},"keywords":{}}],["108.91052564051816",{"_index":694,"title":{},"content":{"15":{"position":[[2969,18]]}},"keywords":{}}],["108.9175",{"_index":688,"title":{},"content":{"15":{"position":[[2798,10]]}},"keywords":{}}],["108.9426",{"_index":690,"title":{},"content":{"15":{"position":[[2854,10]]}},"keywords":{}}],["109.0226",{"_index":686,"title":{},"content":{"15":{"position":[[2742,10]]}},"keywords":{}}],["10th",{"_index":3487,"title":{},"content":{"101":{"position":[[1046,4]]}},"keywords":{}}],["11",{"_index":1266,"title":{},"content":{"28":{"position":[[1966,3]]},"30":{"position":[[9371,3]]},"34":{"position":[[3355,3],[3746,3]]},"74":{"position":[[389,2],[667,4]]},"90":{"position":[[3368,2]]}},"keywords":{}}],["111",{"_index":1907,"title":{},"content":{"44":{"position":[[312,3],[331,3]]},"45":{"position":[[355,4]]}},"keywords":{}}],["111.000000",{"_index":1921,"title":{},"content":{"44":{"position":[[807,10]]}},"keywords":{}}],["116n",{"_index":4891,"title":{},"content":{"169":{"position":[[442,5]]}},"keywords":{}}],["12",{"_index":422,"title":{},"content":{"7":{"position":[[892,2]]},"28":{"position":[[1299,4],[1337,4],[3099,4],[3137,4]]},"30":{"position":[[1390,3],[1665,4],[1703,4],[3014,4],[3052,4],[4938,4],[4976,4],[6082,4],[6120,4],[9109,2],[9347,4],[9379,4]]},"68":{"position":[[789,2]]},"71":{"position":[[1485,2]]},"74":{"position":[[421,3],[689,2]]},"85":{"position":[[345,2],[422,2]]},"88":{"position":[[1552,5],[1879,5],[2999,5],[3388,5]]},"91":{"position":[[764,5],[1230,5]]},"113":{"position":[[2363,4]]},"115":{"position":[[768,4]]},"116":{"position":[[788,4]]},"117":{"position":[[1810,4]]},"163":{"position":[[1248,2]]}},"keywords":{}}],["12.32",{"_index":4886,"title":{},"content":{"169":{"position":[[394,6]]}},"keywords":{}}],["12.366942",{"_index":3643,"title":{},"content":{"105":{"position":[[2429,9]]}},"keywords":{}}],["1216n",{"_index":4880,"title":{},"content":{"169":{"position":[[333,6]]}},"keywords":{}}],["122.332071",{"_index":1458,"title":{},"content":{"30":{"position":[[8560,11]]}},"keywords":{}}],["124.5",{"_index":866,"title":{},"content":{"20":{"position":[[2895,7]]}},"keywords":{}}],["128",{"_index":3599,"title":{},"content":{"105":{"position":[[1239,5],[1278,5],[2232,5],[2357,5]]}},"keywords":{}}],["128934900",{"_index":2505,"title":{},"content":{"65":{"position":[[718,9]]}},"keywords":{}}],["13",{"_index":2513,"title":{},"content":{"65":{"position":[[1130,2],[1208,2]]},"78":{"position":[[444,3]]}},"keywords":{}}],["138.108597",{"_index":3619,"title":{},"content":{"105":{"position":[[1983,10]]}},"keywords":{}}],["14",{"_index":3516,"title":{},"content":{"103":{"position":[[578,2]]},"113":{"position":[[2401,4]]},"115":{"position":[[806,4]]},"116":{"position":[[826,4]]},"117":{"position":[[1846,4]]},"179":{"position":[[700,2]]}},"keywords":{}}],["14.31",{"_index":4873,"title":{},"content":{"168":{"position":[[320,6]]}},"keywords":{}}],["14.80",{"_index":4865,"title":{},"content":{"168":{"position":[[233,6]]}},"keywords":{}}],["14.86",{"_index":363,"title":{},"content":{"6":{"position":[[919,5]]}},"keywords":{}}],["140",{"_index":2139,"title":{},"content":{"51":{"position":[[3004,3]]},"52":{"position":[[747,3]]}},"keywords":{}}],["15",{"_index":2922,"title":{},"content":{"88":{"position":[[2871,4]]},"121":{"position":[[2321,2]]}},"keywords":{}}],["15.37",{"_index":356,"title":{},"content":{"6":{"position":[[810,5]]}},"keywords":{}}],["15.62",{"_index":340,"title":{},"content":{"6":{"position":[[558,6]]}},"keywords":{}}],["150",{"_index":3918,"title":{},"content":{"121":{"position":[[2202,3]]}},"keywords":{}}],["1500",{"_index":3273,"title":{},"content":{"93":{"position":[[4545,4]]}},"keywords":{}}],["1535n",{"_index":4875,"title":{},"content":{"168":{"position":[[336,6]]}},"keywords":{}}],["1583n",{"_index":4885,"title":{},"content":{"169":{"position":[[387,6]]}},"keywords":{}}],["16",{"_index":2504,"title":{},"content":{"65":{"position":[[667,2],[689,3]]},"105":{"position":[[573,2],[1206,4],[2115,4],[2735,3]]},"128":{"position":[[478,2]]},"163":{"position":[[1338,2]]},"192":{"position":[[240,2],[353,2]]}},"keywords":{}}],["16.431797",{"_index":3620,"title":{},"content":{"105":{"position":[[1994,9]]}},"keywords":{}}],["16.715032",{"_index":3625,"title":{},"content":{"105":{"position":[[2068,9]]}},"keywords":{}}],["1640",{"_index":4579,"title":{},"content":{"155":{"position":[[1382,4]]}},"keywords":{}}],["1650",{"_index":4582,"title":{},"content":{"155":{"position":[[1444,4]]}},"keywords":{}}],["1660",{"_index":4585,"title":{},"content":{"155":{"position":[[1506,4]]}},"keywords":{}}],["1672",{"_index":4588,"title":{},"content":{"155":{"position":[[1569,4]]}},"keywords":{}}],["16mmm",{"_index":2502,"title":{},"content":{"65":{"position":[[598,6]]}},"keywords":{}}],["17",{"_index":2146,"title":{},"content":{"51":{"position":[[3310,3]]}},"keywords":{}}],["17.097543",{"_index":3635,"title":{},"content":{"105":{"position":[[2222,9]]}},"keywords":{}}],["17.263611",{"_index":3627,"title":{},"content":{"105":{"position":[[2096,9]]}},"keywords":{}}],["17.263672",{"_index":3632,"title":{},"content":{"105":{"position":[[2173,9],[2254,9]]}},"keywords":{}}],["17.265625",{"_index":3642,"title":{},"content":{"105":{"position":[[2419,9]]}},"keywords":{}}],["1724195340",{"_index":2495,"title":{},"content":{"64":{"position":[[1933,10]]}},"keywords":{}}],["173n",{"_index":4887,"title":{},"content":{"169":{"position":[[413,5]]}},"keywords":{}}],["1751n",{"_index":4863,"title":{},"content":{"168":{"position":[[219,6]]}},"keywords":{}}],["18",{"_index":2923,"title":{},"content":{"88":{"position":[[2919,4]]},"91":{"position":[[518,6]]},"97":{"position":[[5055,2]]}},"keywords":{}}],["18):datetime(2016",{"_index":3080,"title":{},"content":{"91":{"position":[[570,18]]}},"keywords":{}}],["18.870387",{"_index":3637,"title":{},"content":{"105":{"position":[[2305,9]]}},"keywords":{}}],["18.92",{"_index":4882,"title":{},"content":{"169":{"position":[[347,6]]}},"keywords":{}}],["1828n",{"_index":4867,"title":{},"content":{"168":{"position":[[267,6]]}},"keywords":{}}],["18:20",{"_index":4962,"title":{},"content":{"173":{"position":[[1301,7]]}},"keywords":{}}],["1992",{"_index":2452,"title":{},"content":{"64":{"position":[[240,5],[408,4],[1103,4],[1363,5]]}},"keywords":{}}],["1:m",{"_index":433,"title":{},"content":{"7":{"position":[[1168,3]]}},"keywords":{}}],["1].count",{"_index":1937,"title":{},"content":{"44":{"position":[[1345,10]]}},"keywords":{}}],["1]['close",{"_index":1034,"title":{},"content":{"24":{"position":[[644,11]]}},"keywords":{}}],["1st",{"_index":2445,"title":{},"content":{"62":{"position":[[1747,3]]},"64":{"position":[[235,4],[2044,3]]},"65":{"position":[[2173,3]]}},"keywords":{}}],["1}(d_i",{"_index":1546,"title":{},"content":{"32":{"position":[[1717,6]]}},"keywords":{}}],["1}d_i",{"_index":1544,"title":{},"content":{"32":{"position":[[1654,5]]}},"keywords":{}}],["1ω=1sω≥sd⋅∣ω∣≤d∣ω∣≤l",{"_index":791,"title":{},"content":{"20":{"position":[[773,25]]}},"keywords":{}}],["1⃗ω=1s⃗ω≥sd⃗⋅∣ω∣≤d∣ω∣≤l\\begin{align",{"_index":777,"title":{},"content":{"20":{"position":[[545,37]]}},"keywords":{}}],["1−p1",{"_index":1973,"title":{},"content":{"45":{"position":[[765,4]]}},"keywords":{}}],["2",{"_index":608,"title":{"45":{"position":[[29,1]]},"61":{"position":[[15,2]]},"71":{"position":[[10,2]]},"79":{"position":[[8,2]]},"92":{"position":[[11,2]]},"97":{"position":[[6,2]]},"109":{"position":[[5,2]]},"116":{"position":[[8,2]]},"141":{"position":[[8,2]]}},"content":{"13":{"position":[[1996,2]]},"14":{"position":[[963,2],[3068,2]]},"15":{"position":[[414,2],[474,1],[2739,2]]},"22":{"position":[[2062,2]]},"34":{"position":[[3668,2]]},"44":{"position":[[275,2]]},"52":{"position":[[1124,2]]},"61":{"position":[[41,1]]},"64":{"position":[[876,2]]},"65":{"position":[[1721,2],[2471,2]]},"68":{"position":[[795,2]]},"70":{"position":[[326,1],[501,1]]},"71":{"position":[[426,1],[600,1],[1479,1]]},"74":{"position":[[411,1],[612,3]]},"76":{"position":[[1307,2],[1357,2]]},"88":{"position":[[2706,2]]},"90":{"position":[[772,1],[925,2],[1337,2],[2157,1],[2310,2]]},"91":{"position":[[435,2]]},"97":{"position":[[1781,2]]},"105":{"position":[[1185,3],[2008,2]]},"109":{"position":[[468,1]]},"111":{"position":[[447,1]]},"136":{"position":[[959,1]]},"163":{"position":[[842,1],[850,1],[870,1],[890,1]]},"192":{"position":[[401,1]]},"193":{"position":[[1793,1],[2748,1]]}},"keywords":{}}],["2**20",{"_index":3589,"title":{},"content":{"105":{"position":[[887,7],[1140,7],[1599,7]]}},"keywords":{}}],["2.21",{"_index":2328,"title":{},"content":{"58":{"position":[[236,4]]}},"keywords":{}}],["2.5",{"_index":2305,"title":{"57":{"position":[[0,3]]}},"content":{"57":{"position":[[669,3]]},"58":{"position":[[155,3],[381,3]]},"64":{"position":[[48,3]]},"70":{"position":[[638,3]]},"90":{"position":[[4526,5]]}},"keywords":{}}],["2.7",{"_index":364,"title":{},"content":{"6":{"position":[[931,3]]}},"keywords":{}}],["2.84",{"_index":355,"title":{},"content":{"6":{"position":[[795,4]]}},"keywords":{}}],["2.84%rrr",{"_index":322,"title":{},"content":{"6":{"position":[[334,8]]}},"keywords":{}}],["2/2)*t",{"_index":399,"title":{},"content":{"7":{"position":[[466,9]]}},"keywords":{}}],["2/9",{"_index":2775,"title":{},"content":{"78":{"position":[[820,4],[825,4],[846,5],[852,4],[857,4]]},"82":{"position":[[198,4],[203,4],[208,5],[230,4],[235,4],[240,5]]}},"keywords":{}}],["20",{"_index":908,"title":{},"content":{"22":{"position":[[760,4]]},"45":{"position":[[1613,2],[1685,2]]},"53":{"position":[[145,4]]},"105":{"position":[[2591,2]]},"163":{"position":[[1427,2]]},"189":{"position":[[1883,4]]}},"keywords":{}}],["200",{"_index":452,"title":{},"content":{"8":{"position":[[206,4]]}},"keywords":{}}],["2000",{"_index":996,"title":{},"content":{"23":{"position":[[141,5]]},"24":{"position":[[3067,4],[3378,5]]},"82":{"position":[[337,5]]}},"keywords":{}}],["2012",{"_index":1374,"title":{},"content":{"30":{"position":[[2533,4]]}},"keywords":{}}],["2013",{"_index":1282,"title":{},"content":{"28":{"position":[[2424,4],[4037,4]]}},"keywords":{}}],["2015",{"_index":1364,"title":{},"content":{"30":{"position":[[2115,6],[3601,6],[3808,6],[4219,4],[4375,4],[5374,6],[6674,6],[6887,6],[7165,5]]},"40":{"position":[[1090,4],[1250,5]]}},"keywords":{}}],["2016",{"_index":1256,"title":{},"content":{"28":{"position":[[1780,5]]},"30":{"position":[[1366,5]]},"62":{"position":[[145,4],[168,5],[1623,4],[1646,4]]},"64":{"position":[[425,4],[1120,4],[2048,5]]},"65":{"position":[[759,4],[1251,4]]}},"keywords":{}}],["2048",{"_index":3601,"title":{},"content":{"105":{"position":[[1284,6],[1297,6],[1310,6],[1324,5],[2363,5],[2403,5],[2445,5],[2488,5]]}},"keywords":{}}],["2068",{"_index":2515,"title":{},"content":{"65":{"position":[[1271,5],[1403,4],[1932,5],[2074,5]]}},"keywords":{}}],["2070",{"_index":2528,"title":{},"content":{"65":{"position":[[2177,5],[2536,4]]}},"keywords":{}}],["2083",{"_index":1946,"title":{},"content":{"44":{"position":[[1619,4]]}},"keywords":{}}],["21",{"_index":2003,"title":{},"content":{"45":{"position":[[2196,3],[2976,3]]},"193":{"position":[[3518,2]]}},"keywords":{}}],["2185n",{"_index":4871,"title":{},"content":{"168":{"position":[[306,6]]}},"keywords":{}}],["22",{"_index":5100,"title":{},"content":{"181":{"position":[[282,2]]},"193":{"position":[[3525,2]]}},"keywords":{}}],["22147.004400281654",{"_index":2778,"title":{},"content":{"78":{"position":[[933,18]]}},"keywords":{}}],["229",{"_index":5302,"title":{},"content":{"193":{"position":[[2351,3]]}},"keywords":{}}],["23",{"_index":2534,"title":{},"content":{"65":{"position":[[2474,3]]}},"keywords":{}}],["23:59:00",{"_index":2443,"title":{},"content":{"62":{"position":[[1657,9]]}},"keywords":{}}],["23rd",{"_index":2538,"title":{},"content":{"65":{"position":[[2530,5]]}},"keywords":{}}],["24",{"_index":4282,"title":{},"content":{"129":{"position":[[536,2],[728,2],[1936,2]]},"152":{"position":[[664,2]]},"163":{"position":[[1513,2]]},"184":{"position":[[307,3],[596,2]]},"196":{"position":[[980,3]]}},"keywords":{}}],["24.736506",{"_index":3645,"title":{},"content":{"105":{"position":[[2471,9]]}},"keywords":{}}],["2423n",{"_index":4876,"title":{},"content":{"168":{"position":[[343,6]]}},"keywords":{}}],["25",{"_index":451,"title":{},"content":{"8":{"position":[[201,4],[234,4]]},"30":{"position":[[5984,4],[6350,3]]},"34":{"position":[[3853,2],[3962,2]]},"44":{"position":[[858,3]]},"179":{"position":[[620,2],[1006,2],[1119,2]]},"196":{"position":[[1214,2]]}},"keywords":{}}],["250",{"_index":368,"title":{},"content":{"6":{"position":[[1007,3]]},"20":{"position":[[1108,3]]},"82":{"position":[[114,3]]}},"keywords":{}}],["2500000000",{"_index":2310,"title":{},"content":{"57":{"position":[[167,10]]}},"keywords":{}}],["251",{"_index":5241,"title":{},"content":{"189":{"position":[[1824,3]]}},"keywords":{}}],["253",{"_index":5239,"title":{},"content":{"189":{"position":[[1778,3],[1806,3]]}},"keywords":{}}],["256",{"_index":3597,"title":{},"content":{"105":{"position":[[1211,5],[1222,5],[1233,5],[1252,5],[1291,5],[2120,4],[2158,4],[2197,4],[2273,5],[2397,5],[2739,4],[3212,4]]},"195":{"position":[[180,3],[323,3]]}},"keywords":{}}],["258",{"_index":5240,"title":{},"content":{"189":{"position":[[1791,3]]}},"keywords":{}}],["2599n",{"_index":4881,"title":{},"content":{"169":{"position":[[340,6]]}},"keywords":{}}],["26",{"_index":2879,"title":{},"content":{"88":{"position":[[1548,3],[2942,4],[2995,3]]},"91":{"position":[[1048,4],[1226,3]]}},"keywords":{}}],["268",{"_index":1095,"title":{},"content":{"24":{"position":[[2528,3],[2532,3],[2548,3],[2552,3],[2569,3],[2573,3],[2592,3],[2596,3],[2616,3],[2620,3]]},"25":{"position":[[2251,3],[2255,3],[2271,3],[2275,3],[2292,3],[2296,3],[2315,3],[2319,3],[2339,3],[2343,3]]}},"keywords":{}}],["27",{"_index":2892,"title":{},"content":{"88":{"position":[[1875,3],[3269,4],[3384,3]]},"90":{"position":[[4060,3]]},"91":{"position":[[592,4],[760,3]]}},"keywords":{}}],["271",{"_index":1096,"title":{},"content":{"24":{"position":[[2536,3],[2540,3],[2556,3],[2560,3],[2577,3],[2581,3],[2600,3],[2604,3],[2624,3],[2628,3]]},"25":{"position":[[2259,3],[2263,3],[2279,3],[2283,3],[2300,3],[2304,3],[2323,3],[2327,3],[2347,3],[2351,3]]}},"keywords":{}}],["273n",{"_index":4866,"title":{},"content":{"168":{"position":[[261,5]]}},"keywords":{}}],["279",{"_index":5252,"title":{},"content":{"189":{"position":[[2563,3]]}},"keywords":{}}],["28",{"_index":2535,"title":{},"content":{"65":{"position":[[2481,3]]},"88":{"position":[[3313,4]]}},"keywords":{}}],["2836n",{"_index":4868,"title":{},"content":{"168":{"position":[[274,6]]}},"keywords":{}}],["286n",{"_index":4892,"title":{},"content":{"169":{"position":[[448,5]]}},"keywords":{}}],["29",{"_index":1659,"title":{},"content":{"34":{"position":[[3359,4],[3750,4]]},"181":{"position":[[289,2]]}},"keywords":{}}],["29)]['value'].sum",{"_index":2470,"title":{},"content":{"64":{"position":[[910,19]]},"65":{"position":[[1755,19]]}},"keywords":{}}],["2943n",{"_index":4864,"title":{},"content":{"168":{"position":[[226,6]]}},"keywords":{}}],["2f",{"_index":602,"title":{},"content":{"13":{"position":[[1873,7]]}},"keywords":{}}],["2f"",{"_index":604,"title":{},"content":{"13":{"position":[[1891,13]]},"14":{"position":[[2972,13]]},"15":{"position":[[2643,13]]}},"keywords":{}}],["2fs"",{"_index":538,"title":{},"content":{"12":{"position":[[626,12]]}},"keywords":{}}],["2fs\\n"",{"_index":592,"title":{},"content":{"13":{"position":[[1613,14]]},"14":{"position":[[2696,14]]},"15":{"position":[[2370,14]]}},"keywords":{}}],["2x",{"_index":1701,"title":{},"content":{"38":{"position":[[975,2]]}},"keywords":{}}],["3",{"_index":418,"title":{"80":{"position":[[8,2]]},"110":{"position":[[5,2]]},"117":{"position":[[8,2]]},"142":{"position":[[8,2]]}},"content":{"7":{"position":[[827,2]]},"13":{"position":[[2052,2]]},"14":{"position":[[1045,2],[1166,2],[3124,2]]},"15":{"position":[[2795,2]]},"22":{"position":[[2133,2]]},"24":{"position":[[389,1]]},"26":{"position":[[181,1]]},"38":{"position":[[983,1],[1110,1]]},"44":{"position":[[550,3]]},"53":{"position":[[450,1]]},"57":{"position":[[569,1]]},"58":{"position":[[726,1]]},"62":{"position":[[630,2]]},"63":{"position":[[71,1]]},"64":{"position":[[287,1]]},"66":{"position":[[240,1]]},"70":{"position":[[345,1],[521,1]]},"71":{"position":[[446,1],[620,1]]},"74":{"position":[[630,3]]},"80":{"position":[[77,1]]},"88":{"position":[[1455,2],[1784,2],[2846,2],[3243,2]]},"91":{"position":[[5009,1],[5522,1],[5728,1],[5906,1]]},"92":{"position":[[1603,1]]},"96":{"position":[[119,1]]},"163":{"position":[[844,1],[852,1],[872,1],[892,1]]},"193":{"position":[[1822,2],[2777,2]]}},"keywords":{}}],["3.4",{"_index":2329,"title":{},"content":{"58":{"position":[[252,3]]}},"keywords":{}}],["3.5",{"_index":2608,"title":{},"content":{"71":{"position":[[738,3],[766,3]]}},"keywords":{}}],["3.91",{"_index":4877,"title":{},"content":{"168":{"position":[[350,5]]}},"keywords":{}}],["3.96",{"_index":5246,"title":{},"content":{"189":{"position":[[2246,4]]}},"keywords":{}}],["3/1/2016",{"_index":2886,"title":{},"content":{"88":{"position":[[1677,8]]}},"keywords":{}}],["3/5/2016",{"_index":2894,"title":{},"content":{"88":{"position":[[1984,8]]}},"keywords":{}}],["30",{"_index":718,"title":{},"content":{"17":{"position":[[233,2]]},"30":{"position":[[9375,3]]},"88":{"position":[[3246,4]]},"123":{"position":[[679,2]]}},"keywords":{}}],["300",{"_index":3176,"title":{},"content":{"91":{"position":[[5823,5]]}},"keywords":{}}],["3000",{"_index":2792,"title":{},"content":{"82":{"position":[[407,5]]},"93":{"position":[[1223,4],[2943,4],[3082,4]]}},"keywords":{}}],["300kb",{"_index":4404,"title":{},"content":{"136":{"position":[[1014,5]]}},"keywords":{}}],["306",{"_index":5303,"title":{},"content":{"193":{"position":[[2379,3]]}},"keywords":{}}],["31",{"_index":2395,"title":{},"content":{"62":{"position":[[164,3],[633,3],[1654,2]]},"115":{"position":[[1121,2],[1468,2],[1751,2],[2209,2]]}},"keywords":{}}],["31st",{"_index":2446,"title":{},"content":{"62":{"position":[[1765,5]]}},"keywords":{}}],["32",{"_index":3545,"title":{},"content":{"103":{"position":[[2097,3]]},"105":{"position":[[726,2],[1201,4],[1217,4],[2082,3],[2153,4]]},"153":{"position":[[558,3],[617,3],[677,3],[737,3]]},"192":{"position":[[500,2]]},"195":{"position":[[240,3],[314,3],[391,3],[629,3]]}},"keywords":{}}],["32.375",{"_index":869,"title":{},"content":{"20":{"position":[[2985,8]]}},"keywords":{}}],["32.981380",{"_index":3622,"title":{},"content":{"105":{"position":[[2031,9]]}},"keywords":{}}],["33",{"_index":2144,"title":{},"content":{"51":{"position":[[3297,3],[3351,4]]},"116":{"position":[[1073,2],[1373,2],[1656,2],[2067,2]]}},"keywords":{}}],["34.527161",{"_index":3624,"title":{},"content":{"105":{"position":[[2058,9]]}},"keywords":{}}],["34.527344",{"_index":3634,"title":{},"content":{"105":{"position":[[2212,9],[2295,9]]}},"keywords":{}}],["34.531250",{"_index":3644,"title":{},"content":{"105":{"position":[[2461,9]]}},"keywords":{}}],["3497n",{"_index":4872,"title":{},"content":{"168":{"position":[[313,6]]}},"keywords":{}}],["35.79154",{"_index":1451,"title":{},"content":{"30":{"position":[[8481,10]]}},"keywords":{}}],["355n",{"_index":4870,"title":{},"content":{"168":{"position":[[300,5]]}},"keywords":{}}],["358",{"_index":5193,"title":{},"content":{"188":{"position":[[2620,3]]}},"keywords":{}}],["36.790387773552119",{"_index":867,"title":{},"content":{"20":{"position":[[2911,20]]}},"keywords":{}}],["365",{"_index":5172,"title":{},"content":{"188":{"position":[[1590,3],[1616,3]]}},"keywords":{}}],["366n",{"_index":4883,"title":{},"content":{"169":{"position":[[375,5]]}},"keywords":{}}],["369",{"_index":1877,"title":{},"content":{"43":{"position":[[668,3],[1128,3]]},"45":{"position":[[348,3]]}},"keywords":{}}],["36:6",{"_index":3776,"title":{},"content":{"115":{"position":[[1037,4],[1384,4],[2125,4]]}},"keywords":{}}],["37.800940",{"_index":3638,"title":{},"content":{"105":{"position":[[2347,9]]}},"keywords":{}}],["372",{"_index":5176,"title":{},"content":{"188":{"position":[[1634,3],[2587,3]]}},"keywords":{}}],["381",{"_index":5178,"title":{},"content":{"188":{"position":[[1688,3],[1714,3]]}},"keywords":{}}],["388",{"_index":5179,"title":{},"content":{"188":{"position":[[1732,3]]}},"keywords":{}}],["39",{"_index":5212,"title":{},"content":{"188":{"position":[[3869,2]]}},"keywords":{}}],["39.940753336615096)]"",{"_index":868,"title":{},"content":{"20":{"position":[[2940,26]]}},"keywords":{}}],["3f}%".format(expected_return",{"_index":856,"title":{},"content":{"20":{"position":[[2541,38]]}},"keywords":{}}],["4",{"_index":613,"title":{"81":{"position":[[8,2]]},"111":{"position":[[5,2]]}},"content":{"13":{"position":[[2108,2]]},"14":{"position":[[3180,2]]},"15":{"position":[[2851,2]]},"22":{"position":[[2203,2]]},"23":{"position":[[66,1]]},"28":{"position":[[1086,3]]},"65":{"position":[[311,1],[789,1],[1051,1],[1160,1]]},"70":{"position":[[365,1],[541,1]]},"71":{"position":[[466,1],[640,1]]},"80":{"position":[[83,2]]},"88":{"position":[[1545,2],[1872,2],[2868,2],[2916,2],[2939,2],[2992,2],[3266,2],[3310,2],[3381,2]]},"91":{"position":[[515,2],[567,2],[589,2],[757,2],[965,2],[1023,2],[1045,2],[1223,2]]},"97":{"position":[[1802,1]]},"105":{"position":[[744,1],[1193,3],[1197,3],[2045,2],[2078,3],[2939,2]]},"115":{"position":[[2469,1]]},"116":{"position":[[2327,1]]},"128":{"position":[[538,3],[651,2],[885,3],[1535,1],[1618,1]]},"163":{"position":[[854,1],[874,1],[894,1],[1072,1],[1706,2]]},"181":{"position":[[159,1]]},"193":{"position":[[1828,1],[2783,1]]}},"keywords":{}}],["4%bless",{"_index":1961,"title":{},"content":{"45":{"position":[[188,11]]}},"keywords":{}}],["4.05",{"_index":4894,"title":{},"content":{"169":{"position":[[460,5]]}},"keywords":{}}],["4.274846",{"_index":3631,"title":{},"content":{"105":{"position":[[2144,8]]}},"keywords":{}}],["4.34",{"_index":870,"title":{},"content":{"20":{"position":[[3018,6]]}},"keywords":{}}],["4.5",{"_index":2589,"title":{},"content":{"70":{"position":[[666,3]]},"90":{"position":[[4319,4]]}},"keywords":{}}],["40",{"_index":3044,"title":{},"content":{"90":{"position":[[4119,4]]}},"keywords":{}}],["40.78306",{"_index":1454,"title":{},"content":{"30":{"position":[[8513,10]]}},"keywords":{}}],["400",{"_index":3181,"title":{},"content":{"92":{"position":[[1375,4]]}},"keywords":{}}],["4000",{"_index":2794,"title":{},"content":{"82":{"position":[[477,5]]}},"keywords":{}}],["404",{"_index":3320,"title":{},"content":{"96":{"position":[[256,3]]}},"keywords":{}}],["413n",{"_index":4862,"title":{},"content":{"168":{"position":[[213,5]]}},"keywords":{}}],["42.098687",{"_index":1460,"title":{},"content":{"30":{"position":[[8589,11]]}},"keywords":{}}],["42.935064321851307",{"_index":865,"title":{},"content":{"20":{"position":[[2865,20]]}},"keywords":{}}],["421n",{"_index":4888,"title":{},"content":{"169":{"position":[[419,5]]}},"keywords":{}}],["47.60621",{"_index":1457,"title":{},"content":{"30":{"position":[[8549,10]]}},"keywords":{}}],["47578",{"_index":3159,"title":{},"content":{"91":{"position":[[4389,6],[4399,6],[5199,6],[5209,6],[5582,6],[5592,6]]},"92":{"position":[[1162,6],[1172,6],[1720,6],[1730,6],[1879,6],[1889,6]]}},"keywords":{}}],["4760716",{"_index":2527,"title":{},"content":{"65":{"position":[[2115,7]]}},"keywords":{}}],["48",{"_index":2516,"title":{},"content":{"65":{"position":[[1303,2]]}},"keywords":{}}],["48041640",{"_index":2514,"title":{},"content":{"65":{"position":[[1176,8]]}},"keywords":{}}],["481",{"_index":4599,"title":{},"content":{"156":{"position":[[666,3]]}},"keywords":{}}],["49",{"_index":323,"title":{},"content":{"6":{"position":[[345,5],[833,4]]}},"keywords":{}}],["49.517493",{"_index":3646,"title":{},"content":{"105":{"position":[[2514,9]]}},"keywords":{}}],["4b392b#4b392b",{"_index":2226,"title":{},"content":{"53":{"position":[[715,14]]}},"keywords":{}}],["4differentimplement",{"_index":3945,"title":{},"content":{"122":{"position":[[757,25]]}},"keywords":{}}],["4f",{"_index":591,"title":{},"content":{"13":{"position":[[1588,7]]},"14":{"position":[[2671,7]]},"15":{"position":[[2345,7]]}},"keywords":{}}],["5",{"_index":365,"title":{"82":{"position":[[8,2]]},"112":{"position":[[5,2]]}},"content":{"6":{"position":[[967,1],[1071,2]]},"11":{"position":[[139,1],[297,1]]},"13":{"position":[[2164,2],[2211,1]]},"14":{"position":[[3236,2],[3283,1]]},"15":{"position":[[2907,2],[2954,1]]},"30":{"position":[[3282,2],[7234,2]]},"33":{"position":[[946,3]]},"34":{"position":[[3462,1],[3566,1]]},"51":{"position":[[3304,2]]},"65":{"position":[[2478,2]]},"70":{"position":[[385,1],[561,1]]},"71":{"position":[[486,1],[660,1]]},"78":{"position":[[450,2]]},"88":{"position":[[1477,2],[1806,2],[1809,3],[3333,2],[3336,3]]},"90":{"position":[[3340,2],[4057,2],[4307,2],[4412,3],[4515,3]]},"91":{"position":[[4340,1],[4548,1],[5962,1]]},"97":{"position":[[1788,1]]},"103":{"position":[[629,1]]},"121":{"position":[[2180,2]]},"163":{"position":[[856,1],[876,1],[896,1]]},"193":{"position":[[1854,2],[2809,2]]}},"keywords":{}}],["5%you",{"_index":1586,"title":{},"content":{"33":{"position":[[1110,6]]}},"keywords":{}}],["5.0",{"_index":4764,"title":{},"content":{"163":{"position":[[459,3]]}},"keywords":{}}],["5.05",{"_index":610,"title":{},"content":{"13":{"position":[[2027,5]]}},"keywords":{}}],["5.18",{"_index":612,"title":{},"content":{"13":{"position":[[2083,5]]}},"keywords":{}}],["5.32",{"_index":617,"title":{},"content":{"13":{"position":[[2195,5]]}},"keywords":{}}],["5.34",{"_index":539,"title":{},"content":{"12":{"position":[[672,5]]}},"keywords":{}}],["5.37",{"_index":615,"title":{},"content":{"13":{"position":[[2139,5]]}},"keywords":{}}],["5.59",{"_index":607,"title":{},"content":{"13":{"position":[[1971,5]]}},"keywords":{}}],["5.590373200042106",{"_index":1662,"title":{},"content":{"34":{"position":[[3429,17]]}},"keywords":{}}],["5.62",{"_index":5187,"title":{},"content":{"188":{"position":[[2270,4]]}},"keywords":{}}],["5.6x",{"_index":1664,"title":{},"content":{"34":{"position":[[3523,4]]}},"keywords":{}}],["5.72",{"_index":653,"title":{},"content":{"14":{"position":[[3043,5]]}},"keywords":{}}],["5.81",{"_index":661,"title":{},"content":{"14":{"position":[[3267,5]]}},"keywords":{}}],["5.8337945679814904",{"_index":864,"title":{},"content":{"20":{"position":[[2836,20]]}},"keywords":{}}],["5.85",{"_index":655,"title":{},"content":{"14":{"position":[[3099,5]]}},"keywords":{}}],["5.87",{"_index":657,"title":{},"content":{"14":{"position":[[3155,5]]}},"keywords":{}}],["5.89",{"_index":685,"title":{},"content":{"15":{"position":[[2714,5]]}},"keywords":{}}],["5.90",{"_index":687,"title":{},"content":{"15":{"position":[[2770,5]]}},"keywords":{}}],["5.92",{"_index":689,"title":{},"content":{"15":{"position":[[2826,5]]}},"keywords":{}}],["5.93",{"_index":659,"title":{},"content":{"14":{"position":[[3211,5]]}},"keywords":{}}],["5.94",{"_index":691,"title":{},"content":{"15":{"position":[[2882,5]]}},"keywords":{}}],["5/1/2016"",{"_index":2887,"title":{},"content":{"88":{"position":[[1688,16]]}},"keywords":{}}],["5/18/2016",{"_index":3214,"title":{},"content":{"93":{"position":[[2036,9]]}},"keywords":{}}],["5/19/2016",{"_index":3213,"title":{},"content":{"93":{"position":[[1964,10]]}},"keywords":{}}],["5/5/2016",{"_index":2895,"title":{},"content":{"88":{"position":[[1995,10]]}},"keywords":{}}],["50",{"_index":672,"title":{},"content":{"15":{"position":[[377,4]]},"24":{"position":[[341,3]]},"30":{"position":[[1191,4]]},"44":{"position":[[871,3]]},"49":{"position":[[329,3],[370,3]]},"51":{"position":[[3375,4]]}},"keywords":{}}],["500",{"_index":846,"title":{},"content":{"20":{"position":[[2290,5]]},"23":{"position":[[100,3]]},"24":{"position":[[3362,3]]},"150":{"position":[[534,4]]},"161":{"position":[[1352,3]]}},"keywords":{}}],["5000",{"_index":2796,"title":{},"content":{"82":{"position":[[547,5]]}},"keywords":{}}],["51131",{"_index":1945,"title":{},"content":{"44":{"position":[[1589,6]]}},"keywords":{}}],["512",{"_index":3600,"title":{},"content":{"105":{"position":[[1265,5],[1304,5],[2315,5],[2439,5]]}},"keywords":{}}],["522",{"_index":5254,"title":{},"content":{"189":{"position":[[2849,3]]}},"keywords":{}}],["524",{"_index":5253,"title":{},"content":{"189":{"position":[[2805,3],[2831,3]]}},"keywords":{}}],["539n",{"_index":4879,"title":{},"content":{"169":{"position":[[327,5]]}},"keywords":{}}],["541",{"_index":5245,"title":{},"content":{"189":{"position":[[2233,3],[2280,3]]}},"keywords":{}}],["545",{"_index":5247,"title":{},"content":{"189":{"position":[[2262,3]]}},"keywords":{}}],["545.0354060154496",{"_index":2799,"title":{},"content":{"82":{"position":[[658,17]]}},"keywords":{}}],["546.7574874775273",{"_index":2795,"title":{},"content":{"82":{"position":[[518,17]]}},"keywords":{}}],["547.7803673440676",{"_index":2791,"title":{},"content":{"82":{"position":[[378,17]]}},"keywords":{}}],["547.9805613193807",{"_index":2793,"title":{},"content":{"82":{"position":[[448,17]]}},"keywords":{}}],["549.400679551826",{"_index":2806,"title":{},"content":{"82":{"position":[[939,16]]}},"keywords":{}}],["549.5798007672656",{"_index":2797,"title":{},"content":{"82":{"position":[[588,17]]}},"keywords":{}}],["549.9306537114975",{"_index":2803,"title":{},"content":{"82":{"position":[[798,17]]}},"keywords":{}}],["55",{"_index":5336,"title":{},"content":{"196":{"position":[[1625,2]]}},"keywords":{}}],["550.1134504086606",{"_index":2801,"title":{},"content":{"82":{"position":[[728,17]]}},"keywords":{}}],["550.7075182119111",{"_index":2805,"title":{},"content":{"82":{"position":[[868,17]]}},"keywords":{}}],["551",{"_index":5249,"title":{},"content":{"189":{"position":[[2516,3]]}},"keywords":{}}],["551.6995384525453",{"_index":2790,"title":{},"content":{"82":{"position":[[308,17]]}},"keywords":{}}],["559",{"_index":5251,"title":{},"content":{"189":{"position":[[2545,3]]}},"keywords":{}}],["5:28",{"_index":2539,"title":{},"content":{"65":{"position":[[2544,4]]}},"keywords":{}}],["6",{"_index":561,"title":{"113":{"position":[[5,2]]}},"content":{"13":{"position":[[575,2]]},"14":{"position":[[1405,2]]},"15":{"position":[[774,2]]},"30":{"position":[[7194,2]]},"40":{"position":[[475,2],[2011,2],[2955,2]]},"45":{"position":[[2470,2],[3250,2]]},"64":{"position":[[458,1],[774,1],[960,1]]},"70":{"position":[[405,1],[580,1]]},"71":{"position":[[506,1],[680,1]]},"76":{"position":[[1304,2],[1354,2],[2027,2],[2054,2]]},"79":{"position":[[61,2]]},"80":{"position":[[54,2]]},"81":{"position":[[131,3],[150,3]]},"88":{"position":[[3551,2]]},"90":{"position":[[4240,3]]},"91":{"position":[[460,2],[4322,2]]},"163":{"position":[[858,1],[878,1],[898,1]]},"175":{"position":[[264,1]]},"193":{"position":[[1860,1],[2815,1]]}},"keywords":{}}],["6%capit",{"_index":641,"title":{},"content":{"14":{"position":[[1290,9]]}},"keywords":{}}],["6"",{"_index":954,"title":{},"content":{"22":{"position":[[1807,7]]},"71":{"position":[[1406,9]]}},"keywords":{}}],["6.00",{"_index":4890,"title":{},"content":{"169":{"position":[[432,5]]}},"keywords":{}}],["6.06",{"_index":693,"title":{},"content":{"15":{"position":[[2938,5]]}},"keywords":{}}],["6.185015",{"_index":3641,"title":{},"content":{"105":{"position":[[2388,8]]}},"keywords":{}}],["6000",{"_index":2798,"title":{},"content":{"82":{"position":[[617,5]]}},"keywords":{}}],["603",{"_index":2132,"title":{},"content":{"51":{"position":[[2551,3],[2579,3]]}},"keywords":{}}],["63",{"_index":1164,"title":{},"content":{"25":{"position":[[2753,3]]}},"keywords":{}}],["64",{"_index":3598,"title":{},"content":{"105":{"position":[[1228,4],[2192,4],[3208,3]]},"192":{"position":[[693,2]]}},"keywords":{}}],["641",{"_index":5186,"title":{},"content":{"188":{"position":[[2257,3]]}},"keywords":{}}],["645",{"_index":5189,"title":{},"content":{"188":{"position":[[2304,3]]}},"keywords":{}}],["647",{"_index":5188,"title":{},"content":{"188":{"position":[[2286,3]]}},"keywords":{}}],["659n",{"_index":4893,"title":{},"content":{"169":{"position":[[454,5]]}},"keywords":{}}],["667",{"_index":5198,"title":{},"content":{"188":{"position":[[3112,3],[3138,3]]}},"keywords":{}}],["672",{"_index":5199,"title":{},"content":{"188":{"position":[[3156,3]]}},"keywords":{}}],["69",{"_index":1666,"title":{},"content":{"34":{"position":[[3595,4]]}},"keywords":{}}],["69.054298",{"_index":3618,"title":{},"content":{"105":{"position":[[1973,9]]}},"keywords":{}}],["69.054306",{"_index":3621,"title":{},"content":{"105":{"position":[[2011,9],[2021,9]]}},"keywords":{}}],["69.054321",{"_index":3623,"title":{},"content":{"105":{"position":[[2048,9]]}},"keywords":{}}],["69.054443",{"_index":3626,"title":{},"content":{"105":{"position":[[2086,9]]}},"keywords":{}}],["69.054688",{"_index":3629,"title":{},"content":{"105":{"position":[[2125,9],[2163,9],[2202,9],[2244,9],[2285,9],[2327,9],[2337,9]]}},"keywords":{}}],["69.062500",{"_index":3639,"title":{},"content":{"105":{"position":[[2369,9],[2409,9],[2451,9],[2494,9],[2504,9]]}},"keywords":{}}],["6\\}pij​∈(0,1);i,j∈{1,…,6",{"_index":2822,"title":{},"content":{"85":{"position":[[303,26]]}},"keywords":{}}],["6x",{"_index":1700,"title":{},"content":{"38":{"position":[[921,2]]}},"keywords":{}}],["7",{"_index":1260,"title":{},"content":{"28":{"position":[[1899,3]]},"30":{"position":[[9341,2]]},"68":{"position":[[522,2],[562,2],[724,1]]},"70":{"position":[[708,1],[1288,1]]},"71":{"position":[[808,1]]},"163":{"position":[[860,1],[880,1],[900,1]]}},"keywords":{}}],["7.77",{"_index":5250,"title":{},"content":{"189":{"position":[[2529,4]]}},"keywords":{}}],["70",{"_index":642,"title":{},"content":{"14":{"position":[[1317,3]]},"15":{"position":[[325,3]]},"196":{"position":[[1827,2]]}},"keywords":{}}],["70%coupon",{"_index":640,"title":{},"content":{"14":{"position":[[1279,10]]}},"keywords":{}}],["7000",{"_index":2800,"title":{},"content":{"82":{"position":[[687,5]]}},"keywords":{}}],["717",{"_index":5191,"title":{},"content":{"188":{"position":[[2574,3]]}},"keywords":{}}],["718",{"_index":5192,"title":{},"content":{"188":{"position":[[2602,3]]}},"keywords":{}}],["73",{"_index":4516,"title":{},"content":{"152":{"position":[[683,2]]}},"keywords":{}}],["73.971249",{"_index":1455,"title":{},"content":{"30":{"position":[[8524,10]]}},"keywords":{}}],["737n",{"_index":4884,"title":{},"content":{"169":{"position":[[381,5]]}},"keywords":{}}],["75",{"_index":1929,"title":{},"content":{"44":{"position":[[884,3]]}},"keywords":{}}],["75.917974",{"_index":1461,"title":{},"content":{"30":{"position":[[8601,10]]}},"keywords":{}}],["773609400",{"_index":2474,"title":{},"content":{"64":{"position":[[1072,9]]}},"keywords":{}}],["774",{"_index":2476,"title":{},"content":{"64":{"position":[[1145,3]]}},"keywords":{}}],["775,804,660",{"_index":2496,"title":{},"content":{"64":{"position":[[1987,11]]}},"keywords":{}}],["775804660",{"_index":2494,"title":{},"content":{"64":{"position":[[1901,9]]}},"keywords":{}}],["78.781117",{"_index":1452,"title":{},"content":{"30":{"position":[[8492,10]]}},"keywords":{}}],["7983)browser",{"_index":4206,"title":{},"content":{"125":{"position":[[11127,14]]}},"keywords":{}}],["8",{"_index":644,"title":{},"content":{"14":{"position":[[1376,2]]},"15":{"position":[[745,2]]},"28":{"position":[[1914,3]]},"34":{"position":[[3990,2]]},"40":{"position":[[306,3],[1840,3],[2783,3]]},"53":{"position":[[199,1],[1429,1]]},"65":{"position":[[2080,1]]},"91":{"position":[[1539,1],[4998,1],[5063,1],[5145,1],[5372,1],[5969,1]]},"92":{"position":[[1597,1]]},"127":{"position":[[643,2],[1293,2]]},"128":{"position":[[280,2],[503,3],[542,1],[1152,2],[1423,1]]},"129":{"position":[[911,2],[947,1],[1150,2],[1566,1],[2621,1],[2648,3]]},"163":{"position":[[862,1],[882,1],[902,1],[1163,1]]},"172":{"position":[[497,2]]},"185":{"position":[[834,2]]},"195":{"position":[[249,1],[400,1]]}},"keywords":{}}],["8.481735",{"_index":3628,"title":{},"content":{"105":{"position":[[2106,8]]}},"keywords":{}}],["8.542909",{"_index":3633,"title":{},"content":{"105":{"position":[[2183,8]]}},"keywords":{}}],["8.631836",{"_index":3630,"title":{},"content":{"105":{"position":[[2135,8]]}},"keywords":{}}],["8.632812",{"_index":3640,"title":{},"content":{"105":{"position":[[2379,8]]}},"keywords":{}}],["8.__str__",{"_index":4329,"title":{},"content":{"129":{"position":[[2408,13],[2454,11],[2505,11]]}},"keywords":{}}],["8.to_str",{"_index":4279,"title":{},"content":{"129":{"position":[[430,13]]},"130":{"position":[[469,13]]}},"keywords":{}}],["80",{"_index":673,"title":{},"content":{"15":{"position":[[438,4]]},"26":{"position":[[664,3]]}},"keywords":{}}],["8000",{"_index":2802,"title":{},"content":{"82":{"position":[[757,5]]}},"keywords":{}}],["8139060",{"_index":2444,"title":{},"content":{"62":{"position":[[1667,7]]}},"keywords":{}}],["86400",{"_index":2380,"title":{},"content":{"61":{"position":[[1697,6]]}},"keywords":{}}],["890",{"_index":5216,"title":{},"content":{"188":{"position":[[4013,3]]}},"keywords":{}}],["9",{"_index":324,"title":{},"content":{"6":{"position":[[351,3],[838,3]]},"28":{"position":[[1932,3]]},"90":{"position":[[4622,4]]},"163":{"position":[[864,1],[884,1],[904,1]]},"172":{"position":[[511,2]]}},"keywords":{}}],["9.430644",{"_index":3636,"title":{},"content":{"105":{"position":[[2264,8]]}},"keywords":{}}],["9000",{"_index":2804,"title":{},"content":{"82":{"position":[[827,5]]}},"keywords":{}}],["91n",{"_index":4874,"title":{},"content":{"168":{"position":[[331,4]]}},"keywords":{}}],["926",{"_index":5214,"title":{},"content":{"188":{"position":[[3934,3]]}},"keywords":{}}],["95.00",{"_index":620,"title":{},"content":{"13":{"position":[[2275,7]]}},"keywords":{}}],["96",{"_index":2456,"title":{},"content":{"64":{"position":[[441,2],[945,2]]}},"keywords":{}}],["96mmm",{"_index":2465,"title":{},"content":{"64":{"position":[[733,6]]}},"keywords":{}}],["97.44",{"_index":663,"title":{},"content":{"14":{"position":[[3363,6]]}},"keywords":{}}],["99.9th",{"_index":4859,"title":{},"content":{"168":{"position":[[177,6]]},"169":{"position":[[291,6]]}},"keywords":{}}],["99th",{"_index":4857,"title":{},"content":{"168":{"position":[[167,4]]},"169":{"position":[[281,4]]}},"keywords":{}}],["_",{"_index":3374,"title":{},"content":{"97":{"position":[[1561,3],[3656,2]]},"103":{"position":[[1730,2],[1733,2],[2049,2],[2052,2]]},"105":{"position":[[2687,2],[2690,2],[2888,2],[2891,2],[3160,2],[3163,2]]},"188":{"position":[[1553,1],[1649,1]]},"189":{"position":[[1743,1]]}},"keywords":{}}],["__abs__",{"_index":4311,"title":{},"content":{"129":{"position":[[2132,11]]}},"keywords":{}}],["__add__",{"_index":4312,"title":{},"content":{"129":{"position":[[2144,10]]}},"keywords":{}}],["__and__",{"_index":4313,"title":{},"content":{"129":{"position":[[2155,10]]}},"keywords":{}}],["__class__",{"_index":4314,"title":{},"content":{"129":{"position":[[2166,12]]}},"keywords":{}}],["__cmp__",{"_index":4315,"title":{},"content":{"129":{"position":[[2179,10]]}},"keywords":{}}],["__coerce__",{"_index":4316,"title":{},"content":{"129":{"position":[[2190,13]]}},"keywords":{}}],["__delattr__",{"_index":4317,"title":{},"content":{"129":{"position":[[2204,14]]}},"keywords":{}}],["__div__",{"_index":4318,"title":{},"content":{"129":{"position":[[2219,10]]}},"keywords":{}}],["__divmod__",{"_index":4319,"title":{},"content":{"129":{"position":[[2230,13]]}},"keywords":{}}],["__doc__",{"_index":4320,"title":{},"content":{"129":{"position":[[2244,10]]}},"keywords":{}}],["__float__",{"_index":4321,"title":{},"content":{"129":{"position":[[2255,12]]}},"keywords":{}}],["__floordiv__",{"_index":4322,"title":{},"content":{"129":{"position":[[2268,15]]}},"keywords":{}}],["__init__",{"_index":931,"title":{},"content":{"22":{"position":[[1268,8]]}},"keywords":{}}],["__init__(self",{"_index":932,"title":{},"content":{"22":{"position":[[1281,14]]},"93":{"position":[[1549,14]]}},"keywords":{}}],["__setattr__",{"_index":4323,"title":{},"content":{"129":{"position":[[2288,14]]}},"keywords":{}}],["__sizeof__",{"_index":4324,"title":{},"content":{"129":{"position":[[2303,13]]}},"keywords":{}}],["__str__",{"_index":4325,"title":{},"content":{"129":{"position":[[2317,10]]}},"keywords":{}}],["__sub__",{"_index":4326,"title":{},"content":{"129":{"position":[[2328,10]]}},"keywords":{}}],["__subclasshook__",{"_index":4327,"title":{},"content":{"129":{"position":[[2339,19]]}},"keywords":{}}],["__truediv__",{"_index":4328,"title":{},"content":{"129":{"position":[[2359,14]]}},"keywords":{}}],["_a",{"_index":4548,"title":{},"content":{"153":{"position":[[548,3],[599,3],[664,3],[718,3]]},"195":{"position":[[230,3],[296,3],[378,3],[610,3]]}},"keywords":{}}],["_bootstrap",{"_index":5217,"title":{},"content":{"188":{"position":[[4020,10]]}},"keywords":{}}],["_bootstrap_inn",{"_index":5215,"title":{},"content":{"188":{"position":[[3941,16]]}},"keywords":{}}],["_dist_1",{"_index":5293,"title":{},"content":{"193":{"position":[[1869,7],[2824,7]]}},"keywords":{}}],["_dist_2",{"_index":5296,"title":{},"content":{"193":{"position":[[1918,7],[2873,7]]}},"keywords":{}}],["_i",{"_index":5164,"title":{},"content":{"188":{"position":[[1099,2]]},"189":{"position":[[1161,2],[1431,2]]},"199":{"position":[[1478,4]]}},"keywords":{}}],["_x",{"_index":4554,"title":{},"content":{"153":{"position":[[914,5],[1002,2]]},"195":{"position":[[818,2]]}},"keywords":{}}],["a"flamegraph"",{"_index":4378,"title":{},"content":{"135":{"position":[[92,24]]}},"keywords":{}}],["a.i",{"_index":5285,"title":{},"content":{"193":{"position":[[1367,4],[2547,4],[2617,4],[2631,4],[3318,4],[3632,4]]}},"keywords":{}}],["a.x",{"_index":5282,"title":{},"content":{"193":{"position":[[1339,4],[2519,4],[2578,4],[2592,4],[3290,4],[3604,4]]}},"keywords":{}}],["a=440",{"_index":63,"title":{},"content":{"1":{"position":[[702,5]]}},"keywords":{}}],["aa",{"_index":4915,"title":{},"content":{"172":{"position":[[1176,2]]}},"keywords":{}}],["aac",{"_index":3478,"title":{},"content":{"101":{"position":[[591,3]]},"106":{"position":[[437,3]]}},"keywords":{}}],["aamaz",{"_index":2275,"title":{},"content":{"53":{"position":[[1499,8]]}},"keywords":{}}],["aapl",{"_index":2875,"title":{},"content":{"88":{"position":[[1412,4],[2756,4],[2876,5],[2947,5]]},"91":{"position":[[1501,4]]}},"keywords":{}}],["aapl[datetime(2016",{"_index":3091,"title":{},"content":{"91":{"position":[[1003,19]]}},"keywords":{}}],["aapl_plot",{"_index":3088,"title":{},"content":{"91":{"position":[[909,9],[975,10]]}},"keywords":{}}],["aapl_plot.legend(loc=3",{"_index":3097,"title":{},"content":{"91":{"position":[[1319,23]]}},"keywords":{}}],["aapl_plot.plot(aapl_truncated.index",{"_index":3095,"title":{},"content":{"91":{"position":[[1117,36]]}},"keywords":{}}],["aapl_plot.set_title('aapl",{"_index":3098,"title":{},"content":{"91":{"position":[[1343,25]]}},"keywords":{}}],["aapl_plot.vlines(date2num(datetime(2016",{"_index":3096,"title":{},"content":{"91":{"position":[[1182,40]]}},"keywords":{}}],["aapl_trunc",{"_index":3090,"title":{},"content":{"91":{"position":[[986,14]]}},"keywords":{}}],["aapl_truncated['close']/2",{"_index":3094,"title":{},"content":{"91":{"position":[[1091,25]]}},"keywords":{}}],["aapl_truncated['open']/2",{"_index":3093,"title":{},"content":{"91":{"position":[[1064,24]]}},"keywords":{}}],["abandon",{"_index":169,"title":{},"content":{"3":{"position":[[675,9]]},"97":{"position":[[2636,7]]}},"keywords":{}}],["abil",{"_index":280,"title":{},"content":{"4":{"position":[[1098,7]]},"46":{"position":[[162,7]]}},"keywords":{}}],["abort",{"_index":3785,"title":{},"content":{"115":{"position":[[2453,8]]},"116":{"position":[[2311,8]]}},"keywords":{}}],["aboutlong",{"_index":3906,"title":{},"content":{"121":{"position":[[1645,9]]}},"keywords":{}}],["abov",{"_index":474,"title":{},"content":{"9":{"position":[[696,5]]},"13":{"position":[[181,5],[263,5]]},"14":{"position":[[336,5],[406,5],[724,5],[868,5],[1061,5]]},"20":{"position":[[878,5]]},"30":{"position":[[1185,5],[2289,6]]},"33":{"position":[[44,5]]},"40":{"position":[[3384,5]]},"43":{"position":[[1113,6]]},"72":{"position":[[402,5]]},"83":{"position":[[19,6]]},"88":{"position":[[3572,6]]},"90":{"position":[[5062,5]]},"125":{"position":[[8840,5]]},"176":{"position":[[825,5]]},"189":{"position":[[1671,6]]}},"keywords":{}}],["above)project",{"_index":4207,"title":{},"content":{"125":{"position":[[11250,14]]}},"keywords":{}}],["above,std::vec",{"_index":4695,"title":{},"content":{"160":{"position":[[2497,14]]}},"keywords":{}}],["acc_df",{"_index":1916,"title":{},"content":{"44":{"position":[[701,6]]}},"keywords":{}}],["acc_df.describ",{"_index":1919,"title":{},"content":{"44":{"position":[[772,17]]}},"keywords":{}}],["acccur",{"_index":1171,"title":{},"content":{"26":{"position":[[239,9]]}},"keywords":{}}],["accept",{"_index":3431,"title":{},"content":{"97":{"position":[[5917,6]]},"101":{"position":[[995,10]]},"125":{"position":[[4224,7]]},"166":{"position":[[706,6]]},"176":{"position":[[1615,10]]},"182":{"position":[[659,10]]}},"keywords":{}}],["accept_prob",{"_index":2740,"title":{},"content":{"76":{"position":[[3018,11],[3109,12]]}},"keywords":{}}],["access",{"_index":2350,"title":{},"content":{"61":{"position":[[134,6],[354,6],[716,6],[763,6],[953,6],[1196,6]]},"62":{"position":[[36,6]]},"97":{"position":[[5525,6]]},"113":{"position":[[405,6]]},"115":{"position":[[2813,8]]},"121":{"position":[[520,6]]},"128":{"position":[[612,6]]},"160":{"position":[[2359,6]]},"173":{"position":[[2103,8]]},"174":{"position":[[620,6]]},"180":{"position":[[208,9]]},"185":{"position":[[150,6]]},"188":{"position":[[4247,7]]},"190":{"position":[[320,6]]}},"keywords":{}}],["access_token",{"_index":2391,"title":{},"content":{"61":{"position":[[2302,12]]},"62":{"position":[[51,13],[490,15],[506,13]]}},"keywords":{}}],["accident",{"_index":823,"title":{},"content":{"20":{"position":[[1625,12]]},"160":{"position":[[1408,12]]}},"keywords":{}}],["accomplish",{"_index":2230,"title":{},"content":{"53":{"position":[[810,15],[1740,15]]},"86":{"position":[[595,11]]},"101":{"position":[[319,10]]},"160":{"position":[[2186,12]]},"164":{"position":[[1278,13]]},"186":{"position":[[155,10]]}},"keywords":{}}],["accord",{"_index":2536,"title":{},"content":{"65":{"position":[[2487,9]]},"75":{"position":[[1203,9]]}},"keywords":{}}],["account",{"_index":1437,"title":{},"content":{"30":{"position":[[7778,7]]},"43":{"position":[[959,9]]},"64":{"position":[[339,7]]},"76":{"position":[[1569,7]]},"86":{"position":[[419,8]]},"90":{"position":[[3243,7]]}},"keywords":{}}],["accur",{"_index":1014,"title":{},"content":{"24":{"position":[[55,8],[345,9],[3224,8]]},"25":{"position":[[2772,8]]},"26":{"position":[[86,8]]},"45":{"position":[[980,8]]},"65":{"position":[[147,8]]},"91":{"position":[[5127,9]]},"193":{"position":[[1042,9]]}},"keywords":{}}],["accuraci",{"_index":1098,"title":{},"content":{"24":{"position":[[2643,9]]},"25":{"position":[[2366,9],[2757,8]]},"26":{"position":[[641,8]]},"44":{"position":[[631,8],[746,10],[1525,9],[1636,9]]},"45":{"position":[[1736,8]]},"89":{"position":[[771,8]]}},"keywords":{}}],["accuracy"",{"_index":2008,"title":{},"content":{"45":{"position":[[2286,15],[3066,15]]}},"keywords":{}}],["accuracy:"",{"_index":1092,"title":{},"content":{"24":{"position":[[2416,16]]},"25":{"position":[[2139,16]]}},"keywords":{}}],["accuracycount",{"_index":1920,"title":{},"content":{"44":{"position":[[793,13]]}},"keywords":{}}],["accus",{"_index":2946,"title":{},"content":{"89":{"position":[[220,6]]}},"keywords":{}}],["achiev",{"_index":1174,"title":{},"content":{"26":{"position":[[630,7]]},"117":{"position":[[2034,7]]}},"keywords":{}}],["acknowledg",{"_index":3314,"title":{},"content":{"96":{"position":[[29,11]]},"175":{"position":[[870,14]]}},"keywords":{}}],["aconst",{"_index":5128,"title":{},"content":{"184":{"position":[[918,6]]}},"keywords":{}}],["acquir",{"_index":4901,"title":{},"content":{"172":{"position":[[306,8]]},"188":{"position":[[1388,8],[2388,7]]},"189":{"position":[[2938,9]]}},"keywords":{}}],["acquire/releaseth",{"_index":5220,"title":{},"content":{"188":{"position":[[4176,18]]}},"keywords":{}}],["acquisit",{"_index":4560,"title":{},"content":{"155":{"position":[[329,11]]}},"keywords":{}}],["act",{"_index":3574,"title":{},"content":{"105":{"position":[[157,4]]},"113":{"position":[[851,4]]}},"keywords":{}}],["action",{"_index":2905,"title":{},"content":{"88":{"position":[[2424,7]]},"113":{"position":[[2567,7]]},"127":{"position":[[1625,7]]},"179":{"position":[[354,7]]},"188":{"position":[[818,7]]},"193":{"position":[[874,6]]}},"keywords":{}}],["activ",{"_index":181,"title":{},"content":{"3":{"position":[[905,8]]},"62":{"position":[[863,11]]},"188":{"position":[[578,6],[1970,6]]}},"keywords":{}}],["activities/heart/date/{0}/1d/1min.json",{"_index":2412,"title":{},"content":{"62":{"position":[[716,40]]}},"keywords":{}}],["actual",{"_index":22,"title":{"76":{"position":[[4,6]]}},"content":{"1":{"position":[[241,8]]},"2":{"position":[[94,6],[513,8]]},"7":{"position":[[800,8]]},"10":{"position":[[576,6]]},"11":{"position":[[52,8]]},"12":{"position":[[20,8]]},"13":{"position":[[57,8]]},"22":{"position":[[111,6]]},"24":{"position":[[1075,8],[2996,6]]},"25":{"position":[[795,8]]},"26":{"position":[[200,6]]},"28":{"position":[[803,8]]},"29":{"position":[[196,8]]},"30":{"position":[[563,8],[738,8],[4067,8],[7279,8]]},"34":{"position":[[130,8],[280,8],[754,8]]},"35":{"position":[[162,8],[407,8]]},"38":{"position":[[1300,6]]},"40":{"position":[[743,8]]},"43":{"position":[[1264,8]]},"45":{"position":[[919,8],[1262,8],[1535,6],[3557,8]]},"46":{"position":[[173,8],[445,8]]},"49":{"position":[[641,6]]},"51":{"position":[[2000,8],[2241,8],[2767,8],[2957,6],[3563,8]]},"52":{"position":[[43,8]]},"62":{"position":[[16,8],[86,6],[1788,6]]},"73":{"position":[[498,6]]},"74":{"position":[[144,8]]},"76":{"position":[[96,8],[620,8]]},"77":{"position":[[212,6]]},"82":{"position":[[1037,6]]},"86":{"position":[[984,8]]},"90":{"position":[[56,6]]},"91":{"position":[[1714,8]]},"95":{"position":[[329,8]]},"96":{"position":[[1823,8]]},"97":{"position":[[745,6],[2728,8],[4180,8],[6319,8]]},"102":{"position":[[1462,8]]},"103":{"position":[[148,8],[1274,6],[1552,8]]},"106":{"position":[[78,8],[254,8]]},"108":{"position":[[178,8]]},"109":{"position":[[48,8]]},"111":{"position":[[18,8]]},"112":{"position":[[67,8],[409,8],[596,6],[1744,8]]},"113":{"position":[[103,8],[626,6],[1306,6],[1626,8]]},"116":{"position":[[3214,8]]},"117":{"position":[[449,6],[1681,6],[1933,8]]},"120":{"position":[[398,8]]},"121":{"position":[[197,8],[371,6],[2334,8]]},"125":{"position":[[6316,8],[6911,8]]},"130":{"position":[[486,8]]},"160":{"position":[[2515,8]]},"163":{"position":[[375,8],[2444,8]]},"165":{"position":[[426,8]]},"167":{"position":[[60,8]]},"172":{"position":[[1879,8]]},"176":{"position":[[1170,8]]},"188":{"position":[[4493,8]]},"193":{"position":[[1396,6]]},"196":{"position":[[123,8]]}},"keywords":{}}],["actual_word",{"_index":2100,"title":{},"content":{"51":{"position":[[1194,12]]}},"keywords":{}}],["actualu64",{"_index":5345,"title":{},"content":{"197":{"position":[[537,9],[574,9],[1224,11],[1350,9]]}},"keywords":{}}],["ad",{"_index":193,"title":{},"content":{"3":{"position":[[1129,5]]},"121":{"position":[[2636,5]]},"123":{"position":[[1059,6]]},"166":{"position":[[21,5]]},"189":{"position":[[471,5],[605,6]]}},"keywords":{}}],["adapt",{"_index":5138,"title":{},"content":{"186":{"position":[[219,7]]}},"keywords":{}}],["add",{"_index":285,"title":{},"content":{"4":{"position":[[1220,4]]},"7":{"position":[[87,3]]},"128":{"position":[[1609,3]]},"129":{"position":[[719,3]]},"133":{"position":[[251,3]]},"161":{"position":[[1239,3],[1289,3]]},"185":{"position":[[579,3]]},"193":{"position":[[1649,3]]}},"keywords":{}}],["addit",{"_index":1403,"title":{},"content":{"30":{"position":[[4425,8],[5860,8]]},"86":{"position":[[431,9]]},"125":{"position":[[4411,10]]},"172":{"position":[[2145,8]]},"173":{"position":[[1005,8]]}},"keywords":{}}],["addition",{"_index":343,"title":{},"content":{"6":{"position":[[599,12]]},"66":{"position":[[285,13]]},"83":{"position":[[304,13]]},"85":{"position":[[400,13]]},"90":{"position":[[3379,13]]}},"keywords":{}}],["address",{"_index":1592,"title":{},"content":{"34":{"position":[[182,8]]},"160":{"position":[[2241,10],[3343,7],[3632,7]]},"165":{"position":[[135,7]]},"166":{"position":[[221,9]]},"170":{"position":[[169,9]]},"178":{"position":[[497,7]]},"180":{"position":[[270,8]]},"181":{"position":[[654,7]]},"190":{"position":[[37,7],[420,7]]},"197":{"position":[[1006,7]]},"198":{"position":[[127,9]]},"199":{"position":[[789,8]]}},"keywords":{}}],["adjust",{"_index":3039,"title":{},"content":{"90":{"position":[[3920,10]]}},"keywords":{}}],["admit",{"_index":1312,"title":{},"content":{"29":{"position":[[11,5]]}},"keywords":{}}],["admittedli",{"_index":3872,"title":{},"content":{"121":{"position":[[99,10]]}},"keywords":{}}],["advanc",{"_index":2901,"title":{},"content":{"88":{"position":[[2256,7]]}},"keywords":{}}],["advantag",{"_index":1690,"title":{},"content":{"38":{"position":[[256,9]]},"97":{"position":[[2700,9]]},"125":{"position":[[1102,9]]}},"keywords":{}}],["advent",{"_index":4350,"title":{},"content":{"132":{"position":[[516,6]]}},"keywords":{}}],["advic",{"_index":1682,"title":{},"content":{"36":{"position":[[137,6]]}},"keywords":{}}],["affect",{"_index":4635,"title":{},"content":{"159":{"position":[[817,6]]},"160":{"position":[[1899,6]]},"176":{"position":[[281,7]]}},"keywords":{}}],["affin",{"_index":4947,"title":{},"content":{"173":{"position":[[691,8],[803,8],[1843,8]]}},"keywords":{}}],["afirst",{"_index":4820,"title":{},"content":{"165":{"position":[[41,6]]}},"keywords":{}}],["aftermov",{"_index":3916,"title":{},"content":{"121":{"position":[[2118,11]]}},"keywords":{}}],["afternoon",{"_index":3026,"title":{},"content":{"90":{"position":[[3502,9]]}},"keywords":{}}],["afterward",{"_index":1857,"title":{},"content":{"41":{"position":[[637,10]]},"76":{"position":[[823,10]]},"193":{"position":[[230,10]]}},"keywords":{}}],["again",{"_index":1320,"title":{},"content":{"29":{"position":[[442,5]]},"34":{"position":[[608,5]]},"38":{"position":[[1019,5]]},"39":{"position":[[135,6]]},"45":{"position":[[3368,5]]},"57":{"position":[[138,8]]},"83":{"position":[[605,5]]},"88":{"position":[[2161,6]]},"91":{"position":[[5869,6]]},"97":{"position":[[278,6]]},"98":{"position":[[948,6]]},"115":{"position":[[656,6]]},"125":{"position":[[1352,8]]},"128":{"position":[[1243,6],[1562,6]]},"129":{"position":[[406,6]]},"161":{"position":[[432,6]]}},"keywords":{}}],["again???"",{"_index":5085,"title":{},"content":{"179":{"position":[[1589,17]]}},"keywords":{}}],["against",{"_index":1609,"title":{},"content":{"34":{"position":[[1167,7]]},"38":{"position":[[577,7]]},"45":{"position":[[2713,7]]},"57":{"position":[[483,8]]},"112":{"position":[[430,8]]},"125":{"position":[[7806,7]]},"158":{"position":[[482,7]]}},"keywords":{}}],["agent",{"_index":911,"title":{},"content":{"22":{"position":[[846,6],[888,5]]},"93":{"position":[[2454,7]]}},"keywords":{}}],["agent"",{"_index":918,"title":{},"content":{"22":{"position":[[949,12],[2447,12]]}},"keywords":{}}],["aggreg",{"_index":4878,"title":{},"content":{"169":{"position":[[127,12],[144,11]]}},"keywords":{}}],["ago",{"_index":3957,"title":{},"content":{"122":{"position":[[1239,4]]}},"keywords":{}}],["agre",{"_index":2324,"title":{},"content":{"58":{"position":[[173,6]]},"193":{"position":[[625,5]]}},"keywords":{}}],["ahead",{"_index":309,"title":{},"content":{"6":{"position":[[95,5]]},"8":{"position":[[10,5]]},"15":{"position":[[562,5]]},"30":{"position":[[866,5]]},"43":{"position":[[197,5]]},"52":{"position":[[513,5]]},"57":{"position":[[637,5]]},"60":{"position":[[73,5]]},"103":{"position":[[377,5]]},"172":{"position":[[2116,5]]}},"keywords":{}}],["ala",{"_index":3856,"title":{},"content":{"120":{"position":[[664,5]]}},"keywords":{}}],["alac",{"_index":3472,"title":{},"content":{"101":{"position":[[379,5]]}},"keywords":{}}],["alchemi",{"_index":4645,"title":{},"content":{"160":{"position":[[11,7]]}},"keywords":{}}],["alejandro",{"_index":2958,"title":{},"content":{"89":{"position":[[918,9]]}},"keywords":{}}],["alert",{"_index":3806,"title":{},"content":{"116":{"position":[[871,6]]}},"keywords":{}}],["algebra",{"_index":2833,"title":{},"content":{"86":{"position":[[854,7]]}},"keywords":{}}],["algorithm",{"_index":697,"title":{"16":{"position":[[16,9]]},"51":{"position":[[4,10]]},"103":{"position":[[12,10]]}},"content":{"40":{"position":[[2509,9]]},"73":{"position":[[177,10],[295,10],[574,10]]},"75":{"position":[[83,10],[373,10],[1106,9]]},"76":{"position":[[1819,9]]},"83":{"position":[[82,9],[340,9]]},"85":{"position":[[20,9]]},"86":{"position":[[51,10],[151,10],[614,9],[763,9],[1038,9]]},"102":{"position":[[1094,10]]},"103":{"position":[[169,10],[789,9]]},"106":{"position":[[275,9]]},"172":{"position":[[465,10],[565,10]]}},"keywords":{}}],["alias",{"_index":2707,"title":{},"content":{"76":{"position":[[1406,8]]}},"keywords":{}}],["alive!"",{"_index":4082,"title":{},"content":{"125":{"position":[[3462,13]]}},"keywords":{}}],["all_word",{"_index":2096,"title":{},"content":{"51":{"position":[[1115,9],[2280,9]]}},"keywords":{}}],["all_words.count(h",{"_index":2129,"title":{},"content":{"51":{"position":[[2469,19]]}},"keywords":{}}],["all_words[i+1",{"_index":2107,"title":{},"content":{"51":{"position":[[1385,15]]}},"keywords":{}}],["allday",{"_index":2869,"title":{},"content":{"88":{"position":[[1222,7]]}},"keywords":{}}],["alloc",{"_index":4353,"title":{"133":{"position":[[22,10]]},"138":{"position":[[27,11]]},"139":{"position":[[7,11]]},"151":{"position":[[0,11]]},"154":{"position":[[0,11]]},"158":{"position":[[8,11]]},"159":{"position":[[0,11]]},"160":{"position":[[0,11]]},"177":{"position":[[0,11]]},"191":{"position":[[0,11]]}},"content":{"132":{"position":[[550,9],[609,9],[653,12],[828,10]]},"133":{"position":[[64,9]]},"135":{"position":[[266,9],[415,11],[482,11]]},"136":{"position":[[34,11],[126,11],[727,10],[900,11]]},"137":{"position":[[46,9]]},"139":{"position":[[33,11],[186,8],[514,10],[789,9],[889,11],[983,10]]},"140":{"position":[[244,9]]},"141":{"position":[[164,8],[269,12]]},"142":{"position":[[143,9]]},"143":{"position":[[63,10],[104,10],[579,10]]},"144":{"position":[[50,9]]},"145":{"position":[[187,11]]},"146":{"position":[[198,10],[311,10],[399,10]]},"147":{"position":[[532,10]]},"148":{"position":[[91,10],[136,9],[305,11]]},"152":{"position":[[114,11],[179,10],[514,8],[910,10]]},"155":{"position":[[469,9],[528,5],[849,11]]},"156":{"position":[[214,8],[493,8],[786,9],[955,8]]},"157":{"position":[[123,9],[262,11],[634,9],[720,11]]},"158":{"position":[[285,10]]},"159":{"position":[[250,9],[398,11],[562,11],[619,9],[824,10],[935,10],[951,11],[1001,8],[1081,8]]},"160":{"position":[[1669,5],[3487,10]]},"164":{"position":[[360,9],[467,8],[1033,9],[1373,8]]},"165":{"position":[[454,11]]},"166":{"position":[[866,10]]},"168":{"position":[[134,9]]},"172":{"position":[[275,10],[696,11],[831,9],[971,9],[1049,8],[1222,10]]},"193":{"position":[[1221,10],[2132,9],[2419,11]]},"194":{"position":[[134,10],[206,11],[694,11]]},"195":{"position":[[42,10],[504,8],[740,10]]},"196":{"position":[[1923,11]]},"197":{"position":[[265,9],[1548,10]]},"198":{"position":[[496,11],[798,9],[909,11]]},"199":{"position":[[533,9],[771,9],[826,9],[1055,11],[1332,10],[1629,8]]}},"keywords":{}}],["alloc(&self",{"_index":4530,"title":{},"content":{"152":{"position":[[1323,16]]},"156":{"position":[[1406,16]]}},"keywords":{}}],["alloc::string::tostring>::to_string@plt",{"_index":4289,"title":{},"content":{"129":{"position":[[633,42]]}},"keywords":{}}],["alloc_count",{"_index":4625,"title":{},"content":{"158":{"position":[[340,15]]}},"keywords":{}}],["allocate/dealloc",{"_index":4913,"title":{},"content":{"172":{"position":[[844,19]]}},"keywords":{}}],["allocated.cel",{"_index":4633,"title":{},"content":{"159":{"position":[[704,14]]}},"keywords":{}}],["allocated.inlin",{"_index":4634,"title":{},"content":{"159":{"position":[[777,18]]}},"keywords":{}}],["allocation."",{"_index":4533,"title":{},"content":{"152":{"position":[[1433,19]]},"156":{"position":[[1516,19]]}},"keywords":{}}],["allocation/drop",{"_index":4413,"title":{},"content":{"139":{"position":[[113,19]]}},"keywords":{}}],["allow",{"_index":377,"title":{},"content":{"7":{"position":[[67,6]]},"20":{"position":[[104,5]]},"45":{"position":[[1118,6]]},"61":{"position":[[112,5],[923,6]]},"73":{"position":[[640,6]]},"76":{"position":[[656,5],[2978,5]]},"95":{"position":[[134,6]]},"97":{"position":[[1386,6],[5264,6]]},"113":{"position":[[1102,5]]},"116":{"position":[[14,6]]},"117":{"position":[[121,6]]},"121":{"position":[[1292,7]]},"132":{"position":[[624,6]]},"141":{"position":[[99,5]]},"159":{"position":[[450,7]]},"173":{"position":[[565,7]]},"174":{"position":[[884,6]]},"179":{"position":[[508,6]]},"184":{"position":[[799,7]]},"186":{"position":[[41,8],[407,7]]},"188":{"position":[[700,7]]}},"keywords":{}}],["along",{"_index":2297,"title":{},"content":{"55":{"position":[[52,5]]},"112":{"position":[[1040,5]]},"150":{"position":[[625,5]]}},"keywords":{}}],["alpha",{"_index":876,"title":{"22":{"position":[[38,6]]}},"content":{},"keywords":{}}],["alpha=.5",{"_index":2999,"title":{},"content":{"90":{"position":[[1599,9],[1748,9],[2892,9]]}},"keywords":{}}],["alreadi",{"_index":977,"title":{},"content":{"22":{"position":[[2772,7]]},"30":{"position":[[9617,7]]},"43":{"position":[[184,7]]},"51":{"position":[[3483,7]]},"60":{"position":[[6,7]]},"93":{"position":[[1063,7]]},"122":{"position":[[343,7]]},"124":{"position":[[620,7]]},"125":{"position":[[1052,7],[1839,7],[2149,7]]},"137":{"position":[[97,7]]},"145":{"position":[[208,7]]},"163":{"position":[[605,7]]},"176":{"position":[[1055,7]]},"195":{"position":[[661,7]]}},"keywords":{}}],["alright",{"_index":2287,"title":{},"content":{"53":{"position":[[2227,8]]},"125":{"position":[[10065,8]]},"161":{"position":[[1581,8]]}},"keywords":{}}],["alsocaptur",{"_index":5328,"title":{},"content":{"196":{"position":[[336,11]]}},"keywords":{}}],["altern",{"_index":2624,"title":{"157":{"position":[[5,13]]}},"content":{"73":{"position":[[371,12]]},"112":{"position":[[711,12]]},"157":{"position":[[294,12],[404,12]]},"158":{"position":[[53,11]]},"172":{"position":[[1210,11]]},"174":{"position":[[820,12]]}},"keywords":{}}],["altogeth",{"_index":4996,"title":{},"content":{"174":{"position":[[1189,10]]}},"keywords":{}}],["alway",{"_index":1204,"title":{},"content":{"28":{"position":[[212,6]]},"172":{"position":[[1001,6]]},"198":{"position":[[873,6]]}},"keywords":{}}],["am/pm",{"_index":3890,"title":{},"content":{"121":{"position":[[994,5]]}},"keywords":{}}],["amaz",{"_index":3846,"title":{},"content":{"118":{"position":[[349,8]]}},"keywords":{}}],["ambiti",{"_index":3991,"title":{},"content":{"124":{"position":[[104,9]]}},"keywords":{}}],["amiss",{"_index":92,"title":{},"content":{"2":{"position":[[258,5]]}},"keywords":{}}],["amongst",{"_index":3560,"title":{},"content":{"104":{"position":[[780,7]]}},"keywords":{}}],["amor",{"_index":5006,"title":{},"content":{"175":{"position":[[355,5]]}},"keywords":{}}],["amount",{"_index":1525,"title":{},"content":{"32":{"position":[[592,6],[1178,6],[1292,6]]},"33":{"position":[[254,6]]},"61":{"position":[[437,6]]},"82":{"position":[[40,6]]},"86":{"position":[[1100,6]]},"101":{"position":[[164,6]]},"106":{"position":[[385,6]]},"125":{"position":[[3383,6]]},"140":{"position":[[120,6]]},"160":{"position":[[219,6],[2853,6]]},"188":{"position":[[1803,6]]}},"keywords":{}}],["amp",{"_index":778,"title":{},"content":{"20":{"position":[[590,5],[623,5],[650,5],[679,5],[718,5]]},"64":{"position":[[879,5]]},"65":{"position":[[1724,5]]},"70":{"position":[[309,5],[328,5],[347,5],[367,5],[387,5],[407,5],[443,5],[483,5],[503,5],[523,5],[543,5],[563,5],[582,5],[642,5]]},"71":{"position":[[409,5],[428,5],[448,5],[468,5],[488,5],[508,5],[543,5],[583,5],[602,5],[622,5],[642,5],[662,5],[682,5],[742,5]]},"74":{"position":[[602,5],[620,5],[641,5],[657,5],[679,5],[1098,6],[1699,6]]},"90":{"position":[[1970,5],[3109,5]]}},"keywords":{}}],["amp;&",{"_index":4078,"title":{},"content":{"125":{"position":[[3146,10],[5257,10],[5374,10],[5614,10],[5805,10],[5922,10]]}},"keywords":{}}],["amp;>",{"_index":1543,"title":{},"content":{"32":{"position":[[1630,9],[1693,9],[1776,9],[1834,9]]}},"keywords":{}}],["amp;'stat",{"_index":3340,"title":{},"content":{"96":{"position":[[1312,13]]}},"keywords":{}}],["amp;[u8",{"_index":4780,"title":{},"content":{"163":{"position":[[1773,10]]}},"keywords":{}}],["amp;[u8]>",{"_index":4782,"title":{},"content":{"163":{"position":[[1812,13]]}},"keywords":{}}],["amp;builder).unwrap",{"_index":3755,"title":{},"content":{"113":{"position":[[1715,23]]}},"keywords":{}}],["amp;cel",{"_index":5078,"title":{},"content":{"179":{"position":[[1054,11],[1155,11]]}},"keywords":{}}],["amp;dyn",{"_index":5346,"title":{},"content":{"197":{"position":[[634,10],[951,8]]}},"keywords":{}}],["amp;end",{"_index":5298,"title":{},"content":{"193":{"position":[[1950,10],[2905,10]]}},"keywords":{}}],["amp;hashmap<u32",{"_index":5385,"title":{},"content":{"199":{"position":[[1541,20]]}},"keywords":{}}],["amp;hashmap::new",{"_index":4392,"title":{},"content":{"136":{"position":[[448,20]]}},"keywords":{}}],["amp;middl",{"_index":5295,"title":{},"content":{"193":{"position":[[1900,13],[2855,13]]}},"keywords":{}}],["amp;mut",{"_index":3329,"title":{},"content":{"96":{"position":[[673,8],[1092,8],[1622,8],[2168,8]]},"97":{"position":[[1565,8],[3659,8],[4445,8],[4881,8]]},"113":{"position":[[1829,8]]},"115":{"position":[[284,8]]},"116":{"position":[[384,8]]},"117":{"position":[[1173,8]]},"144":{"position":[[189,8]]}},"keywords":{}}],["amp;point",{"_index":5280,"title":{},"content":{"193":{"position":[[1067,11],[1082,11],[2471,11],[2486,11],[3556,11],[3571,11]]}},"keywords":{}}],["amp;refcell<u8>",{"_index":5070,"title":{},"content":{"179":{"position":[[407,23],[927,23]]}},"keywords":{}}],["amp;self.messag",{"_index":3427,"title":{},"content":{"97":{"position":[[5661,17]]}},"keywords":{}}],["amp;str",{"_index":4387,"title":{},"content":{"136":{"position":[[285,9]]}},"keywords":{}}],["amp;vec<u32>",{"_index":5381,"title":{},"content":{"199":{"position":[[1249,20],[1392,20]]}},"keywords":{}}],["anafterthought",{"_index":4833,"title":{},"content":{"165":{"position":[[1102,15]]}},"keywords":{}}],["analysi",{"_index":57,"title":{},"content":{"1":{"position":[[642,8]]},"28":{"position":[[136,8],[450,8],[538,9]]},"29":{"position":[[56,9]]},"30":{"position":[[7751,8]]},"45":{"position":[[1103,9]]},"51":{"position":[[1479,8]]},"54":{"position":[[152,8]]},"62":{"position":[[1795,9]]},"65":{"position":[[2134,8]]},"66":{"position":[[453,8],[699,8]]},"91":{"position":[[3236,8]]},"92":{"position":[[31,9],[1048,8]]},"93":{"position":[[1121,8]]},"106":{"position":[[1027,8]]}},"keywords":{}}],["analyt",{"_index":1188,"title":{},"content":{"26":{"position":[[877,9]]}},"keywords":{}}],["analyz",{"_index":2288,"title":{},"content":{"54":{"position":[[66,7]]}},"keywords":{}}],["and_then",{"_index":4479,"title":{},"content":{"147":{"position":[[370,10]]}},"keywords":{}}],["andcach",{"_index":4920,"title":{},"content":{"172":{"position":[[1389,8]]}},"keywords":{}}],["andchar",{"_index":4278,"title":{},"content":{"129":{"position":[[259,7]]}},"keywords":{}}],["andcriterion",{"_index":4543,"title":{},"content":{"153":{"position":[[324,13]]}},"keywords":{}}],["andgap",{"_index":5024,"title":{},"content":{"175":{"position":[[1029,6]]}},"keywords":{}}],["andjavascriptboth",{"_index":5327,"title":{},"content":{"196":{"position":[[264,17]]}},"keywords":{}}],["andmor",{"_index":4826,"title":{},"content":{"165":{"position":[[295,7]]}},"keywords":{}}],["andmutex",{"_index":4608,"title":{},"content":{"157":{"position":[[381,10]]}},"keywords":{}}],["andnetwork",{"_index":4426,"title":{},"content":{"139":{"position":[[648,14]]}},"keywords":{}}],["andshenandoah",{"_index":4910,"title":{},"content":{"172":{"position":[[581,14]]}},"keywords":{}}],["andspin",{"_index":4610,"title":{},"content":{"157":{"position":[[457,8]]}},"keywords":{}}],["andspin::onc",{"_index":4612,"title":{},"content":{"157":{"position":[[517,13]]}},"keywords":{}}],["andstr",{"_index":4594,"title":{},"content":{"156":{"position":[[377,9]]}},"keywords":{}}],["andtim",{"_index":3853,"title":{},"content":{"120":{"position":[[497,8]]}},"keywords":{}}],["andtrait",{"_index":3397,"title":{},"content":{"97":{"position":[[2763,9]]}},"keywords":{}}],["anexampl",{"_index":4163,"title":{},"content":{"125":{"position":[[8368,9]]}},"keywords":{}}],["aninteg",{"_index":4241,"title":{},"content":{"127":{"position":[[1170,9]]}},"keywords":{}}],["anneal",{"_index":2620,"title":{"73":{"position":[[10,10]]},"75":{"position":[[25,10]]},"84":{"position":[[27,10]]},"85":{"position":[[14,11]]}},"content":{"73":{"position":[[285,9],[522,9],[630,9]]},"75":{"position":[[73,9]]},"78":{"position":[[366,9],[962,9]]},"79":{"position":[[166,9]]},"80":{"position":[[188,9]]},"81":{"position":[[167,9]]},"82":{"position":[[966,9]]},"85":{"position":[[64,10],[483,9]]},"86":{"position":[[391,9],[488,9]]}},"keywords":{}}],["annot",{"_index":5160,"title":{},"content":{"188":{"position":[[838,10],[4392,10]]},"189":{"position":[[988,10]]}},"keywords":{}}],["annotationassert",{"_index":5152,"title":{},"content":{"188":{"position":[[362,17]]}},"keywords":{}}],["announc",{"_index":3162,"title":{},"content":{"91":{"position":[[4578,9],[4751,12]]},"92":{"position":[[1398,12],[1449,13]]}},"keywords":{}}],["anoft",{"_index":3967,"title":{},"content":{"123":{"position":[[50,5]]}},"keywords":{}}],["anonym",{"_index":3376,"title":{},"content":{"97":{"position":[[1685,9],[4290,9],[4375,9],[6344,9]]},"196":{"position":[[15,9]]}},"keywords":{}}],["anoth",{"_index":1440,"title":{},"content":{"30":{"position":[[7959,7]]},"40":{"position":[[1465,7]]},"73":{"position":[[857,7]]},"89":{"position":[[101,8]]},"95":{"position":[[360,7]]},"97":{"position":[[1427,7],[1677,7],[4503,7],[4640,7],[5170,7],[5452,7]]},"105":{"position":[[363,7]]},"121":{"position":[[1607,7]]},"125":{"position":[[7062,7]]},"141":{"position":[[364,7]]},"193":{"position":[[180,7]]},"195":{"position":[[751,7]]},"196":{"position":[[799,7]]}},"keywords":{}}],["anownership",{"_index":4671,"title":{},"content":{"160":{"position":[[1097,11]]}},"keywords":{}}],["answer",{"_index":180,"title":{},"content":{"3":{"position":[[881,7]]},"44":{"position":[[1211,7]]},"112":{"position":[[449,6],[531,6]]},"125":{"position":[[608,6]]},"128":{"position":[[95,6]]},"150":{"position":[[932,7]]},"159":{"position":[[110,7]]},"193":{"position":[[245,7]]}},"keywords":{}}],["anti",{"_index":1899,"title":{},"content":{"44":{"position":[[163,4]]}},"keywords":{}}],["anymor",{"_index":2064,"title":{},"content":{"50":{"position":[[65,8]]}},"keywords":{}}],["anyon",{"_index":1837,"title":{},"content":{"40":{"position":[[3390,6]]},"50":{"position":[[183,6]]},"98":{"position":[[499,7]]},"104":{"position":[[1919,6]]},"120":{"position":[[1016,6]]},"125":{"position":[[3549,6]]}},"keywords":{}}],["anyone'sactu",{"_index":4020,"title":{},"content":{"125":{"position":[[573,14]]}},"keywords":{}}],["anyth",{"_index":1576,"title":{},"content":{"33":{"position":[[505,8]]},"51":{"position":[[3089,8]]},"125":{"position":[[2619,9],[10521,8]]},"153":{"position":[[124,9],[900,8]]}},"keywords":{}}],["anyway",{"_index":2669,"title":{},"content":{"75":{"position":[[898,8]]},"76":{"position":[[3009,8]]}},"keywords":{}}],["anywher",{"_index":2327,"title":{},"content":{"58":{"position":[[222,8]]},"181":{"position":[[559,9]]},"199":{"position":[[1221,9]]}},"keywords":{}}],["ap",{"_index":3474,"title":{},"content":{"101":{"position":[[404,6]]}},"keywords":{}}],["aper",{"_index":4855,"title":{},"content":{"168":{"position":[[24,4]]},"169":{"position":[[24,4]]}},"keywords":{}}],["api",{"_index":95,"title":{},"content":{"2":{"position":[[331,3],[532,4]]},"30":{"position":[[8742,3],[9507,4]]},"59":{"position":[[15,3]]},"97":{"position":[[2334,4]]},"117":{"position":[[26,3]]},"125":{"position":[[4436,3],[8755,4],[9689,4],[11142,3]]},"164":{"position":[[1347,3]]},"165":{"position":[[1198,4]]},"188":{"position":[[139,4]]},"189":{"position":[[554,3]]}},"keywords":{}}],["api'",{"_index":4703,"title":{},"content":{"160":{"position":[[3498,5]]}},"keywords":{}}],["api_key",{"_index":1601,"title":{},"content":{"34":{"position":[[1024,7]]},"39":{"position":[[535,7]]}},"keywords":{}}],["api_key=api_key",{"_index":1627,"title":{},"content":{"34":{"position":[[1683,16]]},"39":{"position":[[2245,16]]}},"keywords":{}}],["apikey",{"_index":1462,"title":{},"content":{"30":{"position":[[8712,6],[8891,6],[8985,6]]}},"keywords":{}}],["apion",{"_index":4209,"title":{},"content":{"125":{"position":[[11332,5]]}},"keywords":{}}],["apocalyps",{"_index":4497,"title":{},"content":{"150":{"position":[[481,11]]}},"keywords":{}}],["apolog",{"_index":4380,"title":{},"content":{"135":{"position":[[537,9]]}},"keywords":{}}],["app",{"_index":29,"title":{"125":{"position":[[19,4]]}},"content":{"1":{"position":[[326,3]]},"3":{"position":[[371,3],[407,3]]},"125":{"position":[[1472,3],[1479,3],[1730,5],[3578,4],[3833,3],[6224,4],[6263,3],[7026,3],[9739,3],[11526,3]]}},"keywords":{}}],["app"",{"_index":225,"title":{},"content":{"4":{"position":[[82,9]]}},"keywords":{}}],["appeal",{"_index":43,"title":{},"content":{"1":{"position":[[508,6]]}},"keywords":{}}],["appear",{"_index":1129,"title":{},"content":{"24":{"position":[[3201,7],[3269,7]]},"25":{"position":[[2618,7]]},"30":{"position":[[7453,7]]},"40":{"position":[[3410,7]]},"64":{"position":[[1955,6]]},"122":{"position":[[1264,7],[1393,7]]}},"keywords":{}}],["append",{"_index":1025,"title":{},"content":{"24":{"position":[[485,9]]},"25":{"position":[[210,9]]}},"keywords":{}}],["appendix",{"_index":1863,"title":{"47":{"position":[[0,9]]}},"content":{"43":{"position":[[250,8]]},"91":{"position":[[1832,8],[2736,8]]},"92":{"position":[[548,8]]},"93":{"position":[[1183,8]]}},"keywords":{}}],["appl",{"_index":2841,"title":{},"content":{"88":{"position":[[238,6],[2269,5],[3618,5]]},"89":{"position":[[267,5],[323,5]]},"105":{"position":[[3130,6],[3140,6]]},"172":{"position":[[2372,6]]}},"keywords":{}}],["appli",{"_index":1307,"title":{"32":{"position":[[0,8]]}},"content":{"28":{"position":[[4025,5]]},"32":{"position":[[195,5]]},"54":{"position":[[161,7]]},"96":{"position":[[1296,7]]},"97":{"position":[[5307,5]]},"105":{"position":[[937,7]]},"106":{"position":[[1060,7]]},"176":{"position":[[796,5]]}},"keywords":{}}],["applic",{"_index":118,"title":{"60":{"position":[[15,12]]}},"content":{"2":{"position":[[670,12]]},"3":{"position":[[615,11],[1063,11]]},"59":{"position":[[111,12]]},"60":{"position":[[36,11]]},"61":{"position":[[118,12],[230,12],[284,12],[383,12],[579,11],[704,11],[742,12],[853,12],[933,11],[1055,11],[1184,11]]},"97":{"position":[[756,12]]},"98":{"position":[[83,12],[808,13]]},"125":{"position":[[231,12],[2945,11],[2993,12],[6345,12],[10103,11],[10800,11]]},"134":{"position":[[133,12]]},"139":{"position":[[414,13]]},"160":{"position":[[2062,12],[2746,11]]},"173":{"position":[[1547,12]]},"174":{"position":[[454,12],[841,12]]},"190":{"position":[[474,12]]}},"keywords":{}}],["application/wasm",{"_index":4093,"title":{},"content":{"125":{"position":[[4313,16]]}},"keywords":{}}],["applicationus",{"_index":4102,"title":{},"content":{"125":{"position":[[4861,14]]}},"keywords":{}}],["approach",{"_index":1976,"title":{},"content":{"45":{"position":[[1044,8]]},"102":{"position":[[33,8]]},"132":{"position":[[331,8]]},"182":{"position":[[80,9]]}},"keywords":{}}],["appropri",{"_index":5264,"title":{},"content":{"190":{"position":[[957,12]]}},"keywords":{}}],["approx",{"_index":2475,"title":{},"content":{"64":{"position":[[1135,9]]}},"keywords":{}}],["approxim",{"_index":1665,"title":{},"content":{"34":{"position":[[3581,13]]},"57":{"position":[[64,13]]},"102":{"position":[[538,11],[793,13]]}},"keywords":{}}],["aprestart",{"_index":4133,"title":{},"content":{"125":{"position":[[6297,9]]}},"keywords":{}}],["apt",{"_index":3667,"title":{},"content":{"108":{"position":[[426,3]]}},"keywords":{}}],["arc::new(0",{"_index":4586,"title":{},"content":{"155":{"position":[[1511,12]]}},"keywords":{}}],["arcan",{"_index":4493,"title":{},"content":{"150":{"position":[[321,6]]}},"keywords":{}}],["area",{"_index":1438,"title":{},"content":{"30":{"position":[[7792,5],[7864,5]]},"90":{"position":[[5023,4]]},"91":{"position":[[4862,4]]},"125":{"position":[[1823,5]]},"130":{"position":[[375,5]]},"135":{"position":[[586,4]]}},"keywords":{}}],["arefresh",{"_index":4716,"title":{},"content":{"160":{"position":[[4054,10]]}},"keywords":{}}],["areher",{"_index":4854,"title":{},"content":{"167":{"position":[[152,8]]}},"keywords":{}}],["aren't",{"_index":286,"title":{},"content":{"4":{"position":[[1250,6]]},"33":{"position":[[346,6]]},"44":{"position":[[1852,6]]},"112":{"position":[[1023,6]]},"125":{"position":[[7337,6]]},"129":{"position":[[163,6]]},"152":{"position":[[126,6]]},"179":{"position":[[287,6]]},"184":{"position":[[868,6]]},"190":{"position":[[246,6],[780,6]]},"195":{"position":[[871,6]]},"197":{"position":[[1536,6]]}},"keywords":{}}],["arg",{"_index":933,"title":{},"content":{"22":{"position":[[1296,6]]},"93":{"position":[[1564,6]]},"127":{"position":[[627,5],[1277,5]]}},"keywords":{}}],["args=[n",{"_index":5181,"title":{},"content":{"188":{"position":[[2091,9],[2132,9],[2461,9],[2502,9],[2997,9],[3040,9]]},"189":{"position":[[2121,9],[2161,9],[2404,9],[2444,9],[2691,9],[2733,9]]}},"keywords":{}}],["argument",{"_index":3862,"title":{"193":{"position":[[9,10]]}},"content":{"120":{"position":[[853,8]]},"189":{"position":[[391,8],[459,8],[733,10]]},"193":{"position":[[398,9],[1303,10],[2016,9],[2968,10]]},"196":{"position":[[49,9],[400,9],[438,9]]}},"keywords":{}}],["arm",{"_index":4399,"title":{},"content":{"136":{"position":[[766,5]]}},"keywords":{}}],["around",{"_index":1806,"title":{},"content":{"40":{"position":[[1225,6],[1256,6],[1439,6],[2489,6]]},"117":{"position":[[2135,6]]},"128":{"position":[[963,6]]},"164":{"position":[[534,6],[1122,6]]},"165":{"position":[[852,6]]},"178":{"position":[[441,6]]},"189":{"position":[[2050,6]]},"193":{"position":[[385,6]]}},"keywords":{}}],["arrang",{"_index":4917,"title":{},"content":{"172":{"position":[[1341,8]]},"193":{"position":[[266,8]]}},"keywords":{}}],["array",{"_index":2690,"title":{"153":{"position":[[4,5]]},"195":{"position":[[0,7]]}},"content":{"76":{"position":[[578,5]]},"90":{"position":[[776,6],[1026,5],[2161,6],[2411,5]]},"159":{"position":[[669,7]]},"195":{"position":[[5,5],[70,5],[999,6]]}},"keywords":{}}],["array([0",{"_index":1874,"title":{},"content":{"43":{"position":[[621,9]]}},"keywords":{}}],["array.shape[1",{"_index":2982,"title":{},"content":{"90":{"position":[[986,15],[2371,15]]}},"keywords":{}}],["arriv",{"_index":3656,"title":{},"content":{"106":{"position":[[849,8]]}},"keywords":{}}],["arrowprops=dict(facecolor='black",{"_index":3049,"title":{},"content":{"90":{"position":[[4331,34]]}},"keywords":{}}],["arrowprops={'facecolor",{"_index":3054,"title":{},"content":{"90":{"position":[[4422,24],[4539,24],[4645,24]]}},"keywords":{}}],["art",{"_index":3858,"title":{},"content":{"120":{"position":[[702,3]]},"150":{"position":[[328,5]]}},"keywords":{}}],["articl",{"_index":881,"title":{},"content":{"22":{"position":[[65,7],[133,8],[220,8],[250,7],[282,8],[1142,8],[3012,8]]},"24":{"position":[[2483,8]]},"25":{"position":[[2206,8]]},"160":{"position":[[63,8]]}},"keywords":{}}],["article_data",{"_index":983,"title":{},"content":{"22":{"position":[[2908,12]]}},"keywords":{}}],["article_df",{"_index":986,"title":{},"content":{"22":{"position":[[3030,10]]},"23":{"position":[[222,10]]}},"keywords":{}}],["article_df.sort_values(by='date').iloc[0]['d",{"_index":1002,"title":{},"content":{"23":{"position":[[290,49]]}},"keywords":{}}],["article_html",{"_index":966,"title":{},"content":{"22":{"position":[[2389,12]]}},"keywords":{}}],["article_html.text",{"_index":973,"title":{},"content":{"22":{"position":[[2629,19]]}},"keywords":{}}],["article_list",{"_index":981,"title":{},"content":{"22":{"position":[[2866,12],[2960,13]]}},"keywords":{}}],["article_page_url",{"_index":905,"title":{},"content":{"22":{"position":[[681,17],[798,18]]}},"keywords":{}}],["articlelistpars",{"_index":921,"title":{},"content":{"22":{"position":[[997,19]]}},"keywords":{}}],["articlelistparser(htmlpars",{"_index":883,"title":{},"content":{"22":{"position":[[149,30]]}},"keywords":{}}],["articlereturnpars",{"_index":969,"title":{},"content":{"22":{"position":[[2495,21]]}},"keywords":{}}],["articlereturnparser(htmlpars",{"_index":924,"title":{},"content":{"22":{"position":[[1094,32]]}},"keywords":{}}],["articles_html",{"_index":915,"title":{},"content":{"22":{"position":[[894,13]]}},"keywords":{}}],["arust",{"_index":4062,"title":{},"content":{"125":{"position":[[2358,5]]}},"keywords":{}}],["ashot",{"_index":4354,"title":{},"content":{"132":{"position":[[774,6]]}},"keywords":{}}],["asid",{"_index":5242,"title":{},"content":{"189":{"position":[[1833,6]]}},"keywords":{}}],["ask",{"_index":1933,"title":{},"content":{"44":{"position":[[1246,5]]},"66":{"position":[[708,4]]},"93":{"position":[[986,3]]},"108":{"position":[[161,3]]},"123":{"position":[[344,3]]}},"keywords":{}}],["asm",{"_index":4719,"title":{},"content":{"160":{"position":[[4201,5]]}},"keywords":{}}],["asm.j",{"_index":4064,"title":{},"content":{"125":{"position":[[2540,6]]}},"keywords":{}}],["aspeci",{"_index":4806,"title":{},"content":{"164":{"position":[[551,8]]}},"keywords":{}}],["assembl",{"_index":4247,"title":{},"content":{"128":{"position":[[71,8],[365,8],[1182,8],[1645,8],[1692,9]]},"129":{"position":[[353,9],[480,9],[747,8]]},"130":{"position":[[566,9]]},"152":{"position":[[669,8]]},"155":{"position":[[1368,8],[1430,8],[1492,8],[1555,8]]},"156":{"position":[[563,8]]},"159":{"position":[[207,9]]},"160":{"position":[[3999,8]]},"163":{"position":[[714,8]]},"181":{"position":[[145,8],[267,8],[609,8]]},"183":{"position":[[370,8],[516,8],[723,8]]},"192":{"position":[[671,9]]},"193":{"position":[[286,8],[992,8],[2188,8],[2296,8],[3105,9]]},"194":{"position":[[760,9]]},"196":{"position":[[711,8],[1013,8],[1223,8],[1634,8],[1836,8]]},"197":{"position":[[799,9],[980,9]]},"199":{"position":[[1119,8]]}},"keywords":{}}],["assert",{"_index":5224,"title":{},"content":{"188":{"position":[[4406,6]]}},"keywords":{}}],["assert_eq!(boxed_reader.get_i",{"_index":3804,"title":{},"content":{"116":{"position":[[793,32]]}},"keywords":{}}],["assert_eq!(boxed_reader.get_x",{"_index":3803,"title":{},"content":{"116":{"position":[[755,32]]}},"keywords":{}}],["assert_eq!(point_reader.get_i",{"_index":3764,"title":{},"content":{"113":{"position":[[2368,32]]},"115":{"position":[[773,32]]}},"keywords":{}}],["assert_eq!(point_reader.get_x",{"_index":3763,"title":{},"content":{"113":{"position":[[2330,32]]},"115":{"position":[[735,32]]}},"keywords":{}}],["assert_eq!(point_root.get_i",{"_index":3835,"title":{},"content":{"117":{"position":[[1815,30]]}},"keywords":{}}],["assert_eq!(point_root.get_x",{"_index":3834,"title":{},"content":{"117":{"position":[[1779,30]]}},"keywords":{}}],["assert_no_alloc",{"_index":4462,"title":{},"content":{"145":{"position":[[410,18]]},"147":{"position":[[577,18]]}},"keywords":{}}],["assert_no_alloc!(async_capac",{"_index":4480,"title":{},"content":{"147":{"position":[[465,35]]}},"keywords":{}}],["assert_no_alloc!(async_capacity().poll().unwrap",{"_index":4481,"title":{},"content":{"147":{"position":[[602,51]]}},"keywords":{}}],["assert_no_alloc!(v.push(5",{"_index":4458,"title":{},"content":{"145":{"position":[[236,28]]}},"keywords":{}}],["asset",{"_index":172,"title":{},"content":{"3":{"position":[[771,5]]},"6":{"position":[[78,7]]},"38":{"position":[[325,7]]}},"keywords":{}}],["assign",{"_index":4260,"title":{},"content":{"128":{"position":[[486,6]]},"129":{"position":[[2580,6]]},"198":{"position":[[836,11]]}},"keywords":{}}],["associ",{"_index":4664,"title":{},"content":{"160":{"position":[[706,10]]},"174":{"position":[[236,10],[570,10]]},"197":{"position":[[169,10]]}},"keywords":{}}],["assum",{"_index":459,"title":{},"content":{"9":{"position":[[126,6],[381,7],[589,7]]},"10":{"position":[[365,8]]},"14":{"position":[[596,6]]},"30":{"position":[[1098,6],[2697,6],[7846,6]]},"33":{"position":[[1201,9]]},"34":{"position":[[393,7],[501,8],[3641,6]]},"46":{"position":[[516,8]]},"90":{"position":[[786,6],[2171,6]]},"91":{"position":[[2575,7],[3892,6]]},"92":{"position":[[387,7]]},"97":{"position":[[3126,8]]},"105":{"position":[[534,6],[706,6]]},"110":{"position":[[270,8]]},"112":{"position":[[617,8]]},"115":{"position":[[124,9]]},"116":{"position":[[224,9]]},"117":{"position":[[1016,9]]},"134":{"position":[[1,8]]},"160":{"position":[[3537,6]]},"193":{"position":[[809,6]]}},"keywords":{}}],["assumpt",{"_index":2745,"title":{},"content":{"77":{"position":[[142,10]]},"116":{"position":[[2878,11]]}},"keywords":{}}],["assur",{"_index":2576,"title":{},"content":{"69":{"position":[[153,9]]}},"keywords":{}}],["astro",{"_index":197,"title":{},"content":{"3":{"position":[[1197,5]]}},"keywords":{}}],["aswebassembl",{"_index":4011,"title":{},"content":{"125":{"position":[[257,13]]}},"keywords":{}}],["async_capac",{"_index":4474,"title":{},"content":{"147":{"position":[[192,16],[429,17]]}},"keywords":{}}],["asynchron",{"_index":4471,"title":{},"content":{"147":{"position":[[98,12]]}},"keywords":{}}],["at.w",{"_index":3710,"title":{},"content":{"111":{"position":[[746,5]]}},"keywords":{}}],["atcrates.io",{"_index":4484,"title":{},"content":{"148":{"position":[[379,11]]}},"keywords":{}}],["athena",{"_index":540,"title":{"13":{"position":[[0,6]]}},"content":{"13":{"position":[[83,6],[96,6],[1261,6],[1529,8],[1860,6],[2262,6]]},"14":{"position":[[76,6]]}},"keywords":{}}],["athread_loc",{"_index":4615,"title":{},"content":{"157":{"position":[[680,14]]}},"keywords":{}}],["atomicbool",{"_index":4527,"title":{},"content":{"152":{"position":[[1208,10]]},"156":{"position":[[1291,10]]}},"keywords":{}}],["atomicbool::new(fals",{"_index":4528,"title":{},"content":{"152":{"position":[[1221,23]]},"156":{"position":[[1304,23]]}},"keywords":{}}],["attack",{"_index":3352,"title":{},"content":{"96":{"position":[[2102,7]]}},"keywords":{}}],["attempt",{"_index":164,"title":{"78":{"position":[[0,7]]},"79":{"position":[[0,7]]},"80":{"position":[[0,7]]},"81":{"position":[[0,7]]},"82":{"position":[[0,7]]},"115":{"position":[[0,7]]},"116":{"position":[[0,7]]},"117":{"position":[[0,7]]}},"content":{"3":{"position":[[591,10],[922,8]]},"44":{"position":[[10,7]]},"45":{"position":[[2758,7]]},"97":{"position":[[2674,8],[3944,7],[4087,9],[5334,7]]},"104":{"position":[[616,8]]},"115":{"position":[[12,8]]},"116":{"position":[[173,7]]},"117":{"position":[[206,9]]},"118":{"position":[[258,8]]},"121":{"position":[[325,9]]},"125":{"position":[[2915,10],[4136,10],[8213,10],[10479,8]]},"160":{"position":[[434,8]]},"165":{"position":[[48,7]]},"176":{"position":[[782,10]]},"188":{"position":[[3381,10],[3491,10]]}},"keywords":{}}],["attent",{"_index":3789,"title":{},"content":{"115":{"position":[[2594,9]]},"132":{"position":[[266,9]]},"161":{"position":[[693,9]]},"176":{"position":[[106,9]]}},"keywords":{}}],["attr",{"_index":889,"title":{},"content":{"22":{"position":[[327,7],[413,6],[503,6],[1394,7],[1456,6]]},"93":{"position":[[1663,7]]}},"keywords":{}}],["attribut",{"_index":676,"title":{},"content":{"15":{"position":[[694,9]]},"133":{"position":[[203,10]]},"152":{"position":[[250,10]]},"175":{"position":[[695,10]]},"193":{"position":[[2104,10]]}},"keywords":{}}],["attrs))[0][1",{"_index":899,"title":{},"content":{"22":{"position":[[555,13],[1518,13]]}},"keywords":{}}],["audienc",{"_index":3390,"title":{},"content":{"97":{"position":[[2187,8],[5884,8]]}},"keywords":{}}],["audio",{"_index":83,"title":{"99":{"position":[[4,5]]},"101":{"position":[[24,5]]}},"content":{"2":{"position":[[132,5],[170,5],[317,5],[808,5]]},"3":{"position":[[988,5],[1371,5]]},"100":{"position":[[35,5],[456,5]]},"101":{"position":[[1,5],[398,5],[1109,5]]},"102":{"position":[[54,6]]},"103":{"position":[[5,5],[99,5],[470,5],[2003,5],[2198,5]]},"104":{"position":[[312,6],[1844,5]]},"105":{"position":[[84,5],[338,5]]},"106":{"position":[[27,5],[395,5],[546,5]]}},"keywords":{}}],["audio(data=reconstructed[start:end",{"_index":3540,"title":{},"content":{"103":{"position":[[1790,36],[2107,36]]},"105":{"position":[[2744,36],[2942,36],[3217,36]]}},"keywords":{}}],["audio(data=tabulasa[start:end",{"_index":3518,"title":{},"content":{"103":{"position":[[647,30]]}},"keywords":{}}],["audio,self",{"_index":4424,"title":{},"content":{"139":{"position":[[623,10]]}},"keywords":{}}],["august",{"_index":1261,"title":{},"content":{"28":{"position":[[1903,10],[4215,7]]},"30":{"position":[[1033,6],[1416,9]]},"40":{"position":[[1243,6],[2496,6],[3176,7]]}},"keywords":{}}],["authent",{"_index":2342,"title":{},"content":{"59":{"position":[[124,14]]},"61":{"position":[[1485,13]]}},"keywords":{}}],["author",{"_index":2390,"title":{},"content":{"61":{"position":[[2287,14]]},"74":{"position":[[930,6]]},"76":{"position":[[287,7]]},"97":{"position":[[507,6]]},"109":{"position":[[314,7]]},"142":{"position":[[204,7]]},"166":{"position":[[34,6]]}},"keywords":{}}],["authtoken=quandl_key",{"_index":2859,"title":{},"content":{"88":{"position":[[880,21]]},"93":{"position":[[4295,21]]}},"keywords":{}}],["auto",{"_index":3712,"title":{},"content":{"112":{"position":[[106,4]]}},"keywords":{}}],["autocal",{"_index":301,"title":{"5":{"position":[[0,12]]}},"content":{"6":{"position":[[23,12]]},"12":{"position":[[103,12]]}},"keywords":{}}],["autom",{"_index":3962,"title":{},"content":{"122":{"position":[[1437,10]]},"139":{"position":[[260,9]]}},"keywords":{}}],["automat",{"_index":542,"title":{},"content":{"13":{"position":[[139,13]]},"14":{"position":[[294,13]]},"75":{"position":[[714,13]]},"76":{"position":[[2833,13]]},"90":{"position":[[3432,13]]},"185":{"position":[[226,13]]}},"keywords":{}}],["avail",{"_index":2340,"title":{},"content":{"59":{"position":[[19,9]]},"62":{"position":[[1709,9]]},"97":{"position":[[2923,9]]},"108":{"position":[[621,10]]},"112":{"position":[[750,10],[1690,9]]},"122":{"position":[[783,10]]},"142":{"position":[[114,10]]},"155":{"position":[[511,9]]},"157":{"position":[[307,10]]},"160":{"position":[[1483,10],[1913,10],[3921,9],[4222,10]]},"161":{"position":[[105,10]]},"175":{"position":[[380,10]]},"176":{"position":[[227,10]]}},"keywords":{}}],["availableov",{"_index":4070,"title":{},"content":{"125":{"position":[[2780,13]]}},"keywords":{}}],["averag",{"_index":739,"title":{},"content":{"19":{"position":[[56,7],[114,7]]},"20":{"position":[[820,7]]},"28":{"position":[[662,7],[2101,7],[2639,7],[2698,7],[2853,7],[3756,7],[4357,7]]},"29":{"position":[[90,7],[114,7]]},"30":{"position":[[988,7],[2078,7],[2321,7],[2389,7],[2897,7],[4040,7],[4518,7],[5328,7],[5558,7],[5876,7],[7369,9]]},"43":{"position":[[1311,7]]},"64":{"position":[[1241,7]]},"91":{"position":[[4614,8],[5428,8]]},"167":{"position":[[192,7]]},"176":{"position":[[1260,7]]}},"keywords":{}}],["avoid",{"_index":4398,"title":{},"content":{"136":{"position":[[721,5]]},"157":{"position":[[256,5]]},"160":{"position":[[3848,5]]},"172":{"position":[[2356,5]]},"175":{"position":[[976,6]]},"188":{"position":[[4045,8]]},"189":{"position":[[536,5]]}},"keywords":{}}],["awar",{"_index":1375,"title":{},"content":{"30":{"position":[[2557,5]]},"150":{"position":[[825,5]]},"179":{"position":[[1792,5]]},"188":{"position":[[3370,5]]}},"keywords":{}}],["away",{"_index":3315,"title":{},"content":{"96":{"position":[[56,4]]},"97":{"position":[[5444,4],[5639,4],[5800,4]]},"98":{"position":[[911,4]]},"121":{"position":[[383,6]]},"122":{"position":[[399,4]]},"125":{"position":[[10900,5]]},"185":{"position":[[398,4]]}},"keywords":{}}],["awesom",{"_index":2215,"title":{},"content":{"53":{"position":[[509,8]]},"175":{"position":[[591,8]]}},"keywords":{}}],["awesome"",{"_index":238,"title":{},"content":{"4":{"position":[[370,15]]}},"keywords":{}}],["ax",{"_index":2863,"title":{},"content":{"88":{"position":[[1059,2],[1074,2],[1407,2],[1484,2],[1813,2]]}},"keywords":{}}],["ax.get_ylim()[0",{"_index":2880,"title":{},"content":{"88":{"position":[[1558,17],[1885,17]]}},"keywords":{}}],["ax.get_ylim()[1",{"_index":2881,"title":{},"content":{"88":{"position":[[1576,17],[1903,17]]}},"keywords":{}}],["ax.plot([date2num(start",{"_index":2907,"title":{},"content":{"88":{"position":[[2475,25],[2578,25]]}},"keywords":{}}],["ax.xaxis.set_major_formatter(weekformatt",{"_index":2874,"title":{},"content":{"88":{"position":[[1356,43]]}},"keywords":{}}],["ax.xaxis.set_major_locator(monday",{"_index":2872,"title":{},"content":{"88":{"position":[[1284,35]]}},"keywords":{}}],["ax.xaxis.set_minor_locator(allday",{"_index":2873,"title":{},"content":{"88":{"position":[[1320,35]]}},"keywords":{}}],["ax=ax_aapl",{"_index":2920,"title":{},"content":{"88":{"position":[[2800,11]]}},"keywords":{}}],["ax=ax_fb",{"_index":2930,"title":{},"content":{"88":{"position":[[3201,9]]}},"keywords":{}}],["ax=non",{"_index":2861,"title":{},"content":{"88":{"position":[[946,9]]}},"keywords":{}}],["ax_aapl",{"_index":2915,"title":{},"content":{"88":{"position":[[2709,7]]}},"keywords":{}}],["ax_aapl.get_ylim()[0",{"_index":2925,"title":{},"content":{"88":{"position":[[3005,22]]},"91":{"position":[[1236,22]]}},"keywords":{}}],["ax_aapl.get_ylim()[1",{"_index":2926,"title":{},"content":{"88":{"position":[[3028,22]]},"91":{"position":[[1259,22]]}},"keywords":{}}],["ax_aapl.legend(loc=2",{"_index":2928,"title":{},"content":{"88":{"position":[[3088,21]]}},"keywords":{}}],["ax_aapl.set_title('aapl",{"_index":2929,"title":{},"content":{"88":{"position":[[3110,23]]}},"keywords":{}}],["ax_aapl.vlines(date2num(datetime(2016",{"_index":2924,"title":{},"content":{"88":{"position":[[2953,38]]}},"keywords":{}}],["ax_fb",{"_index":2917,"title":{},"content":{"88":{"position":[[2728,5]]}},"keywords":{}}],["ax_fb.get_ylim()[0",{"_index":2933,"title":{},"content":{"88":{"position":[[3394,20]]},"91":{"position":[[770,20]]}},"keywords":{}}],["ax_fb.get_ylim()[1",{"_index":2934,"title":{},"content":{"88":{"position":[[3415,20]]},"91":{"position":[[791,20]]}},"keywords":{}}],["ax_fb.legend(loc=2",{"_index":2935,"title":{},"content":{"88":{"position":[[3473,19]]}},"keywords":{}}],["ax_fb.set_title('fb",{"_index":2936,"title":{},"content":{"88":{"position":[[3493,19]]}},"keywords":{}}],["ax_fb.vlines(date2num(datetime(2016",{"_index":2932,"title":{},"content":{"88":{"position":[[3344,36]]}},"keywords":{}}],["axarr",{"_index":2913,"title":{},"content":{"88":{"position":[[2682,5]]},"90":{"position":[[1313,5]]},"91":{"position":[[411,5]]}},"keywords":{}}],["axarr[0",{"_index":2916,"title":{},"content":{"88":{"position":[[2719,8]]},"91":{"position":[[473,8]]}},"keywords":{}}],["axarr[0].errorbar(range(1",{"_index":3006,"title":{},"content":{"90":{"position":[[1871,26]]}},"keywords":{}}],["axarr[0].fill_between(range(0",{"_index":2998,"title":{},"content":{"90":{"position":[[1492,30]]}},"keywords":{}}],["axarr[0].legend(loc=2",{"_index":3009,"title":{},"content":{"90":{"position":[[1982,22]]}},"keywords":{}}],["axarr[0].plot(range(range_begin",{"_index":2996,"title":{},"content":{"90":{"position":[[1388,32]]}},"keywords":{}}],["axarr[0].set_xlim",{"_index":3011,"title":{},"content":{"90":{"position":[[2028,19]]}},"keywords":{}}],["axarr[1",{"_index":2918,"title":{},"content":{"88":{"position":[[2736,8]]},"91":{"position":[[921,8]]}},"keywords":{}}],["axarr[1].fill_between(range(0",{"_index":3002,"title":{},"content":{"90":{"position":[[1641,30]]}},"keywords":{}}],["axarr[1].legend(loc=2",{"_index":3010,"title":{},"content":{"90":{"position":[[2005,22]]}},"keywords":{}}],["axarr[1].plot(range(range_begin",{"_index":2997,"title":{},"content":{"90":{"position":[[1440,32]]}},"keywords":{}}],["axarr[1].set_xlim",{"_index":3013,"title":{},"content":{"90":{"position":[[2073,19]]}},"keywords":{}}],["axis=1",{"_index":1781,"title":{},"content":{"39":{"position":[[3336,7]]},"40":{"position":[[252,7],[421,7],[1786,7],[1957,7],[2729,7],[2901,7]]},"90":{"position":[[1002,7],[2387,7]]}},"keywords":{}}],["b",{"_index":3592,"title":{},"content":{"105":{"position":[[1048,4]]},"175":{"position":[[171,1]]},"188":{"position":[[1072,1],[1093,1],[1122,1],[1124,1],[1138,1]]},"189":{"position":[[1141,1],[1155,1],[1184,1],[1186,1],[1200,1],[1411,1],[1425,1],[1454,1],[1456,1],[1470,1]]},"192":{"position":[[172,2],[547,2]]},"193":{"position":[[1079,2],[2483,2],[3259,2],[3568,2]]},"197":{"position":[[1346,1]]}},"keywords":{}}],["b.i",{"_index":5287,"title":{},"content":{"193":{"position":[[1381,4],[2561,4],[2624,4],[2638,5],[3332,4],[3646,4]]}},"keywords":{}}],["b.x",{"_index":5283,"title":{},"content":{"193":{"position":[[1353,4],[2533,4],[2585,4],[2599,5],[3304,4],[3618,4]]}},"keywords":{}}],["b_class",{"_index":1902,"title":{},"content":{"44":{"position":[[222,7]]}},"keywords":{}}],["b_class.append(c",{"_index":1905,"title":{},"content":{"44":{"position":[[278,17]]}},"keywords":{}}],["babel",{"_index":4025,"title":{},"content":{"125":{"position":[[764,5],[6728,5]]}},"keywords":{}}],["back",{"_index":1583,"title":{},"content":{"33":{"position":[[1016,4],[1238,4]]},"53":{"position":[[1119,5]]},"61":{"position":[[1932,4],[2220,4]]},"64":{"position":[[219,4],[1187,4]]},"82":{"position":[[101,4]]},"83":{"position":[[205,4]]},"96":{"position":[[915,4]]},"100":{"position":[[361,4]]},"113":{"position":[[2151,4],[2299,5]]},"115":{"position":[[920,5]]},"120":{"position":[[969,4]]},"123":{"position":[[450,4]]},"137":{"position":[[242,4]]},"156":{"position":[[1110,4]]},"163":{"position":[[151,5]]},"173":{"position":[[1229,4]]},"193":{"position":[[225,4],[1653,4]]}},"keywords":{}}],["backdidn't",{"_index":3322,"title":{},"content":{"96":{"position":[[357,10]]}},"keywords":{}}],["background",{"_index":88,"title":{},"content":{"2":{"position":[[201,10]]},"61":{"position":[[2136,11]]}},"keywords":{}}],["backtest",{"_index":1671,"title":{},"content":{"35":{"position":[[327,9]]},"39":{"position":[[38,9]]}},"keywords":{}}],["backward",{"_index":2450,"title":{},"content":{"64":{"position":[[117,8]]}},"keywords":{}}],["bad",{"_index":1120,"title":{},"content":{"24":{"position":[[2972,3]]},"96":{"position":[[164,3],[815,3]]},"97":{"position":[[6120,4]]},"125":{"position":[[5007,3]]}},"keywords":{}}],["bake",{"_index":4733,"title":{},"content":{"161":{"position":[[412,6],[992,4]]}},"keywords":{}}],["balanc",{"_index":3985,"title":{},"content":{"123":{"position":[[859,7]]}},"keywords":{}}],["ball",{"_index":1561,"title":{},"content":{"32":{"position":[[2281,4]]}},"keywords":{}}],["band",{"_index":1411,"title":{},"content":{"30":{"position":[[5631,4]]}},"keywords":{}}],["bank",{"_index":2035,"title":{},"content":{"46":{"position":[[494,4]]},"53":{"position":[[1762,7]]},"54":{"position":[[199,4]]},"121":{"position":[[34,4]]}},"keywords":{}}],["bar",{"_index":3069,"title":{},"content":{"90":{"position":[[5231,4]]},"91":{"position":[[4834,4]]},"92":{"position":[[1497,4]]}},"keywords":{}}],["barrier",{"_index":544,"title":{},"content":{"13":{"position":[[196,7],[278,7],[433,7],[487,7]]},"14":{"position":[[141,7],[351,7],[421,7],[486,7],[540,7],[615,7],[656,7],[739,8],[885,8],[911,8],[996,8],[1076,8],[1250,8],[1270,8]]},"15":{"position":[[266,8],[316,8],[336,8]]}},"keywords":{}}],["bar{\\lambda",{"_index":2119,"title":{},"content":{"51":{"position":[[2067,18]]}},"keywords":{}}],["base",{"_index":360,"title":{"102":{"position":[[6,5]]}},"content":{"6":{"position":[[887,5]]},"58":{"position":[[512,5],[717,5],[791,5]]},"65":{"position":[[2318,4],[2431,4]]},"75":{"position":[[438,5]]},"89":{"position":[[338,5]]},"125":{"position":[[3246,4]]},"157":{"position":[[160,5],[398,5]]}},"keywords":{}}],["base_url",{"_index":901,"title":{},"content":{"22":{"position":[[596,8],[701,10],[714,9]]},"93":{"position":[[2474,8]]}},"keywords":{}}],["baselin",{"_index":4510,"title":{},"content":{"152":{"position":[[347,8]]}},"keywords":{}}],["basi",{"_index":314,"title":{},"content":{"6":{"position":[[221,5]]},"160":{"position":[[161,6]]},"168":{"position":[[37,6]]},"169":{"position":[[37,6]]}},"keywords":{}}],["basic",{"_index":455,"title":{"110":{"position":[[18,5]]}},"content":{"9":{"position":[[24,5]]},"110":{"position":[[167,5]]},"117":{"position":[[2089,5]]},"169":{"position":[[121,5]]},"199":{"position":[[1290,5]]}},"keywords":{}}],["bassdriv",{"_index":3306,"title":{},"content":{"95":{"position":[[191,10]]}},"keywords":{}}],["basslin",{"_index":3548,"title":{},"content":{"103":{"position":[[2330,8]]},"104":{"position":[[449,9],[1284,9]]}},"keywords":{}}],["batch",{"_index":513,"title":{},"content":{"11":{"position":[[317,7]]}},"keywords":{}}],["bay",{"_index":1979,"title":{},"content":{"45":{"position":[[1247,5],[1668,5]]}},"keywords":{}}],["be",{"_index":635,"title":{},"content":{"14":{"position":[[822,5]]},"22":{"position":[[2751,5]]},"28":{"position":[[289,5],[838,5]]},"33":{"position":[[162,5]]},"36":{"position":[[44,5]]},"40":{"position":[[1496,5]]},"45":{"position":[[787,5],[960,5]]},"53":{"position":[[1636,5],[1785,5]]},"93":{"position":[[1914,5]]},"97":{"position":[[2555,5],[3249,5]]},"113":{"position":[[424,5]]},"122":{"position":[[239,5]]},"123":{"position":[[44,5]]},"125":{"position":[[11307,5]]},"132":{"position":[[298,5]]},"160":{"position":[[3980,5]]},"172":{"position":[[1888,5]]},"176":{"position":[[1139,5]]},"181":{"position":[[939,5]]},"182":{"position":[[547,5]]},"190":{"position":[[715,5]]},"197":{"position":[[199,5]]}},"keywords":{}}],["be.randomli",{"_index":2135,"title":{},"content":{"51":{"position":[[2879,11]]}},"keywords":{}}],["bear",{"_index":1168,"title":{},"content":{"26":{"position":[[10,5]]},"46":{"position":[[147,7]]},"93":{"position":[[145,7]]}},"keywords":{}}],["bearer",{"_index":2406,"title":{},"content":{"62":{"position":[[534,8]]}},"keywords":{}}],["beat",{"_index":2020,"title":{},"content":{"45":{"position":[[2587,4]]},"46":{"position":[[454,4]]},"57":{"position":[[687,6]]},"58":{"position":[[551,5],[636,5]]},"65":{"position":[[49,5],[1320,5]]},"76":{"position":[[2812,5],[2950,4]]}},"keywords":{}}],["beaten",{"_index":2331,"title":{},"content":{"58":{"position":[[318,6]]},"64":{"position":[[1980,6]]}},"keywords":{}}],["becauserefcel",{"_index":5129,"title":{},"content":{"184":{"position":[[933,14]]}},"keywords":{}}],["becom",{"_index":1392,"title":{},"content":{"30":{"position":[[4076,8]]},"53":{"position":[[312,8]]},"103":{"position":[[2024,6]]},"115":{"position":[[2938,8]]},"125":{"position":[[11020,6]]}},"keywords":{}}],["befor",{"_index":79,"title":{},"content":{"2":{"position":[[71,6]]},"24":{"position":[[145,7],[397,6]]},"26":{"position":[[189,6]]},"38":{"position":[[1313,6]]},"44":{"position":[[1257,6]]},"53":{"position":[[1074,6]]},"54":{"position":[[283,6]]},"55":{"position":[[192,7]]},"58":{"position":[[99,6]]},"65":{"position":[[2567,6]]},"89":{"position":[[605,6],[862,6]]},"90":{"position":[[1,6]]},"91":{"position":[[2676,6],[4764,6],[5080,6]]},"92":{"position":[[488,6]]},"93":{"position":[[337,6],[1870,6],[1940,7],[2118,7]]},"106":{"position":[[1068,7]]},"115":{"position":[[2989,6]]},"116":{"position":[[2823,6]]},"125":{"position":[[739,6],[10990,6]]},"127":{"position":[[943,6]]},"150":{"position":[[463,6]]},"160":{"position":[[2734,6],[3379,6]]},"163":{"position":[[331,6]]},"164":{"position":[[999,6]]},"165":{"position":[[904,6]]},"175":{"position":[[1398,6]]},"176":{"position":[[775,6]]},"189":{"position":[[303,6]]},"190":{"position":[[1,6]]}},"keywords":{}}],["began",{"_index":76,"title":{},"content":{"2":{"position":[[32,5]]},"122":{"position":[[537,5]]}},"keywords":{}}],["begin",{"_index":1526,"title":{},"content":{"32":{"position":[[633,9]]},"33":{"position":[[1295,9]]},"75":{"position":[[1076,5]]},"115":{"position":[[3169,6]]},"128":{"position":[[118,5]]},"166":{"position":[[582,10]]},"175":{"position":[[1524,5]]}},"keywords":{}}],["beginn",{"_index":4054,"title":{},"content":{"125":{"position":[[1806,8]]}},"keywords":{}}],["begin{array}{cc",{"_index":2579,"title":{},"content":{"70":{"position":[[257,17]]},"71":{"position":[[357,17]]}},"keywords":{}}],["begin{array}{lr",{"_index":2581,"title":{},"content":{"70":{"position":[[289,17],[463,17]]},"71":{"position":[[389,17],[563,17]]},"74":{"position":[[580,17]]}},"keywords":{}}],["behav",{"_index":3902,"title":{},"content":{"121":{"position":[[1505,7]]},"142":{"position":[[249,6]]},"155":{"position":[[808,6]]},"159":{"position":[[735,6]]},"182":{"position":[[302,6]]}},"keywords":{}}],["behavior",{"_index":4416,"title":{},"content":{"139":{"position":[[286,9]]},"153":{"position":[[70,9]]},"156":{"position":[[1806,9]]},"158":{"position":[[387,9]]},"159":{"position":[[333,8],[835,8]]},"172":{"position":[[1159,8]]},"175":{"position":[[1156,9]]},"179":{"position":[[1693,8]]},"189":{"position":[[186,8]]},"198":{"position":[[612,8],[962,9]]}},"keywords":{}}],["behind",{"_index":1536,"title":{},"content":{"32":{"position":[[1055,6]]}},"keywords":{}}],["believ",{"_index":262,"title":{},"content":{"4":{"position":[[817,7]]},"101":{"position":[[930,7]]},"102":{"position":[[364,7]]},"129":{"position":[[230,7]]},"165":{"position":[[980,7]]},"176":{"position":[[1406,7]]}},"keywords":{}}],["bell",{"_index":3210,"title":{},"content":{"93":{"position":[[1881,5]]}},"keywords":{}}],["below",{"_index":629,"title":{},"content":{"14":{"position":[[197,5],[675,5],[979,5]]},"15":{"position":[[1307,5]]},"20":{"position":[[911,5]]},"28":{"position":[[1630,6],[3416,6]]},"43":{"position":[[259,6]]},"90":{"position":[[3645,6],[5072,5]]},"148":{"position":[[591,6]]},"167":{"position":[[179,5]]},"196":{"position":[[668,5]]},"199":{"position":[[1000,5]]}},"keywords":{}}],["benchmark",{"_index":3577,"title":{},"content":{"105":{"position":[[285,9]]},"153":{"position":[[233,10]]},"163":{"position":[[5,9]]},"167":{"position":[[120,11]]},"170":{"position":[[12,9]]},"172":{"position":[[2398,11]]},"176":{"position":[[309,11],[1118,11],[1305,12]]},"198":{"position":[[332,9]]}},"keywords":{}}],["benchmark,y",{"_index":4619,"title":{},"content":{"158":{"position":[[111,13]]}},"keywords":{}}],["benefici",{"_index":4954,"title":{},"content":{"173":{"position":[[928,11]]}},"keywords":{}}],["benefit",{"_index":2810,"title":{},"content":{"83":{"position":[[160,8]]},"172":{"position":[[2302,8]]},"174":{"position":[[968,8],[1345,9]]}},"keywords":{}}],["besid",{"_index":4182,"title":{},"content":{"125":{"position":[[9344,7]]}},"keywords":{}}],["bespok",{"_index":194,"title":{},"content":{"3":{"position":[[1143,7]]}},"keywords":{}}],["best",{"_index":198,"title":{},"content":{"3":{"position":[[1211,4]]},"44":{"position":[[1765,4]]},"46":{"position":[[502,4]]},"58":{"position":[[206,5],[365,5]]},"76":{"position":[[945,4],[2117,4],[3286,4]]},"93":{"position":[[318,4]]},"104":{"position":[[89,4],[139,4],[959,4],[1472,4]]},"112":{"position":[[553,4],[1318,4]]},"120":{"position":[[1011,4]]},"123":{"position":[[986,4]]},"166":{"position":[[798,4]]},"170":{"position":[[164,4]]},"189":{"position":[[433,4]]}},"keywords":{}}],["bestructur",{"_index":4981,"title":{},"content":{"174":{"position":[[354,12]]}},"keywords":{}}],["bet",{"_index":1598,"title":{},"content":{"34":{"position":[[843,3],[867,3],[945,3]]}},"keywords":{}}],["better",{"_index":431,"title":{},"content":{"7":{"position":[[1093,6]]},"30":{"position":[[2862,6]]},"40":{"position":[[1521,6],[3292,6]]},"45":{"position":[[1871,6]]},"51":{"position":[[2702,6]]},"66":{"position":[[177,6]]},"73":{"position":[[824,6]]},"76":{"position":[[2549,8]]},"78":{"position":[[923,8]]},"82":{"position":[[298,8],[368,8],[438,8],[508,8],[578,8],[648,8],[718,8],[788,8],[858,8],[929,8]]},"86":{"position":[[1168,6]]},"93":{"position":[[757,6],[797,7],[833,6]]},"96":{"position":[[132,6]]},"105":{"position":[[2600,6],[3315,6],[3393,6]]},"121":{"position":[[290,6]]},"125":{"position":[[7348,6]]},"129":{"position":[[1333,6]]},"152":{"position":[[331,6]]},"159":{"position":[[848,6]]},"164":{"position":[[770,7]]},"172":{"position":[[907,6]]},"193":{"position":[[2146,6]]},"198":{"position":[[108,6]]}},"keywords":{}}],["between",{"_index":386,"title":{},"content":{"7":{"position":[[246,7]]},"9":{"position":[[179,7]]},"10":{"position":[[348,7]]},"15":{"position":[[1272,7]]},"43":{"position":[[1324,7]]},"64":{"position":[[317,7],[392,7],[1087,7],[1331,7],[2005,7]]},"89":{"position":[[780,7]]},"91":{"position":[[279,7]]},"115":{"position":[[1216,7],[1596,7],[1873,7],[2421,7],[2674,7]]},"116":{"position":[[1168,7],[1501,7],[1778,7],[2279,7],[3261,7]]},"117":{"position":[[983,7]]},"125":{"position":[[7595,7],[8281,7]]},"161":{"position":[[55,7]]},"175":{"position":[[279,7],[512,7],[1295,7]]},"183":{"position":[[31,7]]},"184":{"position":[[1087,7]]},"185":{"position":[[768,7]]},"199":{"position":[[69,7]]}},"keywords":{}}],["betweenth",{"_index":4650,"title":{},"content":{"160":{"position":[[243,10]]}},"keywords":{}}],["beyond",{"_index":1987,"title":{},"content":{"45":{"position":[[1774,6]]},"120":{"position":[[239,6]]}},"keywords":{}}],["bia",{"_index":1433,"title":{},"content":{"30":{"position":[[7633,5]]},"34":{"position":[[725,4],[1635,5],[2235,5]]},"39":{"position":[[1046,6],[1455,5],[2195,6]]},"41":{"position":[[483,4]]},"91":{"position":[[3918,4]]}},"keywords":{}}],["bias",{"_index":1695,"title":{},"content":{"38":{"position":[[687,7]]},"70":{"position":[[30,6],[57,6],[1225,6],[1243,6]]},"71":{"position":[[1390,6]]},"78":{"position":[[44,6]]},"79":{"position":[[40,6]]},"80":{"position":[[33,6]]},"82":{"position":[[152,6]]}},"keywords":{}}],["bias.th",{"_index":1594,"title":{},"content":{"34":{"position":[[376,8]]}},"keywords":{}}],["bib",{"_index":1836,"title":{},"content":{"40":{"position":[[3364,5]]}},"keywords":{}}],["big",{"_index":1784,"title":{},"content":{"40":{"position":[[58,3],[1310,3]]},"93":{"position":[[425,3]]},"125":{"position":[[11400,3]]},"129":{"position":[[798,3]]},"140":{"position":[[78,3]]},"163":{"position":[[502,3]]}},"keywords":{}}],["bigdecim",{"_index":3943,"title":{},"content":{"122":{"position":[[648,10],[683,10]]}},"keywords":{}}],["biggest",{"_index":5116,"title":{},"content":{"183":{"position":[[12,7]]}},"keywords":{}}],["billion",{"_index":2306,"title":{"57":{"position":[[4,8]]}},"content":{"57":{"position":[[673,7]]},"58":{"position":[[159,7],[241,7],[256,7],[385,7]]},"64":{"position":[[52,7],[2075,7]]}},"keywords":{}}],["billionth",{"_index":5170,"title":{},"content":{"188":{"position":[[1517,9]]}},"keywords":{}}],["bin",{"_index":2110,"title":{},"content":{"51":{"position":[[1713,4]]},"109":{"position":[[184,3]]}},"keywords":{}}],["binar",{"_index":1910,"title":{},"content":{"44":{"position":[[476,10],[593,8]]}},"keywords":{}}],["binari",{"_index":1896,"title":{"44":{"position":[[33,6]]},"162":{"position":[[0,6]]},"163":{"position":[[10,6]]},"166":{"position":[[7,6]]}},"content":{"44":{"position":[[71,6],[370,6],[1781,6]]},"45":{"position":[[208,6],[832,6],[3421,6]]},"96":{"position":[[1265,6]]},"108":{"position":[[11,6],[373,6],[730,6]]},"109":{"position":[[17,6]]},"110":{"position":[[590,6]]},"113":{"position":[[1550,7]]},"115":{"position":[[187,6]]},"116":{"position":[[287,6]]},"117":{"position":[[786,6],[850,6],[1079,6]]},"125":{"position":[[7860,7],[7896,7],[8114,7]]},"160":{"position":[[1862,6]]},"163":{"position":[[307,6]]},"165":{"position":[[205,6]]},"166":{"position":[[272,6]]},"180":{"position":[[95,7]]},"190":{"position":[[657,6]]}},"keywords":{}}],["binarize(x[b_class",{"_index":1914,"title":{},"content":{"44":{"position":[[610,20]]}},"keywords":{}}],["bind",{"_index":4333,"title":{},"content":{"129":{"position":[[2722,7]]},"130":{"position":[[324,9]]},"196":{"position":[[282,4]]}},"keywords":{}}],["bindgen",{"_index":4086,"title":{},"content":{"125":{"position":[[3726,7],[5275,7],[5823,7],[6168,7],[6482,7],[6566,7],[6769,7],[7623,7],[7667,7],[7842,7],[7925,7],[8087,7],[9357,8],[11416,7]]}},"keywords":{}}],["binghamton",{"_index":1202,"title":{},"content":{"28":{"position":[[191,11],[368,11],[990,14]]},"30":{"position":[[8681,13],[10162,10]]}},"keywords":{}}],["binghamton_loc",{"_index":1459,"title":{},"content":{"30":{"position":[[8572,14],[8695,14]]}},"keywords":{}}],["bins=11",{"_index":2566,"title":{},"content":{"68":{"position":[[617,9]]},"70":{"position":[[1198,9]]},"71":{"position":[[1349,8]]},"78":{"position":[[607,8]]}},"keywords":{}}],["bins=bin",{"_index":2113,"title":{},"content":{"51":{"position":[[1771,10]]}},"keywords":{}}],["biotech",{"_index":1823,"title":{},"content":{"40":{"position":[[2588,7]]}},"keywords":{}}],["biotech_df",{"_index":1825,"title":{},"content":{"40":{"position":[[2607,10]]}},"keywords":{}}],["biotech_df.xs('day",{"_index":1830,"title":{},"content":{"40":{"position":[[2707,21]]}},"keywords":{}}],["biotech_df.xs('scor",{"_index":1831,"title":{},"content":{"40":{"position":[[2878,22]]}},"keywords":{}}],["birth",{"_index":2497,"title":{},"content":{"64":{"position":[[2026,5]]}},"keywords":{}}],["birthday",{"_index":2479,"title":{},"content":{"64":{"position":[[1204,9],[1342,8]]}},"keywords":{}}],["birthday_heartbeat",{"_index":2487,"title":{},"content":{"64":{"position":[[1565,19]]}},"keywords":{}}],["birthday_minut",{"_index":2486,"title":{},"content":{"64":{"position":[[1542,16],[1587,16]]}},"keywords":{}}],["bit",{"_index":456,"title":{},"content":{"9":{"position":[[73,3]]},"24":{"position":[[518,3]]},"25":{"position":[[243,3]]},"28":{"position":[[2406,3]]},"29":{"position":[[25,3]]},"30":{"position":[[506,3],[9492,3]]},"40":{"position":[[883,3]]},"44":{"position":[[1005,3],[1677,3]]},"51":{"position":[[850,3]]},"61":{"position":[[1288,3]]},"65":{"position":[[22,4]]},"76":{"position":[[586,3]]},"86":{"position":[[227,3]]},"89":{"position":[[1017,5]]},"96":{"position":[[1955,3]]},"97":{"position":[[1206,3]]},"105":{"position":[[576,3],[729,3],[2867,3]]},"108":{"position":[[553,3]]},"113":{"position":[[792,3]]},"115":{"position":[[2709,3]]},"116":{"position":[[2365,3]]},"117":{"position":[[490,3]]},"123":{"position":[[522,3]]},"124":{"position":[[660,3]]},"125":{"position":[[7332,4]]},"127":{"position":[[312,4],[1119,5],[1216,3],[1549,3]]},"128":{"position":[[559,4],[792,4],[958,4],[1321,4],[1557,4],[1756,4]]},"129":{"position":[[308,3],[468,4],[761,3],[2680,3]]},"152":{"position":[[266,3]]},"156":{"position":[[525,3],[1031,3]]},"157":{"position":[[15,3]]},"160":{"position":[[807,3]]},"161":{"position":[[428,3]]},"179":{"position":[[22,3]]},"184":{"position":[[419,3]]},"196":{"position":[[1403,3]]}},"keywords":{}}],["bitrat",{"_index":3652,"title":{},"content":{"106":{"position":[[465,8]]}},"keywords":{}}],["black",{"_index":3055,"title":{},"content":{"90":{"position":[[4447,8],[4564,8],[4670,8]]}},"keywords":{}}],["blasphemi",{"_index":4199,"title":{},"content":{"125":{"position":[[10319,10]]}},"keywords":{}}],["bless",{"_index":1957,"title":{},"content":{"45":{"position":[[52,8]]}},"keywords":{}}],["blob",{"_index":4088,"title":{},"content":{"125":{"position":[[3897,5],[4481,4],[4623,5],[4936,4],[6591,4]]}},"keywords":{}}],["block",{"_index":913,"title":{},"content":{"22":{"position":[[859,6]]},"91":{"position":[[1819,5],[2750,5]]},"92":{"position":[[562,5]]},"98":{"position":[[248,6]]},"105":{"position":[[3091,5],[3289,5],[3375,5]]},"106":{"position":[[779,6]]},"121":{"position":[[1675,7],[1834,5]]},"123":{"position":[[250,8]]},"125":{"position":[[9425,6],[9655,6]]},"129":{"position":[[156,6],[341,6]]},"163":{"position":[[980,5],[1076,5]]},"165":{"position":[[28,6]]},"188":{"position":[[632,5],[932,6],[4136,7]]}},"keywords":{}}],["block_len",{"_index":4784,"title":{},"content":{"163":{"position":[[1859,10]]}},"keywords":{}}],["block_siz",{"_index":3523,"title":{},"content":{"103":{"position":[[988,10],[1031,10],[1060,11],[1232,11],[1244,12],[1613,11]]},"105":{"position":[[1374,12],[1453,11]]}},"keywords":{}}],["block_size=1024",{"_index":3522,"title":{},"content":{"103":{"position":[[910,17]]}},"keywords":{}}],["block_typ",{"_index":4783,"title":{},"content":{"163":{"position":[[1847,11]]}},"keywords":{}}],["blockstak",{"_index":3904,"title":{},"content":{"121":{"position":[[1573,10]]}},"keywords":{}}],["blog",{"_index":249,"title":{},"content":{"4":{"position":[[654,4]]},"30":{"position":[[7967,4],[8184,4],[8268,4]]},"39":{"position":[[209,4]]},"53":{"position":[[857,4]]},"86":{"position":[[669,4]]},"125":{"position":[[2298,4],[11651,4]]},"161":{"position":[[263,4]]},"166":{"position":[[67,4]]}},"keywords":{}}],["blow",{"_index":980,"title":{"143":{"position":[[0,7]]}},"content":{"22":{"position":[[2833,5]]},"76":{"position":[[1457,4]]},"91":{"position":[[3255,4]]},"92":{"position":[[1067,4]]},"96":{"position":[[1832,5]]},"121":{"position":[[631,5]]},"153":{"position":[[776,5]]}},"keywords":{}}],["blown",{"_index":4303,"title":{},"content":{"129":{"position":[[1755,6]]}},"keywords":{}}],["blue",{"_index":3064,"title":{},"content":{"90":{"position":[[4749,4],[4972,4],[5011,4]]}},"keywords":{}}],["bodywrap",{"_index":3914,"title":{},"content":{"121":{"position":[[2048,11]]}},"keywords":{}}],["boilerpl",{"_index":4219,"title":{},"content":{"125":{"position":[[11592,11]]}},"keywords":{}}],["bokeh.palett",{"_index":1325,"title":{},"content":{"30":{"position":[[156,14]]}},"keywords":{}}],["bokeh.plot",{"_index":1323,"title":{},"content":{"30":{"position":[[99,14]]}},"keywords":{}}],["bokehj",{"_index":1331,"title":{},"content":{"30":{"position":[[298,7]]}},"keywords":{}}],["bond",{"_index":302,"title":{"5":{"position":[[13,5]]}},"content":{"6":{"position":[[36,6]]}},"keywords":{}}],["bonfir",{"_index":2212,"title":{},"content":{"53":{"position":[[452,8]]}},"keywords":{}}],["book",{"_index":4660,"title":{},"content":{"160":{"position":[[628,4]]},"163":{"position":[[70,4]]}},"keywords":{}}],["bookment",{"_index":5064,"title":{},"content":{"179":{"position":[[74,12]]}},"keywords":{}}],["bool",{"_index":4224,"title":{},"content":{"127":{"position":[[205,4]]}},"keywords":{}}],["boolean",{"_index":3891,"title":{},"content":{"121":{"position":[[1005,7]]}},"keywords":{}}],["boost",{"_index":5237,"title":{},"content":{"189":{"position":[[1264,6]]}},"keywords":{}}],["bootstrap",{"_index":4010,"title":{},"content":{"125":{"position":[[204,9]]}},"keywords":{}}],["bore",{"_index":4800,"title":{},"content":{"163":{"position":[[2489,6]]}},"keywords":{}}],["born",{"_index":2451,"title":{},"content":{"64":{"position":[[161,4]]}},"keywords":{}}],["borrow",{"_index":2621,"title":{"97":{"position":[[27,6]]}},"content":{"73":{"position":[[165,6]]},"97":{"position":[[428,6],[4583,7],[5011,8],[5133,8]]},"113":{"position":[[1130,8]]},"115":{"position":[[3137,6]]},"164":{"position":[[717,6]]},"193":{"position":[[3459,9]]}},"keywords":{}}],["both",{"_index":223,"title":{},"content":{"4":{"position":[[61,4]]},"15":{"position":[[458,4]]},"24":{"position":[[2933,4],[3345,4]]},"38":{"position":[[523,4]]},"40":{"position":[[3606,4]]},"71":{"position":[[122,4]]},"76":{"position":[[3277,4]]},"78":{"position":[[39,4]]},"79":{"position":[[35,4]]},"92":{"position":[[1592,4]]},"118":{"position":[[73,4]]},"125":{"position":[[2,4],[11382,4]]},"129":{"position":[[1802,4]]},"130":{"position":[[301,4]]},"132":{"position":[[717,4]]},"146":{"position":[[1,4]]},"160":{"position":[[2697,4]]},"166":{"position":[[321,4]]},"170":{"position":[[228,4]]},"172":{"position":[[1659,4]]},"181":{"position":[[457,4]]},"188":{"position":[[1740,4]]},"189":{"position":[[2334,4]]},"190":{"position":[[889,4]]}},"keywords":{}}],["bothlibtest",{"_index":4542,"title":{},"content":{"153":{"position":[[312,11]]}},"keywords":{}}],["bottom",{"_index":1572,"title":{},"content":{"33":{"position":[[393,6]]},"161":{"position":[[1137,6]]}},"keywords":{}}],["bound",{"_index":811,"title":{},"content":{"20":{"position":[[1203,5],[1947,6]]},"97":{"position":[[1859,5]]},"115":{"position":[[951,5],[1265,5],[1645,5],[1922,5]]},"116":{"position":[[950,5],[1217,5],[1550,5],[1827,5]]},"129":{"position":[[1822,5]]}},"keywords":{}}],["boundari",{"_index":3812,"title":{},"content":{"116":{"position":[[2594,11],[2727,11]]}},"keywords":{}}],["bounds=bound",{"_index":843,"title":{},"content":{"20":{"position":[[2230,14]]}},"keywords":{}}],["box",{"_index":3797,"title":{"116":{"position":[[31,4]]},"152":{"position":[[29,4]]}},"content":{"116":{"position":[[5,3]]},"141":{"position":[[93,5],[196,3]]},"152":{"position":[[627,5]]},"155":{"position":[[1129,3]]},"159":{"position":[[978,5]]}},"keywords":{}}],["box<_>",{"_index":4461,"title":{},"content":{"145":{"position":[[364,14]]}},"keywords":{}}],["box<u64>",{"_index":5366,"title":{},"content":{"198":{"position":[[1012,14],[1147,14]]}},"keywords":{}}],["box<vec<u8>>",{"_index":4434,"title":{},"content":{"141":{"position":[[27,24]]}},"keywords":{}}],["box,rc",{"_index":4697,"title":{},"content":{"160":{"position":[[2571,7]]}},"keywords":{}}],["box::new(0",{"_index":4580,"title":{},"content":{"155":{"position":[[1387,12]]}},"keywords":{}}],["box::new(24",{"_index":4517,"title":{},"content":{"152":{"position":[[694,13]]}},"keywords":{}}],["box::new(point_read",{"_index":3800,"title":{},"content":{"116":{"position":[[569,23]]}},"keywords":{}}],["box::new(vec::new",{"_index":4435,"title":{},"content":{"141":{"position":[[54,21]]}},"keywords":{}}],["box`",{"_index":3801,"title":{},"content":{"116":{"position":[[619,8]]}},"keywords":{}}],["boxed_read",{"_index":3799,"title":{},"content":{"116":{"position":[[554,12]]}},"keywords":{}}],["boxrcarccow",{"_index":4563,"title":{},"content":{"155":{"position":[[570,11]]}},"keywords":{}}],["bracket",{"_index":3870,"title":{},"content":{"121":{"position":[[26,7]]}},"keywords":{}}],["bradlee'",{"_index":1528,"title":{},"content":{"32":{"position":[[768,9]]}},"keywords":{}}],["bradlee@speice.io",{"_index":4721,"title":{},"content":{"160":{"position":[[4330,17]]}},"keywords":{}}],["brainer",{"_index":3963,"title":{},"content":{"122":{"position":[[1487,8]]}},"keywords":{}}],["branch",{"_index":4982,"title":{},"content":{"174":{"position":[[379,6]]}},"keywords":{}}],["branchesin",{"_index":4937,"title":{},"content":{"172":{"position":[[2642,10]]}},"keywords":{}}],["bread",{"_index":3840,"title":{"161":{"position":[[7,5]]}},"content":{"118":{"position":[[128,5]]},"161":{"position":[[246,5],[1001,5],[1516,5],[1550,5]]}},"keywords":{}}],["break",{"_index":299,"title":{},"content":{"4":{"position":[[1521,5]]},"30":{"position":[[9578,7]]},"32":{"position":[[2140,5]]},"33":{"position":[[1190,5]]},"34":{"position":[[251,5]]},"104":{"position":[[97,5]]},"125":{"position":[[11471,5]]},"129":{"position":[[369,5]]},"150":{"position":[[57,5]]},"161":{"position":[[479,5],[1631,6]]},"172":{"position":[[2533,5]]}},"keywords":{}}],["breakfast/articles"",{"_index":904,"title":{},"content":{"22":{"position":[[656,24]]}},"keywords":{}}],["breakneck",{"_index":4359,"title":{},"content":{"132":{"position":[[953,9]]}},"keywords":{}}],["breaksthere'",{"_index":278,"title":{},"content":{"4":{"position":[[1077,13]]}},"keywords":{}}],["breath",{"_index":2201,"title":{},"content":{"53":{"position":[[255,7]]},"66":{"position":[[617,7]]}},"keywords":{}}],["breviti",{"_index":3786,"title":{},"content":{"115":{"position":[[2526,8]]}},"keywords":{}}],["brew",{"_index":3671,"title":{},"content":{"108":{"position":[[515,4]]}},"keywords":{}}],["brief",{"_index":3461,"title":{"101":{"position":[[2,5]]}},"content":{},"keywords":{}}],["bring",{"_index":2716,"title":{},"content":{"76":{"position":[[1854,6]]},"124":{"position":[[421,5]]},"172":{"position":[[2291,6]]}},"keywords":{}}],["brittl",{"_index":4197,"title":{},"content":{"125":{"position":[[10301,7]]}},"keywords":{}}],["broad",{"_index":2950,"title":{},"content":{"89":{"position":[[473,5]]},"197":{"position":[[28,5]]}},"keywords":{}}],["broadli",{"_index":3469,"title":{},"content":{"101":{"position":[[299,7]]}},"keywords":{}}],["broke",{"_index":2938,"title":{},"content":{"88":{"position":[[3590,5]]},"103":{"position":[[60,5]]},"125":{"position":[[2352,5]]}},"keywords":{}}],["brought",{"_index":4765,"title":{},"content":{"163":{"position":[[489,7]]}},"keywords":{}}],["browser",{"_index":70,"title":{},"content":{"1":{"position":[[776,8]]},"125":{"position":[[1039,8],[6811,7],[7180,7],[8747,7],[9465,8]]},"160":{"position":[[2883,8]]}},"keywords":{}}],["browser'",{"_index":4190,"title":{},"content":{"125":{"position":[[9679,9]]}},"keywords":{}}],["browser."",{"_index":26,"title":{},"content":{"1":{"position":[[297,14]]}},"keywords":{}}],["bs",{"_index":3610,"title":{},"content":{"105":{"position":[[1734,3],[1745,2]]}},"keywords":{}}],["bsd",{"_index":3995,"title":{},"content":{"124":{"position":[[270,3]]}},"keywords":{}}],["bubbl",{"_index":4742,"title":{},"content":{"161":{"position":[[880,8]]}},"keywords":{}}],["bueno",{"_index":4186,"title":{},"content":{"125":{"position":[[9480,6]]}},"keywords":{}}],["buffer",{"_index":3752,"title":{},"content":{"113":{"position":[[1573,6],[1598,6],[1645,6],[1707,7]]},"115":{"position":[[148,8],[2737,6]]},"116":{"position":[[248,8]]},"117":{"position":[[1040,8]]},"164":{"position":[[482,6],[589,7],[965,6],[1049,6]]},"168":{"position":[[144,7]]}},"keywords":{}}],["buffer.as_slic",{"_index":3758,"title":{},"content":{"113":{"position":[[1838,18]]},"115":{"position":[[293,18]]},"116":{"position":[[393,18]]},"117":{"position":[[1182,18]]}},"keywords":{}}],["build",{"_index":265,"title":{"111":{"position":[[23,5]]},"112":{"position":[[20,6]]},"171":{"position":[[3,8]]}},"content":{"4":{"position":[[868,5]]},"7":{"position":[[391,5]]},"12":{"position":[[29,5]]},"34":{"position":[[763,5]]},"49":{"position":[[32,5]]},"50":{"position":[[141,5]]},"51":{"position":[[370,5],[714,5]]},"97":{"position":[[2365,5],[3065,5],[3955,5]]},"98":{"position":[[239,8]]},"102":{"position":[[1471,5]]},"105":{"position":[[357,5]]},"109":{"position":[[377,6]]},"111":{"position":[[38,5],[848,5]]},"112":{"position":[[76,5],[139,5]]},"113":{"position":[[118,8],[756,8],[2516,5]]},"124":{"position":[[841,8]]},"125":{"position":[[5219,5],[5767,5],[6997,5],[9646,8],[9727,8]]},"128":{"position":[[18,5]]},"132":{"position":[[22,8],[594,5]]},"141":{"position":[[240,6]]},"143":{"position":[[417,8]]},"146":{"position":[[225,7]]},"160":{"position":[[3564,5]]},"163":{"position":[[545,5],[1634,5],[2408,8]]},"165":{"position":[[911,8]]},"167":{"position":[[7,8]]},"170":{"position":[[1,8]]},"188":{"position":[[159,8]]},"190":{"position":[[448,8]]}},"keywords":{}}],["build.r",{"_index":3698,"title":{},"content":{"111":{"position":[[166,8],[292,9]]}},"keywords":{}}],["build_estimates(sign",{"_index":3602,"title":{},"content":{"105":{"position":[[1336,23]]}},"keywords":{}}],["build_estimates(tabulasa_left",{"_index":3609,"title":{},"content":{"105":{"position":[[1700,30]]}},"keywords":{}}],["build_handler(messag",{"_index":3372,"title":{},"content":{"97":{"position":[[1463,22]]}},"keywords":{}}],["builder",{"_index":3722,"title":{},"content":{"112":{"position":[[1280,7],[1385,8],[1482,7]]},"113":{"position":[[839,8],[948,7],[1044,9]]},"164":{"position":[[352,7]]}},"keywords":{}}],["builder.init_root::<point_capnp::point::builder>",{"_index":3748,"title":{},"content":{"113":{"position":[[1364,57]]}},"keywords":{}}],["builderscan't",{"_index":4805,"title":{},"content":{"164":{"position":[[430,13]]}},"keywords":{}}],["builderthat",{"_index":4807,"title":{},"content":{"164":{"position":[[560,11]]}},"keywords":{}}],["built",{"_index":2147,"title":{},"content":{"51":{"position":[[3437,5]]},"52":{"position":[[10,5]]},"111":{"position":[[583,5]]},"113":{"position":[[563,5]]},"122":{"position":[[245,6]]},"124":{"position":[[16,5]]},"125":{"position":[[1544,5]]},"132":{"position":[[304,6]]},"175":{"position":[[675,5]]},"176":{"position":[[149,6]]}},"keywords":{}}],["bulg",{"_index":3869,"title":{},"content":{"121":{"position":[[20,5]]}},"keywords":{}}],["bulk",{"_index":4384,"title":{},"content":{"136":{"position":[[118,4]]}},"keywords":{}}],["bundl",{"_index":251,"title":{},"content":{"4":{"position":[[691,8]]},"125":{"position":[[4150,6],[6656,6]]}},"keywords":{}}],["bundle.j",{"_index":4089,"title":{},"content":{"125":{"position":[[4003,9]]}},"keywords":{}}],["burden",{"_index":4663,"title":{},"content":{"160":{"position":[[699,6]]},"174":{"position":[[811,8]]}},"keywords":{}}],["burdensom",{"_index":4689,"title":{},"content":{"160":{"position":[[2302,10]]}},"keywords":{}}],["button",{"_index":4032,"title":{},"content":{"125":{"position":[[938,6]]},"176":{"position":[[989,8]]}},"keywords":{}}],["bycach",{"_index":4830,"title":{},"content":{"165":{"position":[[864,9]]}},"keywords":{}}],["bypass",{"_index":4810,"title":{},"content":{"164":{"position":[[703,6]]},"174":{"position":[[1231,7]]}},"keywords":{}}],["byte",{"_index":3319,"title":{},"content":{"96":{"position":[[189,5]]},"105":{"position":[[599,5],[746,5]]},"127":{"position":[[215,4]]},"192":{"position":[[243,5],[356,5],[503,5]]},"193":{"position":[[1145,5]]},"195":{"position":[[184,5]]}},"keywords":{}}],["bytecod",{"_index":4929,"title":{},"content":{"172":{"position":[[2055,8]]},"189":{"position":[[141,8]]}},"keywords":{}}],["bytes"",{"_index":4732,"title":{},"content":{"161":{"position":[[383,12]]}},"keywords":{}}],["bytestr",{"_index":3591,"title":{},"content":{"105":{"position":[[1011,10]]}},"keywords":{}}],["bz2",{"_index":3580,"title":{},"content":{"105":{"position":[[453,3]]}},"keywords":{}}],["bz2"",{"_index":3615,"title":{},"content":{"105":{"position":[[1857,10]]}},"keywords":{}}],["bz2(1",{"_index":3617,"title":{},"content":{"105":{"position":[[1963,6]]}},"keywords":{}}],["bz2_estimate(transform",{"_index":3590,"title":{},"content":{"105":{"position":[[979,25],[1534,25]]}},"keywords":{}}],["bz2_pca_estim",{"_index":3605,"title":{},"content":{"105":{"position":[[1515,16],[1642,16]]}},"keywords":{}}],["c",{"_index":1903,"title":{"128":{"position":[[33,4]]}},"content":{"44":{"position":[[239,1]]},"98":{"position":[[668,3],[672,5],[894,3]]},"103":{"position":[[354,1]]},"128":{"position":[[145,1],[1094,1],[1582,1],[1690,1]]},"130":{"position":[[180,1]]},"155":{"position":[[249,4]]},"160":{"position":[[2321,3]]},"172":{"position":[[1030,3],[1449,1],[1471,3],[1490,3],[1494,4],[1805,3],[2185,2],[2610,3]]},"188":{"position":[[187,1],[193,3],[1079,1],[1085,1],[1128,1],[1130,1],[1147,1],[4299,1]]},"189":{"position":[[593,2],[1147,1],[1190,1],[1192,1],[1209,1],[1417,1],[1460,1],[1462,1],[1479,1]]}},"keywords":{}}],["c"",{"_index":4184,"title":{},"content":{"125":{"position":[[9417,7]]}},"keywords":{}}],["c/c",{"_index":5147,"title":{},"content":{"188":{"position":[[95,6]]},"189":{"position":[[112,6]]}},"keywords":{}}],["c6e2990393c32fe6/out/point_capnp.r",{"_index":3716,"title":{},"content":{"112":{"position":[[835,35]]}},"keywords":{}}],["c='k",{"_index":2011,"title":{},"content":{"45":{"position":[[2358,6],[2433,6],[3138,6],[3213,6]]}},"keywords":{}}],["c_n",{"_index":1541,"title":{},"content":{"32":{"position":[[1572,3]]}},"keywords":{}}],["cach",{"_index":4986,"title":{},"content":{"174":{"position":[[604,8]]}},"keywords":{}}],["cachegrind",{"_index":4923,"title":{},"content":{"172":{"position":[[1620,10]]}},"keywords":{}}],["calcul",{"_index":411,"title":{"18":{"position":[[0,11]]},"19":{"position":[[0,11]]},"20":{"position":[[0,11]]}},"content":{"7":{"position":[[680,9],[765,9]]},"9":{"position":[[297,9]]},"10":{"position":[[526,10],[600,10]]},"19":{"position":[[168,9]]},"20":{"position":[[2742,9]]},"24":{"position":[[207,9]]},"74":{"position":[[212,12],[858,9]]},"76":{"position":[[219,11],[679,12]]},"90":{"position":[[3525,10]]},"163":{"position":[[161,9]]},"165":{"position":[[1316,11]]},"175":{"position":[[1412,9]]},"188":{"position":[[1503,9],[1849,11]]}},"keywords":{}}],["calculate_closing_ret(djia",{"_index":1143,"title":{},"content":{"25":{"position":[[529,27]]}},"keywords":{}}],["calculate_closing_ret(fram",{"_index":1136,"title":{},"content":{"25":{"position":[[152,29]]}},"keywords":{}}],["calculate_closing_ret(nasdaq",{"_index":1147,"title":{},"content":{"25":{"position":[[621,29]]}},"keywords":{}}],["calculate_closing_ret(russ",{"_index":1145,"title":{},"content":{"25":{"position":[[574,27]]}},"keywords":{}}],["calculate_closing_ret(spi",{"_index":1141,"title":{},"content":{"25":{"position":[[485,26]]}},"keywords":{}}],["calculate_opening_ret(djia",{"_index":1041,"title":{},"content":{"24":{"position":[[811,27]]}},"keywords":{}}],["calculate_opening_ret(fram",{"_index":1023,"title":{},"content":{"24":{"position":[[427,29]]}},"keywords":{}}],["calculate_opening_ret(nasdaq",{"_index":1045,"title":{},"content":{"24":{"position":[[901,29]]}},"keywords":{}}],["calculate_opening_ret(russ",{"_index":1043,"title":{},"content":{"24":{"position":[[855,27]]}},"keywords":{}}],["calculate_opening_ret(spi",{"_index":1039,"title":{},"content":{"24":{"position":[[768,26]]}},"keywords":{}}],["calculated_term2",{"_index":502,"title":{},"content":{"10":{"position":[[438,16]]}},"keywords":{}}],["calculated_term2)"",{"_index":505,"title":{},"content":{"10":{"position":[[546,26]]}},"keywords":{}}],["calendar",{"_index":2967,"title":{},"content":{"90":{"position":[[419,9]]},"91":{"position":[[3802,8]]}},"keywords":{}}],["calendar=trade_calendar",{"_index":2977,"title":{},"content":{"90":{"position":[[714,24]]}},"keywords":{}}],["call",{"_index":543,"title":{"146":{"position":[[15,6]]}},"content":{"13":{"position":[[153,6],[191,4],[273,4]]},"14":{"position":[[308,6],[346,4],[610,4],[734,4],[760,6],[906,4],[1071,4],[1097,6],[1245,4]]},"15":{"position":[[311,4]]},"32":{"position":[[760,4]]},"33":{"position":[[465,6]]},"53":{"position":[[1727,4]]},"64":{"position":[[367,4]]},"95":{"position":[[489,4]]},"96":{"position":[[557,4]]},"97":{"position":[[404,4],[1343,6],[4255,4],[4339,4]]},"102":{"position":[[139,6]]},"122":{"position":[[191,4]]},"125":{"position":[[3193,4],[5154,5],[5444,4]]},"127":{"position":[[1508,4]]},"128":{"position":[[669,4],[708,4],[1427,4],[1466,4],[1817,4],[1941,5]]},"129":{"position":[[619,4],[689,4],[1039,4],[1702,4],[1807,4],[1856,4]]},"135":{"position":[[85,6]]},"136":{"position":[[53,5]]},"147":{"position":[[423,5]]},"150":{"position":[[107,4]]},"152":{"position":[[738,4]]},"156":{"position":[[542,4],[594,4],[773,5]]},"160":{"position":[[1277,6]]},"161":{"position":[[966,5]]},"163":{"position":[[439,6]]},"173":{"position":[[176,6],[948,6],[1097,5]]},"174":{"position":[[1217,6]]},"178":{"position":[[630,7]]},"180":{"position":[[620,4]]},"186":{"position":[[641,6]]},"188":{"position":[[909,4],[3736,4],[4441,7]]},"189":{"position":[[240,7],[319,7],[1483,4],[2960,7]]},"193":{"position":[[331,7],[643,7],[701,4],[775,4]]},"195":{"position":[[727,4]]},"196":{"position":[[1081,6]]},"197":{"position":[[998,4]]}},"keywords":{}}],["call_barri",{"_index":558,"title":{},"content":{"13":{"position":[[519,12],[653,13],[800,12],[1200,13]]},"14":{"position":[[1336,12],[1494,13],[1657,12],[2245,13]]},"15":{"position":[[705,12],[865,13],[1047,12],[1915,13]]}},"keywords":{}}],["call_onc",{"_index":5142,"title":{},"content":{"186":{"position":[[589,11]]}},"keywords":{}}],["callback_url",{"_index":2349,"title":{},"content":{"60":{"position":[[242,12]]},"61":{"position":[[1728,13]]}},"keywords":{}}],["caller",{"_index":5290,"title":{},"content":{"193":{"position":[[1602,6]]}},"keywords":{}}],["callingto_str",{"_index":4291,"title":{},"content":{"129":{"position":[[820,18]]}},"keywords":{}}],["came",{"_index":31,"title":{},"content":{"1":{"position":[[336,4]]},"2":{"position":[[264,4],[503,4]]},"53":{"position":[[2218,4]]}},"keywords":{}}],["can't",{"_index":1178,"title":{},"content":{"26":{"position":[[716,5]]},"39":{"position":[[1797,5]]},"46":{"position":[[301,5]]},"96":{"position":[[2051,5]]},"101":{"position":[[954,5]]},"106":{"position":[[704,5]]},"116":{"position":[[2862,5]]},"120":{"position":[[633,5]]},"125":{"position":[[4696,5],[8538,5],[9006,5],[9255,5]]},"127":{"position":[[473,5]]},"153":{"position":[[796,5]]},"160":{"position":[[1402,5]]},"165":{"position":[[544,5]]},"172":{"position":[[1608,5]]},"188":{"position":[[3229,5]]}},"keywords":{}}],["can'tcalendar",{"_index":3947,"title":{},"content":{"122":{"position":[[874,13]]}},"keywords":{}}],["canblock",{"_index":4964,"title":{},"content":{"173":{"position":[[1568,8]]}},"keywords":{}}],["cancondition",{"_index":5219,"title":{},"content":{"188":{"position":[[4159,16]]}},"keywords":{}}],["candid",{"_index":192,"title":{},"content":{"3":{"position":[[1114,10]]},"124":{"position":[[394,9]]}},"keywords":{}}],["candlestick_ohlc",{"_index":2846,"title":{},"content":{"88":{"position":[[383,16]]}},"keywords":{}}],["candlestick_ohlc(ax",{"_index":2867,"title":{},"content":{"88":{"position":[[1162,20]]}},"keywords":{}}],["canreleas",{"_index":4590,"title":{},"content":{"156":{"position":[[123,10]]}},"keywords":{}}],["canyarn",{"_index":4048,"title":{},"content":{"125":{"position":[[1448,7]]}},"keywords":{}}],["cap",{"_index":2955,"title":{},"content":{"89":{"position":[[805,3]]}},"keywords":{}}],["cap'n",{"_index":3662,"title":{"109":{"position":[[19,5]]},"164":{"position":[[0,5]]}},"content":{"108":{"position":[[271,5]]},"109":{"position":[[535,5],[645,5]]},"111":{"position":[[70,5],[606,5]]},"112":{"position":[[1238,5]]},"113":{"position":[[18,5],[127,5],[767,5],[2552,5]]},"116":{"position":[[3241,5]]},"117":{"position":[[49,5],[689,5],[2095,5]]},"164":{"position":[[56,5],[300,5],[629,5],[800,5],[1021,5],[1192,5],[1475,5]]},"165":{"position":[[164,5],[392,5],[1124,5]]},"166":{"position":[[326,5]]},"168":{"position":[[240,5]]},"169":{"position":[[354,5]]}},"keywords":{}}],["cap/high",{"_index":3191,"title":{},"content":{"93":{"position":[[679,8]]}},"keywords":{}}],["capabl",{"_index":3992,"title":{},"content":{"124":{"position":[[169,7]]}},"keywords":{}}],["capit",{"_index":575,"title":{},"content":{"13":{"position":[[937,7]]},"14":{"position":[[1955,7]]},"15":{"position":[[1623,7]]}},"keywords":{}}],["capnp",{"_index":3660,"title":{"108":{"position":[[19,6]]}},"content":{"108":{"position":[[5,5],[871,5]]},"109":{"position":[[11,5],[442,5]]},"113":{"position":[[307,7],[347,6]]}},"keywords":{}}],["capnp.ex",{"_index":3675,"title":{},"content":{"108":{"position":[[720,9]]}},"keywords":{}}],["capnp::message::builder::new_default",{"_index":3739,"title":{},"content":{"113":{"position":[[958,39]]}},"keywords":{}}],["capnp::message::readeroptions::new",{"_index":3759,"title":{},"content":{"113":{"position":[[1857,36]]},"115":{"position":[[312,36]]},"116":{"position":[[412,36]]},"117":{"position":[[1201,36]]}},"keywords":{}}],["capnp::message::typedreader<capnp::serialize::ownedseg",{"_index":3827,"title":{},"content":{"117":{"position":[[1268,63]]}},"keywords":{}}],["capnp::message::typedreader::new(deseri",{"_index":3829,"title":{},"content":{"117":{"position":[[1364,47]]}},"keywords":{}}],["capnp::private::arena::readerarena",{"_index":3781,"title":{},"content":{"115":{"position":[[1651,36],[1819,36]]},"116":{"position":[[1556,36],[1724,36]]}},"keywords":{}}],["capnp::private::layout::wirepoint",{"_index":3780,"title":{},"content":{"115":{"position":[[1279,36],[1544,36]]},"116":{"position":[[1231,36],[1449,36]]}},"keywords":{}}],["capnp::serialize::read_messag",{"_index":3757,"title":{},"content":{"113":{"position":[[1797,31]]},"115":{"position":[[252,31]]},"116":{"position":[[352,31]]},"117":{"position":[[1141,31]]}},"keywords":{}}],["capnp::serialize::write_message(&mut",{"_index":3754,"title":{},"content":{"113":{"position":[[1666,40]]}},"keywords":{}}],["capnp_cookbook_1",{"_index":3681,"title":{},"content":{"109":{"position":[[134,16],[154,16]]},"110":{"position":[[303,18]]},"112":{"position":[[649,16]]}},"keywords":{}}],["capnpc",{"_index":3690,"title":{},"content":{"109":{"position":[[398,6]]},"111":{"position":[[316,7],[533,7]]},"113":{"position":[[325,8]]}},"keywords":{}}],["capnpc::compilercommand::new",{"_index":3702,"title":{},"content":{"111":{"position":[[336,32]]}},"keywords":{}}],["capnproto",{"_index":3668,"title":{},"content":{"108":{"position":[[438,9]]},"109":{"position":[[511,10],[563,10]]}},"keywords":{}}],["capnpwindow",{"_index":3672,"title":{},"content":{"108":{"position":[[528,12]]}},"keywords":{}}],["captain'",{"_index":3658,"title":{"107":{"position":[[0,9]]},"114":{"position":[[0,9]]}},"content":{},"keywords":{}}],["captur",{"_index":2961,"title":{},"content":{"90":{"position":[[98,7]]},"159":{"position":[[42,8]]},"163":{"position":[[1432,8]]},"196":{"position":[[35,7],[165,7],[206,7],[905,8]]}},"keywords":{}}],["captured_len",{"_index":4788,"title":{},"content":{"163":{"position":[[1915,13]]}},"keywords":{}}],["car",{"_index":4425,"title":{},"content":{"139":{"position":[[642,5]]}},"keywords":{}}],["card",{"_index":4275,"title":{},"content":{"129":{"position":[[33,4]]}},"keywords":{}}],["care",{"_index":1395,"title":{},"content":{"30":{"position":[[4141,7]]},"43":{"position":[[1356,4],[1404,4]]},"73":{"position":[[419,4]]},"97":{"position":[[3016,4],[3152,4]]},"121":{"position":[[1637,7]]},"124":{"position":[[553,4]]},"125":{"position":[[4800,4]]},"147":{"position":[[75,7]]},"153":{"position":[[205,8]]},"158":{"position":[[131,4]]},"159":{"position":[[165,4]]},"172":{"position":[[2345,7]]},"173":{"position":[[1932,4]]},"176":{"position":[[889,4]]},"181":{"position":[[970,6]]}},"keywords":{}}],["career",{"_index":2203,"title":{},"content":{"53":{"position":[[302,6],[2175,7]]}},"keywords":{}}],["carefulli",{"_index":3826,"title":{},"content":{"117":{"position":[[931,9]]}},"keywords":{}}],["cargo",{"_index":3683,"title":{},"content":{"109":{"position":[[171,5]]},"112":{"position":[[133,5],[175,5]]},"113":{"position":[[508,6]]},"125":{"position":[[5204,5],[5752,5],[6516,5]]},"160":{"position":[[3602,5],[3616,5],[3679,6],[3704,5]]}},"keywords":{}}],["cargo.lock",{"_index":4148,"title":{},"content":{"125":{"position":[[7532,10]]}},"keywords":{}}],["cargo.toml",{"_index":3684,"title":{},"content":{"109":{"position":[[227,11]]},"111":{"position":[[239,10]]}},"keywords":{}}],["cari",{"_index":1231,"title":{},"content":{"28":{"position":[[1005,7]]},"30":{"position":[[7444,5],[8284,4],[8623,7],[10323,4]]}},"keywords":{}}],["carlo",{"_index":2301,"title":{},"content":{"55":{"position":[[124,5]]}},"keywords":{}}],["carolina",{"_index":1197,"title":{},"content":{"28":{"position":[[60,8]]},"30":{"position":[[84,9],[353,9],[529,8],[1017,8],[7807,9],[8041,8]]}},"keywords":{}}],["cary_forecast",{"_index":1353,"title":{},"content":{"30":{"position":[[1310,13]]}},"keywords":{}}],["cary_loc",{"_index":1450,"title":{},"content":{"30":{"position":[[8470,8],[8631,9]]}},"keywords":{}}],["case",{"_index":1432,"title":{"69":{"position":[[9,6]]},"70":{"position":[[5,4]]},"71":{"position":[[5,4]]},"131":{"position":[[2,4]]},"152":{"position":[[4,4]]}},"content":{"30":{"position":[[7612,4]]},"38":{"position":[[281,5]]},"51":{"position":[[2054,4]]},"53":{"position":[[1953,5],[2072,5]]},"64":{"position":[[728,4],[769,4]]},"68":{"position":[[73,5],[156,5],[899,4],[960,4]]},"69":{"position":[[115,5]]},"72":{"position":[[272,5]]},"75":{"position":[[206,4]]},"96":{"position":[[168,6]]},"104":{"position":[[819,5],[1220,5]]},"105":{"position":[[24,5]]},"116":{"position":[[61,4],[2614,5]]},"148":{"position":[[291,4]]},"152":{"position":[[153,6]]},"160":{"position":[[1184,6]]},"170":{"position":[[250,4],[278,4]]},"184":{"position":[[53,4],[467,6]]},"192":{"position":[[14,4]]},"196":{"position":[[752,5]]},"198":{"position":[[529,5]]}},"keywords":{}}],["case.th",{"_index":2055,"title":{},"content":{"49":{"position":[[190,8]]}},"keywords":{}}],["casino",{"_index":2553,"title":{"67":{"position":[[11,6]]},"77":{"position":[[13,7]]}},"content":{"69":{"position":[[175,6]]},"77":{"position":[[68,6]]},"78":{"position":[[5,6]]},"79":{"position":[[5,6]]},"80":{"position":[[5,6]]},"81":{"position":[[32,6]]},"83":{"position":[[630,7]]},"86":{"position":[[730,6]]}},"keywords":{}}],["casserol",{"_index":4748,"title":{},"content":{"161":{"position":[[1115,9]]}},"keywords":{}}],["catch",{"_index":2744,"title":{"77":{"position":[[0,8]]}},"content":{"77":{"position":[[58,5]]},"121":{"position":[[1376,5],[1567,5]]}},"keywords":{}}],["categor",{"_index":2633,"title":{},"content":{"74":{"position":[[473,11]]}},"keywords":{}}],["categori",{"_index":1015,"title":{},"content":{"24":{"position":[[77,8]]}},"keywords":{}}],["cathol",{"_index":2225,"title":{},"content":{"53":{"position":[[703,8]]}},"keywords":{}}],["caught",{"_index":3443,"title":{},"content":{"98":{"position":[[518,6]]}},"keywords":{}}],["caus",{"_index":828,"title":{},"content":{"20":{"position":[[1703,5]]},"125":{"position":[[9219,7]]},"153":{"position":[[492,6]]},"195":{"position":[[141,5]]}},"keywords":{}}],["caveat",{"_index":1306,"title":{"147":{"position":[[0,8]]}},"content":{"28":{"position":[[4017,7]]},"82":{"position":[[1158,6]]},"93":{"position":[[429,7]]},"160":{"position":[[3371,7]]},"184":{"position":[[770,7]]}},"keywords":{}}],["ccc",{"_index":553,"title":{},"content":{"13":{"position":[[370,3]]}},"keywords":{}}],["cd",{"_index":3682,"title":{},"content":{"109":{"position":[[151,2]]},"110":{"position":[[361,2]]},"125":{"position":[[3108,2]]}},"keywords":{}}],["cdef",{"_index":5161,"title":{},"content":{"188":{"position":[[970,4],[1046,4],[3524,4]]}},"keywords":{}}],["cdot",{"_index":550,"title":{},"content":{"13":{"position":[[325,5]]},"20":{"position":[[600,5],[693,5]]},"64":{"position":[[543,5],[558,5]]},"65":{"position":[[437,5],[452,5]]}},"keywords":{}}],["celgene'",{"_index":1845,"title":{},"content":{"40":{"position":[[3692,9]]}},"keywords":{}}],["cell",{"_index":4566,"title":{},"content":{"155":{"position":[[774,4]]},"173":{"position":[[1986,4],[2196,4]]},"179":{"position":[[581,4],[656,6],[736,6],[863,5]]},"180":{"position":[[373,5],[461,4]]}},"keywords":{}}],["cell.get_mut",{"_index":5097,"title":{},"content":{"180":{"position":[[503,17]]}},"keywords":{}}],["cell.replace(14",{"_index":5072,"title":{},"content":{"179":{"position":[[545,17],[953,17]]}},"keywords":{}}],["center",{"_index":5012,"title":{},"content":{"175":{"position":[[525,8]]}},"keywords":{}}],["center/data",{"_index":491,"title":{},"content":{"10":{"position":[[240,11]]}},"keywords":{}}],["center/interest",{"_index":493,"title":{},"content":{"10":{"position":[[258,15]]}},"keywords":{}}],["centered_data",{"_index":2983,"title":{},"content":{"90":{"position":[[1010,13],[2395,13]]}},"keywords":{}}],["centered_data.mean(axis=0",{"_index":2986,"title":{},"content":{"90":{"position":[[1106,26],[2491,26]]}},"keywords":{}}],["centered_data.shape[1",{"_index":2985,"title":{},"content":{"90":{"position":[[1064,22],[2449,22]]}},"keywords":{}}],["centered_data[:,lookforward",{"_index":2988,"title":{},"content":{"90":{"position":[[1152,29],[2537,29]]}},"keywords":{}}],["certainli",{"_index":3572,"title":{},"content":{"104":{"position":[[1988,9]]},"121":{"position":[[247,9]]},"173":{"position":[[26,9]]},"181":{"position":[[1020,9]]},"199":{"position":[[889,9]]}},"keywords":{}}],["chain",{"_index":2299,"title":{},"content":{"55":{"position":[[112,5]]},"95":{"position":[[450,5]]},"125":{"position":[[10173,5]]}},"keywords":{}}],["challeng",{"_index":255,"title":{},"content":{"4":{"position":[[730,10]]},"30":{"position":[[669,11]]},"53":{"position":[[1601,10]]},"61":{"position":[[1292,12]]}},"keywords":{}}],["chanc",{"_index":1220,"title":{},"content":{"28":{"position":[[700,6],[2870,7],[3855,6],[4275,6],[4339,7]]},"29":{"position":[[136,6]]},"30":{"position":[[4540,6],[4662,6],[5350,8],[5566,6],[5884,7],[5953,6]]},"49":{"position":[[333,6],[374,6]]}},"keywords":{}}],["chance".format(month",{"_index":1304,"title":{},"content":{"28":{"position":[[3778,27]]}},"keywords":{}}],["chane",{"_index":2206,"title":{},"content":{"53":{"position":[[362,5]]}},"keywords":{}}],["chang",{"_index":170,"title":{},"content":{"3":{"position":[[708,8],[789,8],[934,6]]},"4":{"position":[[1242,7]]},"20":{"position":[[46,6],[222,7]]},"24":{"position":[[123,6]]},"28":{"position":[[707,7]]},"38":{"position":[[1255,6]]},"76":{"position":[[1100,9],[1132,9],[1247,6],[1681,6],[1709,6],[1737,6],[1765,6]]},"97":{"position":[[4835,7],[6016,6],[6370,6]]},"104":{"position":[[1368,8]]},"125":{"position":[[2344,7]]},"160":{"position":[[88,6],[4401,7]]},"161":{"position":[[306,6]]},"163":{"position":[[506,8]]},"175":{"position":[[315,6]]},"178":{"position":[[210,9]]},"183":{"position":[[242,6],[879,7]]},"188":{"position":[[2711,6]]},"189":{"position":[[411,8]]}},"keywords":{}}],["changeswasm",{"_index":4211,"title":{},"content":{"125":{"position":[[11404,11]]}},"keywords":{}}],["channel",{"_index":3838,"title":{},"content":{"117":{"position":[[2022,8]]}},"keywords":{}}],["char",{"_index":4225,"title":{},"content":{"127":{"position":[[210,4]]}},"keywords":{}}],["charact",{"_index":2140,"title":{},"content":{"51":{"position":[[3008,10]]}},"keywords":{}}],["characterist",{"_index":541,"title":{},"content":{"13":{"position":[[121,16]]},"14":{"position":[[261,15]]},"172":{"position":[[436,16]]}},"keywords":{}}],["chars_remain",{"_index":2185,"title":{},"content":{"52":{"position":[[729,15],[866,15],[948,15]]}},"keywords":{}}],["chart",{"_index":492,"title":{},"content":{"10":{"position":[[252,5]]},"28":{"position":[[630,7]]},"30":{"position":[[2283,5],[5547,6]]},"33":{"position":[[412,5]]},"88":{"position":[[38,6],[1720,5],[2039,6],[2154,6]]},"90":{"position":[[81,5]]},"91":{"position":[[1402,7]]},"135":{"position":[[123,6]]}},"keywords":{}}],["chatter",{"_index":5023,"title":{},"content":{"175":{"position":[[987,7]]}},"keywords":{}}],["cheap",{"_index":3468,"title":{},"content":{"101":{"position":[[115,5]]}},"keywords":{}}],["cheat",{"_index":2554,"title":{"68":{"position":[[22,9]]}},"content":{"68":{"position":[[113,8],[307,8]]},"69":{"position":[[185,9]]},"72":{"position":[[36,8],[231,8],[738,9]]},"77":{"position":[[75,8]]}},"keywords":{}}],["check",{"_index":574,"title":{},"content":{"13":{"position":[[931,5]]},"14":{"position":[[1949,5]]},"15":{"position":[[1617,5]]},"24":{"position":[[1050,5],[2326,8],[2492,8]]},"25":{"position":[[770,5],[2215,8]]},"30":{"position":[[2795,5],[4437,8],[4471,5]]},"39":{"position":[[1910,5]]},"61":{"position":[[472,5],[679,6]]},"73":{"position":[[484,5]]},"103":{"position":[[1992,6]]},"123":{"position":[[367,5]]},"125":{"position":[[6451,6],[7518,5]]},"129":{"position":[[242,5]]},"143":{"position":[[538,5]]},"148":{"position":[[361,5]]},"156":{"position":[[1829,5]]},"157":{"position":[[474,5]]},"195":{"position":[[540,5]]}},"keywords":{}}],["checked:"",{"_index":1148,"title":{},"content":{"25":{"position":[[2050,15]]}},"keywords":{}}],["checker",{"_index":3355,"title":{"97":{"position":[[34,8]]}},"content":{"97":{"position":[[435,9]]},"115":{"position":[[3144,8]]},"164":{"position":[[724,8]]}},"keywords":{}}],["checkselectron",{"_index":4144,"title":{},"content":{"125":{"position":[[6896,14]]}},"keywords":{}}],["checksum",{"_index":5029,"title":{},"content":{"175":{"position":[[1202,10],[1422,9],[1593,9]]}},"keywords":{}}],["cheek",{"_index":4027,"title":{},"content":{"125":{"position":[[790,5]]}},"keywords":{}}],["child",{"_index":3792,"title":{},"content":{"115":{"position":[[2869,5],[3000,5]]},"116":{"position":[[2800,5]]}},"keywords":{}}],["china",{"_index":1808,"title":{},"content":{"40":{"position":[[1335,5]]}},"keywords":{}}],["chocolatey",{"_index":3673,"title":{},"content":{"108":{"position":[[591,11]]}},"keywords":{}}],["choic",{"_index":228,"title":{},"content":{"4":{"position":[[147,6]]},"125":{"position":[[8775,7]]},"176":{"position":[[540,6]]}},"keywords":{}}],["choos",{"_index":1595,"title":{},"content":{"34":{"position":[[551,7]]},"74":{"position":[[1531,6]]},"102":{"position":[[1198,6]]},"172":{"position":[[403,6]]},"173":{"position":[[1738,6]]},"178":{"position":[[742,8]]},"181":{"position":[[42,6],[750,6]]}},"keywords":{}}],["chop",{"_index":3571,"title":{},"content":{"104":{"position":[[1740,4]]}},"keywords":{}}],["choreographi",{"_index":4657,"title":{},"content":{"160":{"position":[[506,12]]}},"keywords":{}}],["chose",{"_index":2623,"title":{},"content":{"73":{"position":[[345,5]]},"86":{"position":[[165,5]]}},"keywords":{}}],["chosen",{"_index":1980,"title":{},"content":{"45":{"position":[[1304,6]]}},"keywords":{}}],["christma",{"_index":2220,"title":{},"content":{"53":{"position":[[650,9],[1488,10]]},"57":{"position":[[205,9]]}},"keywords":{}}],["chuck",{"_index":2058,"title":{},"content":{"49":{"position":[[358,5]]},"104":{"position":[[905,5]]}},"keywords":{}}],["circumst",{"_index":2618,"title":{},"content":{"72":{"position":[[498,12]]},"143":{"position":[[318,13]]},"172":{"position":[[2582,14]]},"196":{"position":[[1868,12]]}},"keywords":{}}],["cite",{"_index":2944,"title":{},"content":{"89":{"position":[[85,4]]}},"keywords":{}}],["citi",{"_index":1194,"title":{"28":{"position":[[16,7]]}},"content":{"28":{"position":[[155,7],[337,6],[410,5],[739,4],[857,5],[981,6],[2020,6],[2059,4],[2067,7],[2206,4],[2214,7],[2672,6],[3675,6],[3714,4],[3722,7],[3879,4],[3887,7],[4301,6]]},"29":{"position":[[162,6],[236,4]]},"30":{"position":[[8242,6],[8612,6],[9659,5]]},"53":{"position":[[1016,5]]}},"keywords":{}}],["cities.item",{"_index":1485,"title":{},"content":{"30":{"position":[[9672,15]]}},"keywords":{}}],["cities[i",{"_index":1234,"title":{},"content":{"28":{"position":[[1045,11]]}},"keywords":{}}],["citiesal",{"_index":1288,"title":{},"content":{"28":{"position":[[2662,9]]}},"keywords":{}}],["city_avg_cc(c",{"_index":1257,"title":{},"content":{"28":{"position":[[1790,17],[2027,17],[3682,17]]}},"keywords":{}}],["city_avg_precip(c",{"_index":1303,"title":{},"content":{"28":{"position":[[3538,21]]}},"keywords":{}}],["city_color",{"_index":1233,"title":{},"content":{"28":{"position":[[1031,11]]}},"keywords":{}}],["city_forecast",{"_index":1226,"title":{},"content":{"28":{"position":[[864,14]]},"30":{"position":[[1196,14],[9635,14]]}},"keywords":{}}],["city_forecasts[(c",{"_index":1491,"title":{},"content":{"30":{"position":[[9833,21],[9917,21]]}},"keywords":{}}],["claim",{"_index":1678,"title":{},"content":{"36":{"position":[[5,6]]},"165":{"position":[[258,6]]}},"keywords":{}}],["clarifi",{"_index":3072,"title":{},"content":{"91":{"position":[[164,7]]}},"keywords":{}}],["class",{"_index":880,"title":{},"content":{"22":{"position":[[40,7],[143,5],[464,9],[1088,5]]},"43":{"position":[[702,7],[875,8]]},"45":{"position":[[807,8],[1205,8]]},"54":{"position":[[8,5]]},"86":{"position":[[40,7]]},"93":{"position":[[1457,5]]},"127":{"position":[[581,5],[1231,5]]},"129":{"position":[[1915,5]]}},"keywords":{}}],["classif",{"_index":1962,"title":{},"content":{"45":{"position":[[215,14],[839,15]]}},"keywords":{}}],["classifi",{"_index":1897,"title":{"44":{"position":[[40,12]]}},"content":{"44":{"position":[[78,11],[1788,11]]},"45":{"position":[[3428,12]]}},"keywords":{}}],["clb",{"_index":712,"title":{},"content":{"17":{"position":[[169,6]]},"18":{"position":[[207,7]]},"19":{"position":[[436,7]]},"20":{"position":[[356,7],[2886,7]]}},"keywords":{}}],["clean",{"_index":2293,"title":{},"content":{"54":{"position":[[271,5]]},"193":{"position":[[1001,6]]}},"keywords":{}}],["clear",{"_index":114,"title":{},"content":{"2":{"position":[[605,5]]},"3":{"position":[[519,5]]},"28":{"position":[[2794,6]]},"116":{"position":[[2518,6]]},"181":{"position":[[886,5]]},"183":{"position":[[288,6]]},"189":{"position":[[1861,5]]}},"keywords":{}}],["cli",{"_index":4140,"title":{},"content":{"125":{"position":[[6490,4],[7631,3]]}},"keywords":{}}],["cli/bin/cli.js"",{"_index":4121,"title":{},"content":{"125":{"position":[[5505,20],[5967,20]]}},"keywords":{}}],["click",{"_index":4034,"title":{},"content":{"125":{"position":[[983,6]]}},"keywords":{}}],["client",{"_index":2345,"title":{},"content":{"60":{"position":[[108,6]]},"88":{"position":[[731,6]]},"93":{"position":[[4146,6]]}},"keywords":{}}],["client_id",{"_index":2348,"title":{},"content":{"60":{"position":[[231,10]]},"61":{"position":[[1742,12],[1755,9],[2012,9]]}},"keywords":{}}],["client_secret",{"_index":2347,"title":{},"content":{"60":{"position":[[216,14]]}},"keywords":{}}],["clippi",{"_index":5089,"title":{},"content":{"179":{"position":[[1725,6]]}},"keywords":{}}],["clone",{"_index":3449,"title":{},"content":{"98":{"position":[[858,9]]},"125":{"position":[[3053,5]]},"198":{"position":[[1115,7]]}},"keywords":{}}],["cloneabl",{"_index":5365,"title":{},"content":{"198":{"position":[[997,9]]}},"keywords":{}}],["close",{"_index":720,"title":{"25":{"position":[[31,6]]}},"content":{"17":{"position":[[244,7]]},"24":{"position":[[139,5]]},"25":{"position":[[59,5],[2681,6]]},"26":{"position":[[25,5],[279,9],[799,6]]},"32":{"position":[[561,5],[1087,7],[1251,7],[2307,7]]},"33":{"position":[[134,7],[488,7],[623,7],[785,5],[1090,6]]},"34":{"position":[[418,7],[531,5],[643,7],[3139,5],[3658,6]]},"35":{"position":[[96,7]]},"39":{"position":[[1848,5]]},"40":{"position":[[796,5],[3129,5]]},"41":{"position":[[501,5]]},"43":{"position":[[945,7]]},"51":{"position":[[2143,6]]},"53":{"position":[[1294,5],[2009,5]]},"74":{"position":[[1587,5]]},"75":{"position":[[1251,5]]},"90":{"position":[[3931,7]]},"91":{"position":[[310,7],[2594,7]]},"92":{"position":[[406,7]]},"93":{"position":[[2019,7],[2056,6]]},"102":{"position":[[636,5],[807,5]]},"105":{"position":[[95,5],[3118,5]]},"116":{"position":[[2830,7]]},"121":{"position":[[423,5],[1826,5]]},"122":{"position":[[489,5]]},"123":{"position":[[397,5]]},"128":{"position":[[1677,5]]},"132":{"position":[[80,7]]},"155":{"position":[[269,7]]}},"keywords":{}}],["close"",{"_index":1752,"title":{},"content":{"39":{"position":[[2357,11],[2423,11]]}},"keywords":{}}],["close_column",{"_index":1754,"title":{},"content":{"39":{"position":[[2393,12],[2441,12]]}},"keywords":{}}],["close_v",{"_index":1138,"title":{},"content":{"25":{"position":[[375,9],[423,10]]},"34":{"position":[[1749,10]]},"39":{"position":[[1018,11]]}},"keywords":{}}],["close_vals[day",{"_index":1742,"title":{},"content":{"39":{"position":[[2017,14]]}},"keywords":{}}],["closed='left",{"_index":1243,"title":{},"content":{"28":{"position":[[1352,14],[3152,14]]},"30":{"position":[[1718,14],[3067,14],[4991,14],[6135,14]]}},"keywords":{}}],["closer",{"_index":3190,"title":{},"content":{"93":{"position":[[601,6]]},"97":{"position":[[4799,6]]}},"keywords":{}}],["closur",{"_index":3415,"title":{"196":{"position":[[0,9]]}},"content":{"97":{"position":[[4534,7],[4686,7]]},"147":{"position":[[381,7]]},"159":{"position":[[681,8]]},"179":{"position":[[1509,7]]},"196":{"position":[[413,8],[468,8],[779,7],[859,8],[1002,7],[1277,8]]}},"keywords":{}}],["closure@src/main.rs:31:37",{"_index":3775,"title":{},"content":{"115":{"position":[[1008,28],[1355,28],[2096,28]]}},"keywords":{}}],["cloud",{"_index":1217,"title":{},"content":{"28":{"position":[[670,5],[2109,5],[2706,5],[2822,5],[4161,5],[4365,5]]},"29":{"position":[[98,5]]},"30":{"position":[[832,5],[996,5],[1170,5],[2086,5],[2329,5],[2397,5],[2572,5],[3771,5],[4048,5],[4446,5],[5785,5]]}},"keywords":{}}],["cloud_cover_sampl",{"_index":1247,"title":{},"content":{"28":{"position":[[1461,19],[1738,19]]},"30":{"position":[[1822,19],[1944,19],[3171,19],[3354,19]]}},"keywords":{}}],["cloud_cover_v",{"_index":1244,"title":{},"content":{"28":{"position":[[1367,16],[1526,19]]},"30":{"position":[[1733,16],[1887,19],[3082,16],[3236,19],[3298,17]]}},"keywords":{}}],["cloudcov",{"_index":1237,"title":{},"content":{"28":{"position":[[1126,12]]},"30":{"position":[[1498,12]]}},"keywords":{}}],["cloudi",{"_index":1191,"title":{"27":{"position":[[0,6]]}},"content":{"28":{"position":[[236,6],[315,7],[2629,6]]},"30":{"position":[[581,6],[1075,7],[2819,6],[3572,6],[3996,6],[4345,7],[4702,6],[5739,6],[7675,6]]}},"keywords":{}}],["cloudy_day",{"_index":1383,"title":{},"content":{"30":{"position":[[3256,11]]}},"keywords":{}}],["cmp(12",{"_index":4524,"title":{},"content":{"152":{"position":[[1118,7]]}},"keywords":{}}],["cmp(x",{"_index":4513,"title":{},"content":{"152":{"position":[[473,6]]}},"keywords":{}}],["cmr",{"_index":3944,"title":{},"content":{"122":{"position":[[704,3]]}},"keywords":{}}],["cn∑i=1ndioi>∑i=1ndic_n",{"_index":1529,"title":{},"content":{"32":{"position":[[799,25]]}},"keywords":{}}],["cn∑i=1n−1dioi+cndnon>∑i=1n−1di+dncndnon−dn>∑i=1n−1(di−cndioi)dn(cn−onon)>∑i=1n−1di(1−cnoi)dn>oncn−on∑i=1n−1di(1−1oi)\\begin{align",{"_index":1540,"title":{},"content":{"32":{"position":[[1429,142]]}},"keywords":{}}],["co",{"_index":3896,"title":{},"content":{"121":{"position":[[1332,2]]}},"keywords":{}}],["code",{"_index":116,"title":{"76":{"position":[[11,5]]}},"content":{"2":{"position":[[640,4],[824,5]]},"3":{"position":[[231,4]]},"25":{"position":[[11,4],[114,5]]},"30":{"position":[[930,4],[8127,4]]},"34":{"position":[[1004,5],[1368,4]]},"39":{"position":[[130,4],[242,5]]},"43":{"position":[[238,4]]},"47":{"position":[[1,4]]},"50":{"position":[[272,5]]},"52":{"position":[[28,4]]},"53":{"position":[[267,4]]},"54":{"position":[[247,4]]},"61":{"position":[[2103,4]]},"64":{"position":[[1404,4]]},"73":{"position":[[478,5],[505,5]]},"76":{"position":[[1829,4]]},"86":{"position":[[498,4]]},"88":{"position":[[246,4],[971,4],[2433,4]]},"90":{"position":[[171,4]]},"91":{"position":[[403,4],[1733,4],[1814,4],[2745,4],[5138,4],[5515,4]]},"92":{"position":[[223,4],[557,4],[1680,4],[1839,4]]},"93":{"position":[[1240,4],[3795,4]]},"97":{"position":[[2985,4],[3779,4],[5469,5],[5577,4]]},"98":{"position":[[376,4]]},"103":{"position":[[728,4]]},"108":{"position":[[128,4]]},"109":{"position":[[496,4]]},"111":{"position":[[101,4]]},"112":{"position":[[121,5],[255,4],[349,4],[474,4],[1220,5],[1379,5]]},"113":{"position":[[80,4],[170,4],[255,4],[416,4],[549,4],[1094,4]]},"115":{"position":[[77,4],[2829,5]]},"116":{"position":[[2763,4]]},"117":{"position":[[66,5]]},"120":{"position":[[303,4]]},"121":{"position":[[137,4],[188,4],[409,5],[626,4],[715,4],[1127,4],[1279,4],[1765,4],[2245,4]]},"124":{"position":[[690,5]]},"125":{"position":[[659,4],[2749,4],[3776,4],[6542,4],[6777,4]]},"128":{"position":[[80,4],[380,4]]},"129":{"position":[[1353,4]]},"130":{"position":[[501,5]]},"133":{"position":[[140,5]]},"136":{"position":[[178,4]]},"139":{"position":[[226,4],[558,4],[967,4]]},"142":{"position":[[182,4]]},"143":{"position":[[92,4],[279,4],[407,4],[554,4]]},"147":{"position":[[41,4]]},"148":{"position":[[54,4],[186,4]]},"152":{"position":[[866,5]]},"153":{"position":[[103,4],[438,5]]},"155":{"position":[[1273,5]]},"158":{"position":[[36,5],[83,5]]},"160":{"position":[[454,4],[2640,4],[3083,4],[3578,4]]},"163":{"position":[[785,4],[2277,4],[2496,4]]},"164":{"position":[[1327,4]]},"169":{"position":[[156,4]]},"172":{"position":[[2074,5],[2430,4]]},"173":{"position":[[1,4],[49,4],[1479,4]]},"174":{"position":[[213,5],[345,4]]},"178":{"position":[[468,5]]},"181":{"position":[[1032,4]]},"183":{"position":[[151,5]]},"185":{"position":[[493,5]]},"186":{"position":[[507,4]]},"188":{"position":[[226,4],[602,4]]},"189":{"position":[[298,4],[375,4],[770,4],[1921,4]]},"190":{"position":[[141,4],[710,4]]},"193":{"position":[[711,5]]},"196":{"position":[[1465,4]]},"199":{"position":[[87,4]]}},"keywords":{}}],["codeandth",{"_index":3924,"title":{},"content":{"121":{"position":[[2500,10]]}},"keywords":{}}],["codeat",{"_index":5227,"title":{},"content":{"189":{"position":[[170,6]]}},"keywords":{}}],["codec",{"_index":3651,"title":{},"content":{"106":{"position":[[425,6]]}},"keywords":{}}],["codecontain",{"_index":5223,"title":{},"content":{"188":{"position":[[4301,12]]}},"keywords":{}}],["codegen",{"_index":3735,"title":{},"content":{"113":{"position":[[587,7]]}},"keywords":{}}],["coef",{"_index":2684,"title":{},"content":{"76":{"position":[[424,5],[458,5],[713,5],[758,5],[783,7]]}},"keywords":{}}],["coef_rang",{"_index":2760,"title":{},"content":{"78":{"position":[[418,10]]}},"keywords":{}}],["cognit",{"_index":4662,"title":{},"content":{"160":{"position":[[689,9]]}},"keywords":{}}],["coin",{"_index":1130,"title":{},"content":{"24":{"position":[[3238,4]]},"26":{"position":[[102,4],[254,4]]}},"keywords":{}}],["coin_toss",{"_index":2742,"title":{},"content":{"76":{"position":[[3062,9],[3094,9]]}},"keywords":{}}],["col",{"_index":1900,"title":{},"content":{"44":{"position":[[205,4],[244,5]]}},"keywords":{}}],["cold",{"_index":298,"title":{},"content":{"4":{"position":[[1508,4]]},"53":{"position":[[1046,4]]}},"keywords":{}}],["collect",{"_index":4341,"title":{"156":{"position":[[0,12]]}},"content":{"132":{"position":[[167,10]]},"156":{"position":[[1,10],[258,11],[404,11],[472,11]]},"160":{"position":[[1071,8]]},"172":{"position":[[9,11],[44,10],[142,9],[209,9],[535,11],[666,10]]},"176":{"position":[[475,10]]},"199":{"position":[[587,10],[1024,11]]}},"keywords":{}}],["collection.java",{"_index":4902,"title":{},"content":{"172":{"position":[[348,15]]}},"keywords":{}}],["collector",{"_index":3446,"title":{},"content":{"98":{"position":[[583,9]]}},"keywords":{}}],["collus",{"_index":2947,"title":{},"content":{"89":{"position":[[237,10]]}},"keywords":{}}],["color",{"_index":429,"title":{},"content":{"7":{"position":[[1044,5],[1148,6],[1172,6]]},"134":{"position":[[409,7]]}},"keywords":{}}],["color='b",{"_index":2882,"title":{},"content":{"88":{"position":[[1594,10],[1921,10],[2567,10],[2668,10]]}},"keywords":{}}],["color='g",{"_index":2927,"title":{},"content":{"88":{"position":[[3051,10],[3436,10]]},"91":{"position":[[812,10],[1282,10]]}},"keywords":{}}],["color=city_colors[c",{"_index":1278,"title":{},"content":{"28":{"position":[[2287,24],[3960,24]]}},"keywords":{}}],["color=color",{"_index":438,"title":{},"content":{"7":{"position":[[1230,13]]}},"keywords":{}}],["color=palette[x",{"_index":1368,"title":{},"content":{"30":{"position":[[2234,17],[3719,17],[3942,17],[5498,17],[6799,17],[7022,17]]}},"keywords":{}}],["columbu",{"_index":2972,"title":{},"content":{"90":{"position":[[602,8]]}},"keywords":{}}],["column",{"_index":1953,"title":{},"content":{"44":{"position":[[1844,7]]},"102":{"position":[[1014,7]]}},"keywords":{}}],["combin",{"_index":4768,"title":{},"content":{"163":{"position":[[669,9]]}},"keywords":{}}],["combust",{"_index":4506,"title":{},"content":{"150":{"position":[[869,7]]}},"keywords":{}}],["come",{"_index":74,"title":{},"content":{"2":{"position":[[5,5]]},"3":{"position":[[5,5]]},"4":{"position":[[316,5]]},"30":{"position":[[783,5],[7984,6]]},"40":{"position":[[2124,4]]},"46":{"position":[[576,4]]},"51":{"position":[[3108,4]]},"57":{"position":[[507,5]]},"61":{"position":[[58,6]]},"64":{"position":[[200,5]]},"65":{"position":[[5,5],[119,4]]},"66":{"position":[[683,6]]},"69":{"position":[[126,4]]},"83":{"position":[[57,4],[200,4]]},"95":{"position":[[179,6],[390,6]]},"96":{"position":[[1521,4]]},"97":{"position":[[1447,4]]},"102":{"position":[[79,5]]},"103":{"position":[[27,5],[2339,5]]},"120":{"position":[[356,4]]},"125":{"position":[[9549,6],[11604,5]]},"127":{"position":[[41,5]]},"133":{"position":[[374,5]]},"152":{"position":[[24,5]]},"155":{"position":[[238,5]]},"157":{"position":[[327,5]]},"158":{"position":[[364,5]]},"188":{"position":[[284,5]]},"192":{"position":[[19,5]]},"197":{"position":[[16,4]]}},"keywords":{}}],["comfort",{"_index":4818,"title":{},"content":{"164":{"position":[[1554,11]]}},"keywords":{}}],["coming.i'm",{"_index":3441,"title":{},"content":{"98":{"position":[[415,10]]}},"keywords":{}}],["command",{"_index":3677,"title":{},"content":{"108":{"position":[[841,7]]},"112":{"position":[[145,8],[577,7],[736,7]]},"124":{"position":[[214,7]]},"173":{"position":[[634,7]]}},"keywords":{}}],["comment",{"_index":3729,"title":{},"content":{"113":{"position":[[233,8]]},"122":{"position":[[628,8]]},"148":{"position":[[582,8]]}},"keywords":{}}],["common",{"_index":4591,"title":{},"content":{"156":{"position":[[317,6]]}},"keywords":{}}],["commun",{"_index":5271,"title":{},"content":{"193":{"position":[[38,11]]}},"keywords":{}}],["compani",{"_index":2948,"title":{"149":{"position":[[11,9]]}},"content":{"89":{"position":[[254,7]]},"90":{"position":[[3479,7]]},"93":{"position":[[717,9],[1228,10],[1854,7]]},"150":{"position":[[742,8]]}},"keywords":{}}],["compar",{"_index":989,"title":{},"content":{"23":{"position":[[51,7]]},"28":{"position":[[485,9]]},"30":{"position":[[7200,8],[8002,7]]},"102":{"position":[[684,10]]},"152":{"position":[[649,7]]},"161":{"position":[[725,8]]},"172":{"position":[[2362,9]]},"189":{"position":[[579,10]]}},"keywords":{}}],["comparison",{"_index":1012,"title":{"24":{"position":[[12,11]]}},"content":{"105":{"position":[[3147,11]]},"112":{"position":[[1564,11]]},"121":{"position":[[2471,11]]},"152":{"position":[[794,10]]}},"keywords":{}}],["compat",{"_index":157,"title":{},"content":{"3":{"position":[[466,13],[1416,16]]},"124":{"position":[[33,10]]},"125":{"position":[[6819,10]]}},"keywords":{}}],["compens",{"_index":852,"title":{},"content":{"20":{"position":[[2447,10]]}},"keywords":{}}],["competit",{"_index":699,"title":{"17":{"position":[[8,11]]}},"content":{},"keywords":{}}],["compil",{"_index":93,"title":{"151":{"position":[[21,8]]}},"content":{"2":{"position":[[289,8]]},"96":{"position":[[1889,7],[2033,7]]},"97":{"position":[[42,8],[460,8],[480,7],[1748,7],[4168,8]]},"111":{"position":[[201,9],[524,8],[558,7],[701,8]]},"115":{"position":[[857,8]]},"116":{"position":[[2456,8],[2853,8]]},"121":{"position":[[2109,8],[2256,9]]},"125":{"position":[[6108,7],[6525,7],[6752,7],[7133,8],[7682,9]]},"127":{"position":[[694,8]]},"128":{"position":[[307,8],[1364,8]]},"129":{"position":[[383,8],[1365,8]]},"152":{"position":[[582,8],[1662,8]]},"153":{"position":[[352,8],[868,8],[1033,8]]},"155":{"position":[[1610,8]]},"156":{"position":[[701,8]]},"159":{"position":[[438,8],[518,8]]},"160":{"position":[[540,9],[651,8],[962,8],[2987,8],[3109,8],[3242,8]]},"172":{"position":[[1744,12],[1776,8],[1918,8],[2130,11],[2472,8]]},"174":{"position":[[281,8]]},"178":{"position":[[158,8],[408,8],[669,7],[686,8]]},"180":{"position":[[194,7],[528,8],[551,8]]},"181":{"position":[[29,8],[356,8],[737,8]]},"183":{"position":[[623,8],[834,8]]},"184":{"position":[[983,7]]},"185":{"position":[[545,7]]},"188":{"position":[[439,11]]},"189":{"position":[[76,9],[125,8],[275,8],[510,8],[781,8],[1516,12],[1599,8],[1969,12]]},"190":{"position":[[573,9]]},"192":{"position":[[566,8]]},"193":{"position":[[257,8],[825,8],[1244,8],[1968,8],[2923,8],[3775,8]]},"194":{"position":[[436,8],[535,8]]},"195":{"position":[[979,8]]},"196":{"position":[[1195,8],[1295,8],[1606,8],[1808,8],[1893,8]]},"197":{"position":[[1421,8]]},"198":{"position":[[1169,8]]},"199":{"position":[[1709,8]]}},"keywords":{}}],["compiler'",{"_index":5277,"title":{},"content":{"193":{"position":[[739,10]]},"196":{"position":[[609,10]]}},"keywords":{}}],["compiler)th",{"_index":3692,"title":{},"content":{"109":{"position":[[522,12]]}},"keywords":{}}],["compilercommanddynam",{"_index":3711,"title":{},"content":{"111":{"position":[[858,27]]}},"keywords":{}}],["complain",{"_index":1321,"title":{"30":{"position":[[0,11]]}},"content":{"30":{"position":[[38,11],[2479,12],[7647,9]]},"112":{"position":[[181,12]]},"116":{"position":[[2897,9]]},"139":{"position":[[15,11]]}},"keywords":{}}],["complaint",{"_index":3434,"title":{},"content":{"97":{"position":[[6138,9]]}},"keywords":{}}],["complet",{"_index":2194,"title":{},"content":{"53":{"position":[[23,10]]},"75":{"position":[[1119,8]]},"88":{"position":[[114,9]]},"153":{"position":[[974,9]]},"173":{"position":[[1199,9]]},"188":{"position":[[3261,10]]}},"keywords":{}}],["complex",{"_index":2,"title":{"0":{"position":[[23,7]]}},"content":{"3":{"position":[[1159,10]]},"4":{"position":[[1028,11]]},"97":{"position":[[1215,8],[2963,7]]},"109":{"position":[[99,7]]},"117":{"position":[[494,8]]},"125":{"position":[[7109,10]]},"160":{"position":[[33,7],[229,10],[498,7]]},"163":{"position":[[252,8],[742,7],[2181,7]]},"196":{"position":[[1741,9]]},"199":{"position":[[1438,7]]}},"keywords":{}}],["complex"",{"_index":272,"title":{},"content":{"4":{"position":[[966,15]]}},"keywords":{}}],["complexitywebpack",{"_index":264,"title":{},"content":{"4":{"position":[[845,17]]}},"keywords":{}}],["complic",{"_index":2344,"title":{},"content":{"59":{"position":[[166,11]]},"73":{"position":[[141,12]]},"85":{"position":[[160,11]]},"108":{"position":[[562,12]]},"121":{"position":[[777,11]]},"125":{"position":[[3671,11],[6939,12]]},"129":{"position":[[770,12],[2684,12]]},"190":{"position":[[524,12]]}},"keywords":{}}],["compon",{"_index":1977,"title":{},"content":{"45":{"position":[[1092,10]]},"102":{"position":[[1185,10],[1243,11],[1333,11]]},"103":{"position":[[1947,10]]},"104":{"position":[[375,9],[480,10],[664,10],[888,11],[925,10],[1097,10],[1201,10],[1456,11]]},"105":{"position":[[62,10],[146,10],[670,10],[3077,10]]},"106":{"position":[[227,9],[581,11]]},"198":{"position":[[755,10]]}},"keywords":{}}],["component_byt",{"_index":3586,"title":{},"content":{"105":{"position":[[764,15]]}},"keywords":{}}],["compos",{"_index":3817,"title":{},"content":{"117":{"position":[[302,7]]}},"keywords":{}}],["comprehens",{"_index":1028,"title":{},"content":{"24":{"position":[[536,13]]},"25":{"position":[[261,13]]},"30":{"position":[[9549,13]]},"121":{"position":[[2414,14],[2444,15],[2614,14]]}},"keywords":{}}],["compress",{"_index":3455,"title":{"99":{"position":[[10,11]]},"100":{"position":[[32,11]]},"101":{"position":[[30,12]]},"102":{"position":[[12,11]]}},"content":{"100":{"position":[[433,11]]},"101":{"position":[[228,8],[346,11],[461,8],[550,11],[698,12],[811,11]]},"102":{"position":[[214,12],[377,11]]},"105":{"position":[[464,8],[925,11],[1081,10]]},"106":{"position":[[33,11]]}},"keywords":{}}],["compress(bytestr",{"_index":3594,"title":{},"content":{"105":{"position":[[1094,20]]}},"keywords":{}}],["compression_attempt",{"_index":3596,"title":{},"content":{"105":{"position":[[1148,20],[1751,20],[1900,20]]}},"keywords":{}}],["comput",{"_index":453,"title":{"9":{"position":[[0,9]]}},"content":{"11":{"position":[[258,7]]},"12":{"position":[[74,9]]},"44":{"position":[[1980,11]]},"45":{"position":[[1365,8],[2524,13]]},"53":{"position":[[83,8]]},"74":{"position":[[1293,13],[1414,8],[1613,8]]},"86":{"position":[[908,7]]},"128":{"position":[[166,9]]},"132":{"position":[[926,8]]},"173":{"position":[[1667,8]]},"174":{"position":[[1028,8]]},"175":{"position":[[266,9]]},"189":{"position":[[2074,8]]}},"keywords":{}}],["concat",{"_index":3345,"title":{},"content":{"96":{"position":[[1543,7],[1853,7],[2057,8]]}},"keywords":{}}],["concat!("y",{"_index":3347,"title":{},"content":{"96":{"position":[[1706,17]]}},"keywords":{}}],["concaten",{"_index":3343,"title":{},"content":{"96":{"position":[[1460,11]]}},"keywords":{}}],["concept",{"_index":2323,"title":{},"content":{"58":{"position":[[144,7]]},"125":{"position":[[10204,8],[10454,8]]}},"keywords":{}}],["concern",{"_index":761,"title":{},"content":{"20":{"position":[[138,9]]},"30":{"position":[[9200,9]]},"33":{"position":[[373,9]]},"44":{"position":[[1009,10]]},"86":{"position":[[231,9]]},"102":{"position":[[339,8]]},"164":{"position":[[238,8]]},"166":{"position":[[234,9]]},"176":{"position":[[1353,8]]}},"keywords":{}}],["conclud",{"_index":2614,"title":{},"content":{"72":{"position":[[208,8],[712,8]]},"188":{"position":[[4363,9]]}},"keywords":{}}],["conclus",{"_index":1311,"title":{"29":{"position":[[0,11]]},"72":{"position":[[10,11]]},"83":{"position":[[0,11]]},"93":{"position":[[0,10]]},"98":{"position":[[0,11]]},"106":{"position":[[0,12]]},"124":{"position":[[12,11]]},"130":{"position":[[0,11]]},"137":{"position":[[0,11]]},"148":{"position":[[0,11]]},"170":{"position":[[0,11]]},"190":{"position":[[0,11]]}},"content":{"30":{"position":[[7391,11]]}},"keywords":{}}],["concurr",{"_index":3201,"title":{},"content":{"93":{"position":[[1419,10]]}},"keywords":{}}],["condit",{"_index":1442,"title":{},"content":{"30":{"position":[[8021,10]]},"51":{"position":[[728,11]]},"160":{"position":[[3356,10]]},"188":{"position":[[4209,10]]}},"keywords":{}}],["confer",{"_index":2276,"title":{},"content":{"53":{"position":[[1508,10]]}},"keywords":{}}],["confid",{"_index":2294,"title":{},"content":{"55":{"position":[[12,9]]},"170":{"position":[[145,9]]}},"keywords":{}}],["configur",{"_index":168,"title":{},"content":{"3":{"position":[[658,14],[729,14],[953,14]]},"97":{"position":[[6257,9]]}},"keywords":{}}],["confirm",{"_index":1285,"title":{},"content":{"28":{"position":[[2520,9],[4130,7]]},"30":{"position":[[7620,12]]}},"keywords":{}}],["confus",{"_index":196,"title":{},"content":{"3":{"position":[[1186,10]]}},"keywords":{}}],["congest",{"_index":5016,"title":{},"content":{"175":{"position":[[652,10]]}},"keywords":{}}],["congratul",{"_index":3982,"title":{},"content":{"123":{"position":[[726,15]]}},"keywords":{}}],["connect",{"_index":50,"title":{},"content":{"1":{"position":[[567,10]]},"173":{"position":[[1649,9]]},"175":{"position":[[138,10],[1011,10]]}},"keywords":{}}],["conrod",{"_index":4044,"title":{},"content":{"125":{"position":[[1326,7]]}},"keywords":{}}],["consequ",{"_index":5299,"title":{},"content":{"193":{"position":[[1992,11]]}},"keywords":{}}],["conserv",{"_index":1855,"title":{},"content":{"41":{"position":[[558,12]]}},"keywords":{}}],["consid",{"_index":1584,"title":{},"content":{"33":{"position":[[1036,8]]},"40":{"position":[[3643,8]]},"72":{"position":[[386,11]]},"132":{"position":[[206,10]]}},"keywords":{}}],["consider",{"_index":2320,"title":{"58":{"position":[[12,15]]}},"content":{"58":{"position":[[62,14]]}},"keywords":{}}],["consist",{"_index":1166,"title":{},"content":{"25":{"position":[[2802,13]]},"28":{"position":[[4255,12]]},"40":{"position":[[1035,12]]},"181":{"position":[[945,11]]}},"keywords":{}}],["const",{"_index":3772,"title":{"178":{"position":[[0,5]]}},"content":{"115":{"position":[[957,7],[1189,7],[1271,7],[1536,7],[1928,7],[2277,7]]},"116":{"position":[[956,7],[1141,7],[1223,7],[1441,7],[1833,7],[2135,7],[2680,7]]},"159":{"position":[[410,5]]},"163":{"position":[[1678,5]]},"178":{"position":[[136,6],[524,5],[536,5],[640,5],[717,5]]},"179":{"position":[[771,5],[857,5],[1245,5],[1423,7]]},"180":{"position":[[35,5],[124,5],[367,5]]},"181":{"position":[[57,5],[72,5],[667,5],[926,5],[997,5]]},"182":{"position":[[33,5],[479,6]]},"183":{"position":[[39,5],[107,5],[224,5]]},"184":{"position":[[442,5],[550,5],[814,5]]}},"keywords":{}}],["constant",{"_index":3528,"title":{},"content":{"103":{"position":[[1114,11]]},"152":{"position":[[618,8]]},"179":{"position":[[126,9]]}},"keywords":{}}],["constant_values=0",{"_index":3529,"title":{},"content":{"103":{"position":[[1126,18]]}},"keywords":{}}],["constantli",{"_index":5259,"title":{},"content":{"190":{"position":[[271,10]]}},"keywords":{}}],["constitut",{"_index":1681,"title":{},"content":{"36":{"position":[[115,10]]}},"keywords":{}}],["constraint",{"_index":837,"title":{},"content":{"20":{"position":[[2014,11]]},"160":{"position":[[1795,11],[2485,11]]}},"keywords":{}}],["constraints=constraint",{"_index":844,"title":{},"content":{"20":{"position":[[2245,24]]}},"keywords":{}}],["construct",{"_index":509,"title":{},"content":{"11":{"position":[[101,9]]},"51":{"position":[[2776,12],[3418,13]]},"117":{"position":[[941,9]]}},"keywords":{}}],["contact",{"_index":1889,"title":{},"content":{"43":{"position":[[1332,7],[1382,10]]}},"keywords":{}}],["contain",{"_index":1969,"title":{},"content":{"45":{"position":[[467,9]]},"61":{"position":[[1998,10],[2179,8],[2256,8]]},"96":{"position":[[1018,7]]},"97":{"position":[[2975,9]]},"104":{"position":[[235,10],[390,8]]},"113":{"position":[[874,9]]},"115":{"position":[[172,10]]},"116":{"position":[[272,10]]},"117":{"position":[[1064,10]]},"156":{"position":[[239,8]]},"165":{"position":[[742,8],[796,8]]},"185":{"position":[[278,7]]}},"keywords":{}}],["containwith",{"_index":5218,"title":{},"content":{"188":{"position":[[4118,11]]}},"keywords":{}}],["contemporari",{"_index":3857,"title":{},"content":{"120":{"position":[[689,12]]}},"keywords":{}}],["contend",{"_index":1822,"title":{},"content":{"40":{"position":[[2436,9]]}},"keywords":{}}],["content",{"_index":130,"title":{},"content":{"2":{"position":[[861,7]]},"22":{"position":[[1507,10],[1747,9],[1818,8]]},"49":{"position":[[648,8],[698,7]]},"95":{"position":[[158,7]]},"97":{"position":[[5020,7],[5142,7]]},"98":{"position":[[163,7]]},"109":{"position":[[214,7]]},"110":{"position":[[411,7]]},"111":{"position":[[281,7]]},"112":{"position":[[959,7]]},"113":{"position":[[917,7],[1453,7],[1977,7],[2473,7]]},"115":{"position":[[202,7],[2763,7]]},"116":{"position":[[302,7]]},"117":{"position":[[1094,7]]},"125":{"position":[[2013,7]]},"156":{"position":[[48,8]]},"159":{"position":[[920,8],[1016,8],[1096,8]]},"160":{"position":[[3730,7],[3971,8]]},"164":{"position":[[409,8]]},"192":{"position":[[104,9],[447,7]]}},"keywords":{}}],["context",{"_index":1399,"title":{},"content":{"30":{"position":[[4285,7]]},"51":{"position":[[3394,7]]},"53":{"position":[[744,7]]},"58":{"position":[[863,8]]},"66":{"position":[[120,8]]},"117":{"position":[[228,7]]},"173":{"position":[[1214,7],[1456,7],[1775,7]]},"175":{"position":[[961,8]]},"176":{"position":[[263,7]]},"190":{"position":[[168,7]]}},"keywords":{}}],["contigu",{"_index":5331,"title":{},"content":{"196":{"position":[[924,11]]}},"keywords":{}}],["continu",{"_index":72,"title":{"2":{"position":[[0,10]]}},"content":{"66":{"position":[[161,8]]},"75":{"position":[[764,8]]},"89":{"position":[[652,8],[734,8]]},"93":{"position":[[1107,8]]},"139":{"position":[[818,8]]},"143":{"position":[[186,8]]},"188":{"position":[[711,8]]}},"keywords":{}}],["contrari",{"_index":1173,"title":{},"content":{"26":{"position":[[531,8]]}},"keywords":{}}],["contrast",{"_index":4239,"title":{},"content":{"127":{"position":[[1001,9]]},"164":{"position":[[1138,9]]},"166":{"position":[[444,9]]},"175":{"position":[[234,9]]}},"keywords":{}}],["contribut",{"_index":3986,"title":{},"content":{"123":{"position":[[1012,12]]},"150":{"position":[[990,11]]},"161":{"position":[[149,12]]},"165":{"position":[[988,11]]}},"keywords":{}}],["contributor",{"_index":3974,"title":{},"content":{"123":{"position":[[293,11],[352,11],[592,11],[1029,12]]}},"keywords":{}}],["control",{"_index":2654,"title":{},"content":{"74":{"position":[[1464,7]]},"117":{"position":[[286,8]]},"125":{"position":[[4702,7],[7560,8]]},"128":{"position":[[700,7],[1458,7]]},"173":{"position":[[2130,10]]},"175":{"position":[[639,8],[663,7]]},"189":{"position":[[198,10]]},"198":{"position":[[576,8]]}},"keywords":{}}],["controversi",{"_index":3977,"title":{},"content":{"123":{"position":[[526,14]]}},"keywords":{}}],["conundrum",{"_index":4021,"title":{},"content":{"125":{"position":[[623,9]]}},"keywords":{}}],["conv_count",{"_index":2732,"title":{},"content":{"76":{"position":[[2267,12],[2407,10]]}},"keywords":{}}],["conv_count=10",{"_index":2719,"title":{},"content":{"76":{"position":[[1906,14]]}},"keywords":{}}],["convent",{"_index":5274,"title":{},"content":{"193":{"position":[[339,11],[356,10],[651,11]]}},"keywords":{}}],["converg",{"_index":2812,"title":{},"content":{"83":{"position":[[266,8]]},"86":{"position":[[503,9]]}},"keywords":{}}],["convert",{"_index":3115,"title":{},"content":{"91":{"position":[[2118,7]]},"103":{"position":[[198,7]]},"116":{"position":[[27,7]]}},"keywords":{}}],["convinc",{"_index":4180,"title":{},"content":{"125":{"position":[[9194,9]]}},"keywords":{}}],["cookbook",{"_index":3659,"title":{"107":{"position":[[10,9]]},"114":{"position":[[10,9]]}},"content":{},"keywords":{}}],["cool",{"_index":3363,"title":{"126":{"position":[[34,5]]}},"content":{"97":{"position":[[221,5]]},"98":{"position":[[1188,5]]},"106":{"position":[[995,4]]},"125":{"position":[[74,4],[11709,5]]},"129":{"position":[[597,4]]},"130":{"position":[[136,4],[397,4]]},"139":{"position":[[806,5]]}},"keywords":{}}],["coolest",{"_index":3357,"title":{},"content":{"97":{"position":[[15,7]]}},"keywords":{}}],["coordin",{"_index":1448,"title":{},"content":{"30":{"position":[[8415,10]]},"112":{"position":[[1716,12]]}},"keywords":{}}],["copi",{"_index":975,"title":{"181":{"position":[[0,8]]},"198":{"position":[[0,4]]}},"content":{"22":{"position":[[2675,4]]},"76":{"position":[[1380,5]]},"90":{"position":[[505,4]]},"97":{"position":[[5744,4],[5984,5]]},"128":{"position":[[550,4],[783,4],[950,7],[1313,7],[1543,7]]},"159":{"position":[[461,4],[886,4]]},"164":{"position":[[1297,4]]},"165":{"position":[[440,4]]},"178":{"position":[[426,4],[712,4]]},"181":{"position":[[52,4],[760,4]]},"183":{"position":[[141,6]]},"196":{"position":[[193,8]]},"198":{"position":[[34,4],[270,5],[358,4],[401,7],[428,7],[590,4],[624,4],[776,5],[824,5],[1056,6]]}},"keywords":{}}],["copy(retrieve_data(url",{"_index":984,"title":{},"content":{"22":{"position":[[2923,25]]}},"keywords":{}}],["copyif",{"_index":5362,"title":{},"content":{"198":{"position":[[730,6]]}},"keywords":{}}],["copyto",{"_index":5359,"title":{},"content":{"198":{"position":[[472,6]]}},"keywords":{}}],["core",{"_index":4942,"title":{},"content":{"173":{"position":[[390,5],[429,5],[527,5],[596,5],[773,5],[1757,4],[1899,4]]}},"keywords":{}}],["core::ptr::drop_in_plac",{"_index":4290,"title":{},"content":{"129":{"position":[[694,24]]}},"keywords":{}}],["core::ptr::real_drop_in_plac",{"_index":5351,"title":{},"content":{"197":{"position":[[1261,32]]}},"keywords":{}}],["corert",{"_index":4931,"title":{},"content":{"172":{"position":[[2174,7]]}},"keywords":{}}],["coreutil",{"_index":3996,"title":{},"content":{"124":{"position":[[274,9],[318,9]]}},"keywords":{}}],["corpor",{"_index":2289,"title":{},"content":{"54":{"position":[[74,9],[98,9]]}},"keywords":{}}],["correct",{"_index":482,"title":{},"content":{"10":{"position":[[78,7]]},"20":{"position":[[1162,7]]},"62":{"position":[[1308,7]]},"88":{"position":[[3796,9]]},"132":{"position":[[722,7],[742,7]]},"160":{"position":[[4283,9]]}},"keywords":{}}],["correctli",{"_index":485,"title":{},"content":{"10":{"position":[[114,10]]},"71":{"position":[[1174,10]]},"89":{"position":[[170,9]]},"112":{"position":[[27,9]]},"121":{"position":[[1770,10]]},"148":{"position":[[146,10]]},"167":{"position":[[309,10]]},"175":{"position":[[826,10]]},"197":{"position":[[1082,9]]}},"keywords":{}}],["correctth",{"_index":3164,"title":{},"content":{"91":{"position":[[4791,10]]}},"keywords":{}}],["correspond",{"_index":4596,"title":{},"content":{"156":{"position":[[580,13]]}},"keywords":{}}],["corrupt",{"_index":4677,"title":{},"content":{"160":{"position":[[1421,7]]},"195":{"position":[[923,10]]}},"keywords":{}}],["cost",{"_index":5037,"title":{},"content":{"175":{"position":[[1641,4]]},"178":{"position":[[300,4]]}},"keywords":{}}],["costs;electron",{"_index":4218,"title":{},"content":{"125":{"position":[[11571,14]]}},"keywords":{}}],["cough",{"_index":4155,"title":{},"content":{"125":{"position":[[8170,7]]}},"keywords":{}}],["couldn't",{"_index":183,"title":{},"content":{"3":{"position":[[974,8],[1351,8],[1505,8]]},"4":{"position":[[1369,8]]},"125":{"position":[[2580,8]]}},"keywords":{}}],["count",{"_index":1401,"title":{},"content":{"30":{"position":[[4365,5],[5828,5]]},"40":{"position":[[3554,5]]},"51":{"position":[[1538,5]]},"91":{"position":[[1556,5]]},"172":{"position":[[169,5]]},"193":{"position":[[2335,5]]},"196":{"position":[[1434,5],[1726,6]]}},"keywords":{}}],["count_dict",{"_index":1070,"title":{},"content":{"24":{"position":[[1635,10]]},"25":{"position":[[1334,10]]}},"keywords":{}}],["count_dict[index",{"_index":1083,"title":{},"content":{"24":{"position":[[2126,17]]},"25":{"position":[[1850,17]]}},"keywords":{}}],["counter",{"_index":930,"title":{},"content":{"22":{"position":[[1238,7]]},"172":{"position":[[1646,8]]}},"keywords":{}}],["counterpart",{"_index":4606,"title":{},"content":{"157":{"position":[[166,12]]},"159":{"position":[[1169,12]]}},"keywords":{}}],["countgo",{"_index":4573,"title":{},"content":{"155":{"position":[[1169,9]]}},"keywords":{}}],["coupl",{"_index":1565,"title":{},"content":{"33":{"position":[[61,6]]},"34":{"position":[[69,6]]},"46":{"position":[[18,6]]},"54":{"position":[[189,6]]},"55":{"position":[[38,6]]},"66":{"position":[[483,6]]},"72":{"position":[[424,6]]},"77":{"position":[[20,6]]},"89":{"position":[[515,6]]},"90":{"position":[[4003,6]]},"91":{"position":[[109,6]]},"97":{"position":[[888,6],[5178,6]]},"100":{"position":[[320,6]]},"102":{"position":[[1144,6]]},"105":{"position":[[2552,6]]},"112":{"position":[[1067,6]]},"121":{"position":[[584,6],[957,6]]},"125":{"position":[[123,6],[4737,6],[10828,6]]},"179":{"position":[[92,6]]}},"keywords":{}}],["coupledifferentthread",{"_index":3950,"title":{},"content":{"122":{"position":[[944,22]]}},"keywords":{}}],["coupon",{"_index":546,"title":{},"content":{"13":{"position":[[230,6],[305,6],[378,6],[578,6],[687,7],[1234,7]]},"14":{"position":[[134,6],[152,7],[414,6],[649,6],[815,6],[878,6],[936,7],[989,6],[1150,6],[1408,6],[1544,7],[1688,6],[1850,6],[2295,7]]},"15":{"position":[[152,7],[259,6],[329,6],[388,7],[446,7],[508,7],[777,6],[915,7],[1078,6],[1356,6],[1965,7]]}},"keywords":{}}],["coupon*i",{"_index":570,"title":{},"content":{"13":{"position":[[831,9]]}},"keywords":{}}],["coupon_barri",{"_index":643,"title":{},"content":{"14":{"position":[[1354,14],[1508,15],[1773,14],[2259,15]]},"15":{"position":[[723,14],[879,15],[1166,14],[1929,15]]}},"keywords":{}}],["cours",{"_index":1673,"title":{},"content":{"35":{"position":[[384,6]]},"71":{"position":[[1456,6]]},"86":{"position":[[456,6]]},"97":{"position":[[5316,8]]},"124":{"position":[[74,6]]},"125":{"position":[[639,6],[2263,6]]}},"keywords":{}}],["cover",{"_index":1218,"title":{},"content":{"28":{"position":[[676,5],[2183,5],[2712,5],[2828,5],[4167,6],[4371,6]]},"29":{"position":[[104,5]]},"30":{"position":[[838,5],[1002,5],[1176,5],[2092,7],[2335,5],[2403,5],[2578,5],[2913,6],[3270,6],[3289,5],[3777,5],[4054,5],[4452,6],[5791,5]]},"97":{"position":[[833,5],[1240,5]]},"118":{"position":[[205,8]]},"155":{"position":[[685,7]]}},"keywords":{}}],["cover".format(month",{"_index":1271,"title":{},"content":{"28":{"position":[[2115,26]]}},"keywords":{}}],["cow::from("drop"",{"_index":4589,"title":{},"content":{"155":{"position":[[1574,28]]}},"keywords":{}}],["cpu",{"_index":4943,"title":{},"content":{"173":{"position":[[425,3],[523,3],[687,3],[1136,3],[1687,3],[1724,3],[1895,3],[2191,4]]},"174":{"position":[[1,3],[189,3],[317,3]]},"176":{"position":[[998,3]]},"180":{"position":[[287,3]]},"188":{"position":[[1574,3],[1672,3],[2241,3],[2558,3],[3096,3]]},"189":{"position":[[1762,3],[2217,3],[2500,3],[2789,3]]},"193":{"position":[[3157,3]]}},"keywords":{}}],["cpu/mmu",{"_index":4984,"title":{},"content":{"174":{"position":[[501,7]]}},"keywords":{}}],["cpython",{"_index":5148,"title":{},"content":{"188":{"position":[[131,7],[560,7]]},"189":{"position":[[546,7]]}},"keywords":{}}],["cra",{"_index":30,"title":{},"content":{"1":{"position":[[330,5]]},"3":{"position":[[353,3],[492,3],[901,3]]}},"keywords":{}}],["crack",{"_index":3317,"title":{},"content":{"96":{"position":[[142,8]]}},"keywords":{}}],["craco",{"_index":151,"title":{},"content":{"3":{"position":[[384,6]]}},"keywords":{}}],["cramer",{"_index":872,"title":{"21":{"position":[[8,6]]}},"content":{"24":{"position":[[3384,6]]},"26":{"position":[[422,6],[543,6]]}},"keywords":{}}],["crash",{"_index":5200,"title":{},"content":{"188":{"position":[[3449,5]]},"195":{"position":[[169,6],[794,7]]}},"keywords":{}}],["crate",{"_index":3701,"title":{},"content":{"111":{"position":[[310,5]]},"113":{"position":[[341,5]]},"132":{"position":[[43,6]]},"155":{"position":[[534,5]]},"157":{"position":[[197,7],[433,6]]},"159":{"position":[[1191,6]]},"160":{"position":[[1675,5],[2543,6]]},"181":{"position":[[850,8]]}},"keywords":{}}],["crazi",{"_index":2141,"title":{},"content":{"51":{"position":[[3102,5]]},"128":{"position":[[1005,6]]}},"keywords":{}}],["creat",{"_index":27,"title":{},"content":{"1":{"position":[[313,6]]},"45":{"position":[[1856,6]]},"62":{"position":[[278,6]]},"90":{"position":[[838,6],[2223,6]]},"91":{"position":[[1790,7],[2714,7]]},"92":{"position":[[526,7]]},"97":{"position":[[927,6],[1272,8],[5377,7]]},"109":{"position":[[57,6]]},"110":{"position":[[205,6],[332,7]]},"113":{"position":[[360,6],[820,8],[1337,6]]},"125":{"position":[[1456,6],[7773,6]]},"127":{"position":[[1373,7]]},"136":{"position":[[579,6]]},"155":{"position":[[928,8]]},"156":{"position":[[459,8]]},"165":{"position":[[714,6]]},"178":{"position":[[308,8]]},"180":{"position":[[560,7]]},"188":{"position":[[2027,6]]},"192":{"position":[[37,8],[414,8]]},"196":{"position":[[140,7]]}},"keywords":{}}],["creation",{"_index":2260,"title":{},"content":{"53":{"position":[[1254,9]]}},"keywords":{}}],["creepi",{"_index":2540,"title":{},"content":{"66":{"position":[[24,6]]}},"keywords":{}}],["cring",{"_index":4015,"title":{},"content":{"125":{"position":[[442,6]]}},"keywords":{}}],["critic",{"_index":2650,"title":{},"content":{"74":{"position":[[1265,10]]},"112":{"position":[[280,10]]},"148":{"position":[[107,8]]},"161":{"position":[[543,10]]},"172":{"position":[[2653,8]]},"173":{"position":[[542,8],[731,8]]}},"keywords":{}}],["crook",{"_index":2831,"title":{},"content":{"86":{"position":[[722,7]]}},"keywords":{}}],["cross",{"_index":671,"title":{},"content":{"15":{"position":[[247,7]]}},"keywords":{}}],["crucial",{"_index":3481,"title":{},"content":{"101":{"position":[[635,7]]},"172":{"position":[[984,8]]},"176":{"position":[[504,7]]}},"keywords":{}}],["crude",{"_index":1094,"title":{},"content":{"24":{"position":[[2522,5],[2674,5]]},"25":{"position":[[2245,5],[2397,5]]}},"keywords":{}}],["crunch",{"_index":2078,"title":{},"content":{"51":{"position":[[339,10]]}},"keywords":{}}],["crusad",{"_index":3796,"title":{},"content":{"115":{"position":[[3161,7]]}},"keywords":{}}],["crust",{"_index":4757,"title":{},"content":{"161":{"position":[[1522,5]]}},"keywords":{}}],["crystal",{"_index":1560,"title":{},"content":{"32":{"position":[[2273,7]]}},"keywords":{}}],["csv",{"_index":2376,"title":{},"content":{"61":{"position":[[1624,3]]}},"keywords":{}}],["culinari",{"_index":3843,"title":{},"content":{"118":{"position":[[168,8]]}},"keywords":{}}],["cur_d1",{"_index":2723,"title":{},"content":{"76":{"position":[[2003,6],[2081,7],[2193,6],[2880,6],[3189,6],[3342,7]]}},"keywords":{}}],["cur_d2",{"_index":2725,"title":{},"content":{"76":{"position":[[2030,6],[2089,7],[2209,6],[2627,7],[2896,6],[3205,6],[3350,6]]}},"keywords":{}}],["cur_scor",{"_index":2726,"title":{},"content":{"76":{"position":[[2057,9],[2174,9],[2582,11],[2776,10],[2858,9],[3051,10],[3167,9]]}},"keywords":{}}],["curios",{"_index":3648,"title":{"132":{"position":[[0,10]]}},"content":{"105":{"position":[[3018,10]]}},"keywords":{}}],["curiou",{"_index":1337,"title":{},"content":{"30":{"position":[[510,8]]},"43":{"position":[[410,8]]},"176":{"position":[[449,7]]}},"keywords":{}}],["current",{"_index":336,"title":{},"content":{"6":{"position":[[505,7]]},"13":{"position":[[352,7]]},"14":{"position":[[630,7]]},"25":{"position":[[19,9]]},"38":{"position":[[889,9]]},"51":{"position":[[815,7],[1000,9]]},"52":{"position":[[926,7],[1041,7],[1100,7]]},"57":{"position":[[549,9]]},"75":{"position":[[451,7],[497,7],[705,8]]},"76":{"position":[[2524,7],[2959,7]]},"78":{"position":[[898,7]]},"82":{"position":[[273,7],[343,7],[413,7],[483,7],[553,7],[623,7],[693,7],[763,7],[833,7],[904,7]]},"88":{"position":[[613,9]]},"93":{"position":[[4028,9]]},"97":{"position":[[4558,7],[4621,7]]},"113":{"position":[[1927,9]]},"117":{"position":[[220,7]]},"124":{"position":[[499,9]]},"125":{"position":[[7911,9]]},"160":{"position":[[3789,9],[4472,9]]},"161":{"position":[[1339,9]]},"175":{"position":[[254,9]]},"184":{"position":[[785,9]]},"189":{"position":[[2928,9]]},"194":{"position":[[618,9]]},"195":{"position":[[710,7]]}},"keywords":{}}],["current[0",{"_index":2191,"title":{},"content":{"52":{"position":[[1000,10],[1022,10]]}},"keywords":{}}],["current_clos",{"_index":1605,"title":{},"content":{"34":{"position":[[1089,14],[1227,13]]},"39":{"position":[[809,14],[862,13],[939,13]]}},"keywords":{}}],["current_open",{"_index":1614,"title":{},"content":{"34":{"position":[[1243,12]]},"39":{"position":[[878,12]]}},"keywords":{}}],["current_pric",{"_index":1727,"title":{},"content":{"39":{"position":[[724,13]]}},"keywords":{}}],["current_price*shar",{"_index":1621,"title":{},"content":{"34":{"position":[[1534,20]]}},"keywords":{}}],["curri",{"_index":3371,"title":{},"content":{"97":{"position":[[1350,9],[2657,7]]}},"keywords":{}}],["curs",{"_index":1958,"title":{},"content":{"45":{"position":[[67,6],[75,6]]}},"keywords":{}}],["custom",{"_index":152,"title":{"42":{"position":[[21,8]]}},"content":{"3":{"position":[[391,9]]},"43":{"position":[[746,10],[773,10],[894,8],[1347,8],[1395,8]]},"44":{"position":[[1171,10],[1318,10],[1378,10],[1405,10],[1578,10],[1608,10]]},"46":{"position":[[190,8],[533,9]]},"125":{"position":[[4878,6],[4898,6]]},"132":{"position":[[602,6]]},"137":{"position":[[39,6]]}},"keywords":{}}],["custombusinessday",{"_index":2966,"title":{},"content":{"90":{"position":[[310,17],[3405,17]]}},"keywords":{}}],["custombusinessday(day",{"_index":2976,"title":{},"content":{"90":{"position":[[690,23]]}},"keywords":{}}],["cut",{"_index":3543,"title":{},"content":{"103":{"position":[[1924,3]]},"188":{"position":[[2759,3]]}},"keywords":{}}],["cvx",{"_index":711,"title":{},"content":{"17":{"position":[[162,6]]},"18":{"position":[[239,6]]},"19":{"position":[[466,6]]},"20":{"position":[[386,6],[2857,7]]}},"keywords":{}}],["cycl",{"_index":247,"title":{},"content":{"4":{"position":[[621,7]]},"161":{"position":[[804,5]]}},"keywords":{}}],["cyclic",{"_index":1813,"title":{},"content":{"40":{"position":[[1628,10]]}},"keywords":{}}],["cyclic_df",{"_index":1814,"title":{},"content":{"40":{"position":[[1640,9]]}},"keywords":{}}],["cyclic_df.xs('day",{"_index":1817,"title":{},"content":{"40":{"position":[[1765,20]]}},"keywords":{}}],["cyclic_df.xs('scor",{"_index":1818,"title":{},"content":{"40":{"position":[[1935,21]]}},"keywords":{}}],["cython",{"_index":5145,"title":{"188":{"position":[[0,7]]}},"content":{"188":{"position":[[13,6],[387,6],[595,6],[827,8],[1493,6],[3515,8],[4152,6]]},"189":{"position":[[6,7],[60,6],[962,7],[1910,6],[2581,7],[2873,7]]},"190":{"position":[[345,6],[537,6],[894,6]]}},"keywords":{}}],["cython'",{"_index":5221,"title":{},"content":{"188":{"position":[[4264,8],[4377,8]]}},"keywords":{}}],["cython/numba",{"_index":5262,"title":{},"content":{"190":{"position":[[504,12]]}},"keywords":{}}],["cython_gil(n",{"_index":5171,"title":{},"content":{"188":{"position":[[1557,14]]}},"keywords":{}}],["cython_gil(unsign",{"_index":5168,"title":{},"content":{"188":{"position":[[1289,19]]}},"keywords":{}}],["cython_nogil(n",{"_index":5177,"title":{},"content":{"188":{"position":[[1653,16]]}},"keywords":{}}],["cython_nogil(unsign",{"_index":5165,"title":{},"content":{"188":{"position":[[1153,21]]}},"keywords":{}}],["cython_recurse(2",{"_index":5204,"title":{},"content":{"188":{"position":[[3626,17]]}},"keywords":{}}],["cython_recurse(int",{"_index":5202,"title":{},"content":{"188":{"position":[[3533,18]]}},"keywords":{}}],["cython_recurse(n",{"_index":5203,"title":{},"content":{"188":{"position":[[3604,16]]}},"keywords":{}}],["c⋅ic",{"_index":549,"title":{},"content":{"13":{"position":[[320,4]]}},"keywords":{}}],["d",{"_index":787,"title":{},"content":{"20":{"position":[[714,3]]},"39":{"position":[[580,2],[2480,3],[2582,1]]},"62":{"position":[[566,3],[825,1],[1112,2]]},"88":{"position":[[762,3],[1279,4]]},"90":{"position":[[774,1],[2159,1]]},"93":{"position":[[2902,2],[4177,3]]},"121":{"position":[[354,2]]}},"keywords":{}}],["d(0,t",{"_index":465,"title":{},"content":{"9":{"position":[[433,5]]}},"keywords":{}}],["d(0,t)=d(0,t−1)⋅fi−1,id(0",{"_index":464,"title":{},"content":{"9":{"position":[[401,26]]}},"keywords":{}}],["d.isoformat",{"_index":3243,"title":{},"content":{"93":{"position":[[2905,14]]}},"keywords":{}}],["d1",{"_index":2597,"title":{},"content":{"70":{"position":[[1027,2]]},"71":{"position":[[1210,2],[1255,2]]}},"keywords":{}}],["d1={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3d2={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3e[d1]=3.5e[d2]=3.5e[d1+d2]=7=e[dfair+dfair]\\begin{align",{"_index":2607,"title":{},"content":{"71":{"position":[[187,169]]}},"keywords":{}}],["d1={1w.p.1/32w.p.1/33w.p.1/124w.p.1/125w.p.1/126w.p.1/12d2={1w.p.1/122w.p.1/123w.p.1/124w.p.1/125w.p.1/36w.p.1/3e[d1]=2.5e[d2]=4.5e[d1+d2]=7=e[dfair+dfair]\\begin{align",{"_index":2578,"title":{},"content":{"70":{"position":[[87,169]]}},"keywords":{}}],["d1_densiti",{"_index":2687,"title":{},"content":{"76":{"position":[[477,11]]}},"keywords":{}}],["d1_index1",{"_index":2701,"title":{},"content":{"76":{"position":[[1260,10]]}},"keywords":{}}],["d1_index2",{"_index":2702,"title":{},"content":{"76":{"position":[[1271,9]]}},"keywords":{}}],["d1_p",{"_index":2680,"title":{},"content":{"76":{"position":[[342,4],[432,5]]}},"keywords":{}}],["d1_val",{"_index":2750,"title":{},"content":{"78":{"position":[[159,7]]}},"keywords":{}}],["d2",{"_index":2598,"title":{},"content":{"70":{"position":[[1067,2]]},"71":{"position":[[1250,2]]}},"keywords":{}}],["d2_densiti",{"_index":2677,"title":{},"content":{"76":{"position":[[204,12],[489,12],[746,11],[989,12]]}},"keywords":{}}],["d2_dist",{"_index":2748,"title":{},"content":{"78":{"position":[[140,8],[512,9]]}},"keywords":{}}],["d2_index1",{"_index":2704,"title":{},"content":{"76":{"position":[[1310,10]]}},"keywords":{}}],["d2_index2",{"_index":2705,"title":{},"content":{"76":{"position":[[1321,9]]}},"keywords":{}}],["d2_p",{"_index":2682,"title":{},"content":{"76":{"position":[[383,4]]}},"keywords":{}}],["d2_p).coef",{"_index":2685,"title":{},"content":{"76":{"position":[[440,10]]}},"keywords":{}}],["d2_val",{"_index":2752,"title":{},"content":{"78":{"position":[[192,7],[309,8],[598,8]]}},"keywords":{}}],["d_1",{"_index":2580,"title":{},"content":{"70":{"position":[[275,3]]},"71":{"position":[[375,3]]}},"keywords":{}}],["d_2",{"_index":2586,"title":{},"content":{"70":{"position":[[449,3],[701,4],[1237,5]]},"71":{"position":[[549,3],[801,4],[1384,5]]}},"keywords":{}}],["d_col",{"_index":719,"title":{},"content":{"17":{"position":[[236,5]]}},"keywords":{}}],["d_i(1",{"_index":1550,"title":{},"content":{"32":{"position":[[1803,5],[1883,5]]}},"keywords":{}}],["d_icn​∑i=1n​oi​di​​>∑i=1n​di",{"_index":1533,"title":{},"content":{"32":{"position":[[874,32]]}},"keywords":{}}],["d_n",{"_index":1545,"title":{},"content":{"32":{"position":[[1662,5],[1689,3],[1748,3],[1830,3]]}},"keywords":{}}],["d_{fair",{"_index":2591,"title":{},"content":{"70":{"position":[[734,9]]},"71":{"position":[[834,9]]}},"keywords":{}}],["daili",{"_index":760,"title":{},"content":{"20":{"position":[[40,5]]},"24":{"position":[[180,5]]}},"keywords":{}}],["daily_invest",{"_index":1603,"title":{},"content":{"34":{"position":[[1047,16]]}},"keywords":{}}],["daily_investment(current_open",{"_index":1728,"title":{},"content":{"39":{"position":[[778,30]]}},"keywords":{}}],["daily_investment(open_vals[day",{"_index":1734,"title":{},"content":{"39":{"position":[[1329,32]]}},"keywords":{}}],["daily_investment(open_vals[day+1",{"_index":1637,"title":{},"content":{"34":{"position":[[2116,34]]}},"keywords":{}}],["damn",{"_index":5036,"title":{},"content":{"175":{"position":[[1606,7]]}},"keywords":{}}],["dashboard_article_link",{"_index":895,"title":{},"content":{"22":{"position":[[474,25]]}},"keywords":{}}],["data",{"_index":721,"title":{"22":{"position":[[20,4]]},"23":{"position":[[21,5]]},"43":{"position":[[0,4]]},"50":{"position":[[4,5]]},"59":{"position":[[12,5]]},"62":{"position":[[15,5]]},"63":{"position":[[31,5]]}},"content":{"17":{"position":[[252,4]]},"22":{"position":[[118,4],[1252,4],[2746,4]]},"23":{"position":[[30,5],[177,4]]},"24":{"position":[[550,4],[748,4],[2891,4],[3290,4],[3414,4]]},"25":{"position":[[275,4],[464,4],[2643,4],[2737,4]]},"26":{"position":[[5,4],[73,4],[222,4],[402,5],[452,4]]},"28":{"position":[[599,5],[1618,4],[2376,4],[2396,4],[2761,4],[2834,4],[3404,4],[4006,4],[4067,5]]},"29":{"position":[[282,4],[401,4]]},"30":{"position":[[768,4],[890,4],[2507,4],[2636,4],[2729,4],[4491,4],[7435,4],[8227,4],[8289,4],[8426,4],[9612,4],[9711,4],[10153,4],[10210,4],[10264,4],[10314,4]]},"34":{"position":[[3031,4]]},"39":{"position":[[315,4],[2334,4]]},"40":{"position":[[30,5]]},"41":{"position":[[261,4]]},"43":{"position":[[31,4],[103,4],[1001,4],[1209,4],[1259,4]]},"44":{"position":[[32,4],[198,5],[491,4],[1839,4],[1945,4]]},"45":{"position":[[323,4],[2783,4],[3543,4]]},"46":{"position":[[127,5],[377,4]]},"47":{"position":[[41,5],[102,4],[201,5]]},"51":{"position":[[94,5],[321,5],[2742,4]]},"53":{"position":[[107,5]]},"57":{"position":[[262,4],[294,4],[604,4]]},"58":{"position":[[40,5],[133,5],[744,5],[924,4]]},"59":{"position":[[63,4],[230,5]]},"61":{"position":[[147,4],[314,5],[337,4],[601,5],[728,5],[781,5],[839,4],[897,5],[972,4],[1098,4],[1144,4]]},"62":{"position":[[104,5],[124,4],[246,4],[357,5],[1288,5],[1730,4]]},"63":{"position":[[29,4],[83,4]]},"65":{"position":[[333,4],[1653,4]]},"66":{"position":[[259,4]]},"69":{"position":[[230,6]]},"74":{"position":[[1017,4]]},"75":{"position":[[341,5]]},"82":{"position":[[50,4],[64,4],[1221,5],[1243,4]]},"83":{"position":[[406,5]]},"88":{"position":[[2468,6]]},"89":{"position":[[964,5]]},"90":{"position":[[4124,4]]},"91":{"position":[[2139,4],[2813,4],[3287,4],[3941,4]]},"92":{"position":[[625,4],[1099,4]]},"93":{"position":[[623,5],[1000,5],[1036,4],[1206,4],[1736,6],[1797,5],[2066,5],[2135,5],[3759,4]]},"95":{"position":[[78,4]]},"97":{"position":[[1409,4],[3459,5]]},"100":{"position":[[41,4],[462,5]]},"101":{"position":[[174,4],[242,4]]},"102":{"position":[[268,4],[894,5],[915,5],[1372,4]]},"104":{"position":[[806,5]]},"106":{"position":[[694,5],[893,4]]},"110":{"position":[[52,4]]},"113":{"position":[[1661,4],[1773,4],[2146,4]]},"117":{"position":[[188,5],[246,5],[1641,5]]},"155":{"position":[[80,4],[146,4],[464,4],[941,4],[1008,4]]},"163":{"position":[[39,4],[82,4],[403,5],[1606,4],[2214,5],[2428,4]]},"166":{"position":[[399,5],[515,4]]},"167":{"position":[[165,4],[234,5],[304,4]]},"172":{"position":[[1311,4],[1333,4]]},"175":{"position":[[194,4],[487,4],[520,4],[1290,4],[1349,5],[1393,4],[1541,4]]},"190":{"position":[[210,4]]}},"keywords":{}}],["data.id",{"_index":2044,"title":{},"content":{"47":{"position":[[147,7]]}},"keywords":{}}],["data.index",{"_index":2043,"title":{},"content":{"47":{"position":[[134,10]]},"88":{"position":[[1150,11]]}},"keywords":{}}],["data.loc[d",{"_index":2866,"title":{},"content":{"88":{"position":[[1119,18]]}},"keywords":{}}],["data.loc[end]['high",{"_index":2910,"title":{},"content":{"88":{"position":[[2543,23]]}},"keywords":{}}],["data.loc[end]['low",{"_index":2912,"title":{},"content":{"88":{"position":[[2645,22]]}},"keywords":{}}],["data.loc[start]['high",{"_index":2909,"title":{},"content":{"88":{"position":[[2517,25]]}},"keywords":{}}],["data.loc[start]['low",{"_index":2911,"title":{},"content":{"88":{"position":[[2620,24]]}},"keywords":{}}],["data['close']/2",{"_index":3133,"title":{},"content":{"91":{"position":[[2892,15]]},"92":{"position":[[704,15]]}},"keywords":{}}],["data['open']/2",{"_index":3132,"title":{},"content":{"91":{"position":[[2875,14]]},"92":{"position":[[687,14]]}},"keywords":{}}],["data[d",{"_index":1037,"title":{},"content":{"24":{"position":[[689,10]]},"25":{"position":[[410,10]]}},"keywords":{}}],["data[tick][d_col].pct_chang",{"_index":727,"title":{},"content":{"18":{"position":[[94,30]]}},"keywords":{}}],["data_str",{"_index":3106,"title":{},"content":{"91":{"position":[[1923,8]]},"93":{"position":[[4336,8]]}},"keywords":{}}],["data_str.split('\\n",{"_index":3112,"title":{},"content":{"91":{"position":[[2047,21]]},"93":{"position":[[4460,21]]}},"keywords":{}}],["data_train",{"_index":2045,"title":{},"content":{"47":{"position":[[155,11]]}},"keywords":{}}],["data_train.to_csv('split_train.csv",{"_index":2048,"title":{},"content":{"47":{"position":[[222,36]]}},"keywords":{}}],["data_valid",{"_index":2046,"title":{},"content":{"47":{"position":[[167,13]]}},"keywords":{}}],["data_validate.to_csv('split_validate.csv",{"_index":2049,"title":{},"content":{"47":{"position":[[259,42]]}},"keywords":{}}],["databas",{"_index":4420,"title":{},"content":{"139":{"position":[[487,8]]}},"keywords":{}}],["datafram",{"_index":432,"title":{},"content":{"7":{"position":[[1137,10]]}},"keywords":{}}],["dataset",{"_index":1866,"title":{},"content":{"43":{"position":[[472,7]]},"44":{"position":[[97,7],[351,7]]},"45":{"position":[[402,8]]},"46":{"position":[[41,8]]},"50":{"position":[[109,8]]},"83":{"position":[[471,8],[542,8]]},"88":{"position":[[668,7]]},"93":{"position":[[4083,7]]},"102":{"position":[[487,7]]},"104":{"position":[[158,7],[1115,8]]}},"keywords":{}}],["dataset.drop(['target",{"_index":1870,"title":{},"content":{"43":{"position":[[544,23]]}},"keywords":{}}],["dataset.id",{"_index":1869,"title":{},"content":{"43":{"position":[[529,10]]}},"keywords":{}}],["dataset.index",{"_index":1868,"title":{},"content":{"43":{"position":[[513,13]]}},"keywords":{}}],["dataset.target",{"_index":1872,"title":{},"content":{"43":{"position":[[590,14]]}},"keywords":{}}],["datastream",{"_index":3655,"title":{},"content":{"106":{"position":[[597,11]]}},"keywords":{}}],["date",{"_index":941,"title":{},"content":{"22":{"position":[[1532,4],[1587,4]]},"23":{"position":[[246,5]]},"24":{"position":[[591,4],[1032,5],[2074,9]]},"25":{"position":[[316,4],[752,5],[1798,9]]},"28":{"position":[[1243,5],[1453,7],[3043,5],[3249,7]]},"30":{"position":[[1609,5],[1814,7],[2958,5],[3163,7],[4882,5],[5083,7],[6026,5],[6232,7],[8855,4]]},"62":{"position":[[287,4]]},"66":{"position":[[31,4],[671,4]]},"88":{"position":[[1142,4]]},"90":{"position":[[3518,4]]},"91":{"position":[[2168,5],[2916,5]]},"92":{"position":[[728,5]]},"93":{"position":[[1534,5],[1907,4],[2757,5],[2872,6]]},"120":{"position":[[109,6]]},"122":{"position":[[1467,4]]},"124":{"position":[[209,4],[238,4]]}},"keywords":{}}],["date(2015",{"_index":1658,"title":{},"content":{"34":{"position":[[3344,10],[3735,10]]}},"keywords":{}}],["date/tim",{"_index":3851,"title":{},"content":{"120":{"position":[[416,9]]},"122":{"position":[[1166,9]]}},"keywords":{}}],["date2num",{"_index":2844,"title":{},"content":{"88":{"position":[[343,8]]}},"keywords":{}}],["date2num(d",{"_index":2865,"title":{},"content":{"88":{"position":[[1101,17]]}},"keywords":{}}],["date2num(end",{"_index":2908,"title":{},"content":{"88":{"position":[[2501,15],[2604,15]]}},"keywords":{}}],["date=non",{"_index":1467,"title":{},"content":{"30":{"position":[[8778,11]]}},"keywords":{}}],["date_list",{"_index":3120,"title":{},"content":{"91":{"position":[[2305,9],[2356,10]]}},"keywords":{}}],["date_str",{"_index":940,"title":{},"content":{"22":{"position":[[1463,11]]},"62":{"position":[[909,8]]}},"keywords":{}}],["dateformatt",{"_index":2847,"title":{},"content":{"88":{"position":[[429,14]]}},"keywords":{}}],["dateformatter('%b",{"_index":2871,"title":{},"content":{"88":{"position":[[1261,17]]}},"keywords":{}}],["datepublish",{"_index":939,"title":{},"content":{"22":{"position":[[1436,16]]}},"keywords":{}}],["dates_fil",{"_index":3257,"title":{},"content":{"93":{"position":[[3295,10]]}},"keywords":{}}],["dates_file.write(yaml.dump({r3000_equities.ix[i]['tick",{"_index":3271,"title":{},"content":{"93":{"position":[[3654,59]]}},"keywords":{}}],["datetim",{"_index":707,"title":{},"content":{"17":{"position":[[108,8],[124,9]]},"30":{"position":[[241,8],[257,8],[8388,8],[8404,8],[9094,10]]},"39":{"position":[[3072,8],[3088,8]]},"43":{"position":[[424,8],[440,8]]},"62":{"position":[[433,8],[449,8]]},"65":{"position":[[2292,8]]},"88":{"position":[[499,8],[515,8]]},"90":{"position":[[333,8],[349,9]]},"93":{"position":[[1305,8],[1321,9],[3902,8]]},"122":{"position":[[275,8]]}},"keywords":{}}],["datetime(2015",{"_index":1774,"title":{},"content":{"39":{"position":[[3141,14]]}},"keywords":{}}],["datetime(2016",{"_index":1777,"title":{},"content":{"39":{"position":[[3202,14]]},"62":{"position":[[583,14],[615,14]]},"88":{"position":[[1440,14],[1462,14],[1769,14],[1791,14],[2831,14],[2853,14],[2901,14],[2924,14],[3228,14],[3251,14],[3295,14],[3318,14]]},"90":{"position":[[4041,15]]}},"keywords":{}}],["datetime(2070",{"_index":2529,"title":{},"content":{"65":{"position":[[2325,14]]}},"keywords":{}}],["datetime(row_dt.year",{"_index":1062,"title":{},"content":{"24":{"position":[[1259,21]]},"25":{"position":[[979,21]]}},"keywords":{}}],["datetime.datetime(2070",{"_index":2533,"title":{},"content":{"65":{"position":[[2447,23]]}},"keywords":{}}],["datetime.now",{"_index":1865,"title":{},"content":{"43":{"position":[[457,14]]},"46":{"position":[[594,14]]},"93":{"position":[[2856,15]]}},"keywords":{}}],["datetime.now().strftime("%i:%m:%",{"_index":1488,"title":{},"content":{"30":{"position":[[9757,38]]}},"keywords":{}}],["datetime.strptime(date_str",{"_index":2423,"title":{},"content":{"62":{"position":[[1067,26]]}},"keywords":{}}],["datetimemodul",{"_index":3850,"title":{},"content":{"120":{"position":[[255,15]]}},"keywords":{}}],["dateutil",{"_index":3200,"title":{"119":{"position":[[23,8]]}},"content":{"93":{"position":[[1372,8]]},"120":{"position":[[67,8]]},"121":{"position":[[978,8],[2491,8]]},"122":{"position":[[301,9],[414,8]]},"124":{"position":[[24,8]]}},"keywords":{}}],["dateutil.pars",{"_index":3104,"title":{},"content":{"91":{"position":[[1858,15]]},"93":{"position":[[3868,15]]},"120":{"position":[[271,15],[785,15]]}},"keywords":{}}],["day",{"_index":766,"title":{"46":{"position":[[12,3]]},"91":{"position":[[44,5]]},"92":{"position":[[32,5]]}},"content":{"20":{"position":[[218,3]]},"24":{"position":[[292,4]]},"26":{"position":[[380,3]]},"30":{"position":[[477,3],[598,4],[1065,4],[1131,3],[1153,3],[2617,5],[2826,4],[3579,6],[4003,4],[4257,4],[4314,4],[4574,4],[4631,4],[4682,4],[5851,5],[5936,3],[6652,6],[6857,4],[7083,4],[7157,4],[7691,5]]},"32":{"position":[[270,3],[520,3],[570,3],[646,3],[1221,3],[1324,3],[2128,4]]},"33":{"position":[[534,3],[609,3],[880,3],[1106,3]]},"34":{"position":[[453,4],[1866,3],[2341,3],[3157,4],[3203,3],[3447,4],[3568,4],[3838,4],[3965,4]]},"38":{"position":[[133,4],[387,3],[541,4],[845,4],[936,3],[985,4],[1062,4],[1112,4]]},"39":{"position":[[1081,3],[1561,3]]},"40":{"position":[[351,4],[681,4],[1885,4],[2208,4],[2828,4],[3527,4],[3565,3]]},"53":{"position":[[993,4],[1037,3]]},"61":{"position":[[1708,3]]},"62":{"position":[[255,3]]},"64":{"position":[[143,3],[465,5],[755,5]]},"65":{"position":[[374,4],[620,4],[1425,3],[1642,3]]},"89":{"position":[[600,4]]},"90":{"position":[[611,3],[662,3],[684,5],[3269,3],[4273,4],[4509,5],[4616,5],[4794,4],[4850,5],[4940,5],[5102,3],[5279,3]]},"91":{"position":[[119,4],[353,5],[1460,4],[1541,4],[1571,5],[2522,4],[2611,3],[2671,4],[3004,5],[4232,5],[4342,3],[4550,5],[5000,4],[5011,5],[5065,4],[5147,3],[5374,4],[5524,3],[5730,3],[5908,3],[5971,3]]},"92":{"position":[[164,5],[334,4],[423,3],[483,4],[816,5],[1605,4]]},"93":{"position":[[1936,3]]},"95":{"position":[[499,4]]},"96":{"position":[[567,4]]},"98":{"position":[[19,5]]},"101":{"position":[[127,5]]},"122":{"position":[[1234,4]]},"150":{"position":[[95,4]]},"167":{"position":[[223,3]]}},"keywords":{}}],["day"",{"_index":1415,"title":{},"content":{"30":{"position":[[5919,9]]}},"keywords":{}}],["day'",{"_index":3075,"title":{},"content":{"91":{"position":[[292,5]]}},"keywords":{}}],["day.th",{"_index":3065,"title":{},"content":{"90":{"position":[[5003,7]]}},"keywords":{}}],["dayloc",{"_index":2849,"title":{},"content":{"88":{"position":[[461,11],[1232,12]]}},"keywords":{}}],["daynnn",{"_index":2464,"title":{},"content":{"64":{"position":[[692,7]]},"65":{"position":[[569,7]]}},"keywords":{}}],["dd_a",{"_index":815,"title":{},"content":{"20":{"position":[[1284,4],[1764,5],[2621,5]]}},"keywords":{}}],["de",{"_index":3954,"title":{},"content":{"122":{"position":[[1157,2]]}},"keywords":{}}],["de/seri",{"_index":4850,"title":{},"content":{"166":{"position":[[884,17]]},"170":{"position":[[369,16]]}},"keywords":{}}],["dead",{"_index":3951,"title":{},"content":{"122":{"position":[[1011,4],[1278,4]]}},"keywords":{}}],["deal",{"_index":4194,"title":{},"content":{"125":{"position":[[10155,4]]},"128":{"position":[[1743,7]]},"142":{"position":[[169,7]]},"160":{"position":[[677,4]]}},"keywords":{}}],["dealloc",{"_index":4522,"title":{},"content":{"152":{"position":[[1027,13]]},"155":{"position":[[1098,10]]},"156":{"position":[[1125,13]]}},"keywords":{}}],["dealloc(&self",{"_index":4535,"title":{},"content":{"152":{"position":[[1488,18]]},"156":{"position":[[1571,18]]}},"keywords":{}}],["deallocation."",{"_index":4536,"title":{},"content":{"152":{"position":[[1600,21]]},"156":{"position":[[1683,21]]}},"keywords":{}}],["debug",{"_index":3885,"title":{},"content":{"121":{"position":[[767,9]]}},"keywords":{}}],["debug_assert",{"_index":4412,"title":{"138":{"position":[[9,13]]}},"content":{"143":{"position":[[362,14]]}},"keywords":{}}],["decent",{"_index":1841,"title":{},"content":{"40":{"position":[[3623,6]]}},"keywords":{}}],["decid",{"_index":2517,"title":{},"content":{"65":{"position":[[1453,7]]},"97":{"position":[[2246,7]]},"194":{"position":[[114,7]]}},"keywords":{}}],["decidedli",{"_index":4490,"title":{},"content":{"150":{"position":[[142,9]]}},"keywords":{}}],["decim",{"_index":3938,"title":{},"content":{"122":{"position":[[323,7],[428,9],[562,7]]}},"keywords":{}}],["decis",{"_index":2028,"title":{},"content":{"45":{"position":[[3577,10]]},"53":{"position":[[768,8]]},"122":{"position":[[814,9]]},"125":{"position":[[4036,8]]},"170":{"position":[[70,9]]}},"keywords":{}}],["declar",{"_index":2815,"title":{},"content":{"83":{"position":[[559,7]]},"155":{"position":[[128,9]]},"178":{"position":[[125,7]]},"179":{"position":[[294,8]]},"180":{"position":[[137,8]]},"182":{"position":[[98,7]]},"184":{"position":[[258,8]]},"186":{"position":[[375,8]]},"195":{"position":[[89,9]]},"196":{"position":[[516,8]]},"197":{"position":[[645,8]]}},"keywords":{}}],["declin",{"_index":1291,"title":{},"content":{"28":{"position":[[2718,7]]}},"keywords":{}}],["decod",{"_index":4815,"title":{},"content":{"164":{"position":[[1254,8]]}},"keywords":{}}],["decompress",{"_index":3484,"title":{},"content":{"101":{"position":[[719,12]]}},"keywords":{}}],["decor",{"_index":5228,"title":{},"content":{"189":{"position":[[229,10],[250,9],[489,10],[634,9]]},"190":{"position":[[407,9]]}},"keywords":{}}],["decreas",{"_index":2699,"title":{},"content":{"76":{"position":[[1116,8]]},"90":{"position":[[4961,10]]}},"keywords":{}}],["deep",{"_index":1186,"title":{},"content":{"26":{"position":[[860,4]]},"125":{"position":[[4787,4]]}},"keywords":{}}],["deepli",{"_index":268,"title":{},"content":{"4":{"position":[[907,6]]}},"keywords":{}}],["deepthought",{"_index":2271,"title":{},"content":{"53":{"position":[[1435,13]]}},"keywords":{}}],["def",{"_index":820,"title":{},"content":{"20":{"position":[[1510,3],[1820,3]]},"22":{"position":[[296,3],[1277,3],[1363,3],[1625,3],[1725,3],[2269,3],[2324,3]]},"24":{"position":[[423,3],[931,3]]},"25":{"position":[[148,3],[651,3]]},"28":{"position":[[1090,3],[1196,3],[1786,3],[2879,3],[3000,3],[3534,3]]},"30":{"position":[[1462,3],[1568,3],[2920,3],[4724,3],[4845,3],[5989,3],[8750,3]]},"39":{"position":[[602,3],[774,3],[990,3],[2142,3],[3036,3]]},"45":{"position":[[2012,3],[2794,3]]},"51":{"position":[[3606,3],[3755,3],[3828,3],[3928,3],[4078,3]]},"52":{"position":[[707,3]]},"62":{"position":[[834,3]]},"70":{"position":[[934,3]]},"76":{"position":[[175,3],[464,3],[965,3],[1887,3]]},"78":{"position":[[111,3]]},"88":{"position":[[563,3],[921,3],[2438,3]]},"90":{"position":[[739,3],[2118,3],[3175,3]]},"91":{"position":[[2413,3],[3315,3]]},"92":{"position":[[228,3]]},"93":{"position":[[1545,3],[1632,3],[1714,3],[2183,3],[2257,3],[3978,3]]},"96":{"position":[[460,3]]},"103":{"position":[[873,3]]},"105":{"position":[[493,3],[975,3],[1332,3]]},"129":{"position":[[1939,3]]},"188":{"position":[[1149,3],[1285,3]]},"189":{"position":[[1077,3],[1349,3],[3069,3]]}},"keywords":{}}],["default",{"_index":4383,"title":{},"content":{"135":{"position":[[652,7]]},"172":{"position":[[457,7],[1301,8]]},"189":{"position":[[884,9],[1320,8]]}},"keywords":{}}],["default,heaptrack",{"_index":4363,"title":{},"content":{"133":{"position":[[77,17]]}},"keywords":{}}],["defeat",{"_index":4105,"title":{},"content":{"125":{"position":[[5025,6]]}},"keywords":{}}],["defin",{"_index":344,"title":{"7":{"position":[[0,8]]},"127":{"position":[[0,8]]}},"content":{"6":{"position":[[612,6]]},"13":{"position":[[16,7]]},"22":{"position":[[16,6]]},"30":{"position":[[1138,7],[5898,6]]},"34":{"position":[[19,7],[713,7]]},"35":{"position":[[7,7]]},"76":{"position":[[13,8]]},"90":{"position":[[4875,7]]},"91":{"position":[[1587,6]]},"97":{"position":[[3427,6]]},"103":{"position":[[717,6]]},"112":{"position":[[1505,7],[1597,7]]},"113":{"position":[[384,6]]},"117":{"position":[[134,6],[2082,6]]},"127":{"position":[[978,6]]},"139":{"position":[[374,6]]},"155":{"position":[[609,7]]},"160":{"position":[[846,8],[4513,7]]},"188":{"position":[[742,6]]}},"keywords":{}}],["definit",{"_index":1520,"title":{},"content":{"32":{"position":[[461,12],[666,11]]},"97":{"position":[[4314,10]]},"105":{"position":[[3300,10]]},"185":{"position":[[214,11],[616,11]]}},"keywords":{}}],["defrost",{"_index":4740,"title":{},"content":{"161":{"position":[[796,7]]}},"keywords":{}}],["degre",{"_index":4668,"title":{},"content":{"160":{"position":[[935,6]]},"161":{"position":[[1356,8]]}},"keywords":{}}],["deliv",{"_index":3438,"title":{},"content":{"98":{"position":[[182,7]]},"125":{"position":[[4608,10]]},"175":{"position":[[816,9]]}},"keywords":{}}],["deliveri",{"_index":5014,"title":{},"content":{"175":{"position":[[624,9]]}},"keywords":{}}],["demonstr",{"_index":2897,"title":{},"content":{"88":{"position":[[2046,11]]},"130":{"position":[[36,13]]},"179":{"position":[[175,11]]},"185":{"position":[[502,11]]},"188":{"position":[[787,12]]}},"keywords":{}}],["deno",{"_index":205,"title":{},"content":{"3":{"position":[[1317,4]]}},"keywords":{}}],["denot",{"_index":3811,"title":{},"content":{"116":{"position":[[2541,7]]}},"keywords":{}}],["densiti",{"_index":2675,"title":{},"content":{"76":{"position":[[86,9],[885,10],[1033,10]]}},"keywords":{}}],["density_coef(d1_dens",{"_index":2676,"title":{},"content":{"76":{"position":[[179,24],[721,24]]}},"keywords":{}}],["density_coef(d1_dist",{"_index":2764,"title":{},"content":{"78":{"position":[[490,21]]}},"keywords":{}}],["density_coef(max_d1",{"_index":2771,"title":{},"content":{"78":{"position":[[689,20]]}},"keywords":{}}],["departmentofredundancydepart",{"_index":2278,"title":{},"content":{"53":{"position":[[1536,33]]}},"keywords":{}}],["depend",{"_index":269,"title":{},"content":{"4":{"position":[[914,9]]},"109":{"position":[[384,13],[427,14]]},"124":{"position":[[445,13]]},"125":{"position":[[4757,9],[8095,10],[9324,6]]},"142":{"position":[[58,9]]},"173":{"position":[[1530,9]]},"190":{"position":[[624,13]]}},"keywords":{}}],["depress",{"_index":1208,"title":{},"content":{"28":{"position":[[300,10],[846,10]]},"29":{"position":[[225,10]]},"30":{"position":[[4712,11]]},"66":{"position":[[870,10]]}},"keywords":{}}],["depth",{"_index":1849,"title":{},"content":{"41":{"position":[[74,5]]},"163":{"position":[[61,5]]}},"keywords":{}}],["derail",{"_index":235,"title":{},"content":{"4":{"position":[[281,6]]}},"keywords":{}}],["derefer",{"_index":4238,"title":{},"content":{"127":{"position":[[926,11],[1189,11],[1456,11]]},"128":{"position":[[1792,11],[1868,12]]}},"keywords":{}}],["dereferenc",{"_index":4234,"title":{},"content":{"127":{"position":[[764,12],[1067,13]]}},"keywords":{}}],["deriv",{"_index":2631,"title":{"74":{"position":[[0,8]]}},"content":{"74":{"position":[[4,6]]},"115":{"position":[[2775,8]]}},"keywords":{}}],["derive(clon",{"_index":5364,"title":{},"content":{"198":{"position":[[973,16]]}},"keywords":{}}],["derive(copi",{"_index":5368,"title":{},"content":{"198":{"position":[[1100,14]]}},"keywords":{}}],["derive(debug",{"_index":5120,"title":{},"content":{"184":{"position":[[131,16],[490,16]]}},"keywords":{}}],["derive(default",{"_index":4546,"title":{},"content":{"153":{"position":[[508,18],[564,18],[623,18],[683,18]]},"195":{"position":[[190,18],[261,18],[337,18],[575,18]]}},"keywords":{}}],["describ",{"_index":4562,"title":{},"content":{"155":{"position":[[400,8]]}},"keywords":{}}],["deseri",{"_index":3756,"title":{"169":{"position":[[0,16]]}},"content":{"113":{"position":[[1757,11],[1782,12],[1909,14]]},"115":{"position":[[237,12]]},"116":{"position":[[337,12]]},"117":{"position":[[1126,12]]},"164":{"position":[[1302,15]]}},"keywords":{}}],["deserialized.get_root::<point_capnp::point::reader>().unwrap",{"_index":3762,"title":{},"content":{"113":{"position":[[2192,69]]},"115":{"position":[[380,69]]},"116":{"position":[[480,69]]}},"keywords":{}}],["deserv",{"_index":2840,"title":{},"content":{"88":{"position":[[207,8]]}},"keywords":{}}],["design",{"_index":1600,"title":{},"content":{"34":{"position":[[901,8]]},"38":{"position":[[23,8]]},"100":{"position":[[146,6],[417,9]]},"102":{"position":[[869,8]]},"155":{"position":[[297,6]]},"172":{"position":[[600,8],[1382,6]]},"176":{"position":[[139,9],[1145,8]]},"199":{"position":[[617,7]]}},"keywords":{}}],["desir",{"_index":2547,"title":{},"content":{"66":{"position":[[548,6]]},"168":{"position":[[100,7]]}},"keywords":{}}],["desktop",{"_index":4002,"title":{"125":{"position":[[11,7]]}},"content":{"125":{"position":[[223,7]]}},"keywords":{}}],["despis",{"_index":4003,"title":{},"content":{"125":{"position":[[7,7]]}},"keywords":{}}],["despit",{"_index":4727,"title":{},"content":{"161":{"position":[[224,7]]}},"keywords":{}}],["destin",{"_index":5035,"title":{},"content":{"175":{"position":[[1577,11]]}},"keywords":{}}],["detail",{"_index":2643,"title":{},"content":{"74":{"position":[[912,8]]},"125":{"position":[[4185,6]]},"127":{"position":[[1604,7]]},"129":{"position":[[1186,7]]},"130":{"position":[[96,7]]},"159":{"position":[[35,6]]},"174":{"position":[[525,8]]},"176":{"position":[[119,7],[569,7]]},"188":{"position":[[4319,6]]},"196":{"position":[[1384,7]]},"198":{"position":[[97,6]]}},"keywords":{}}],["detect",{"_index":174,"title":{"68":{"position":[[15,6]]},"72":{"position":[[0,9]]}},"content":{"3":{"position":[[810,7]]},"68":{"position":[[300,6]]},"69":{"position":[[201,10]]},"71":{"position":[[75,6]]},"72":{"position":[[62,7]]},"190":{"position":[[787,8]]}},"keywords":{}}],["determin",{"_index":1013,"title":{},"content":{"24":{"position":[[40,10],[3312,11]]},"73":{"position":[[71,9]]},"75":{"position":[[836,9]]},"83":{"position":[[95,9]]},"102":{"position":[[1205,10]]},"128":{"position":[[812,10]]},"155":{"position":[[1074,10]]},"193":{"position":[[320,10]]}},"keywords":{}}],["dev",{"_index":3058,"title":{},"content":{"90":{"position":[[4499,4]]}},"keywords":{}}],["develop",{"_index":260,"title":{},"content":{"4":{"position":[[779,10]]},"40":{"position":[[1502,9]]},"46":{"position":[[417,7]]},"51":{"position":[[3575,10]]},"66":{"position":[[318,10]]},"72":{"position":[[453,10]]},"105":{"position":[[197,7]]},"160":{"position":[[2325,10],[2429,10]]}},"keywords":{}}],["deviat",{"_index":742,"title":{},"content":{"19":{"position":[[155,9]]},"72":{"position":[[126,8]]},"90":{"position":[[5052,9]]},"91":{"position":[[4852,9],[5850,9]]},"92":{"position":[[1520,9]]}},"keywords":{}}],["devic",{"_index":4681,"title":{},"content":{"160":{"position":[[1780,8],[2658,7],[2821,8]]},"173":{"position":[[1641,7]]},"175":{"position":[[1239,7]]}},"keywords":{}}],["df",{"_index":2418,"title":{},"content":{"62":{"position":[[962,2],[1134,2]]}},"keywords":{}}],["df.index",{"_index":2421,"title":{},"content":{"62":{"position":[[1028,8]]}},"keywords":{}}],["df['time'].appli",{"_index":2422,"title":{},"content":{"62":{"position":[[1039,17]]}},"keywords":{}}],["dialog",{"_index":2353,"title":{},"content":{"61":{"position":[[206,6]]}},"keywords":{}}],["dice",{"_index":2571,"title":{},"content":{"68":{"position":[[880,4]]},"69":{"position":[[54,4],[344,4],[402,5]]},"72":{"position":[[121,4],[183,5],[329,4],[380,5],[529,4]]},"73":{"position":[[97,4],[819,4]]},"74":{"position":[[372,4]]},"75":{"position":[[258,5]]},"76":{"position":[[1998,4]]},"77":{"position":[[101,5],[161,5]]},"78":{"position":[[25,4]]},"79":{"position":[[21,4]]},"82":{"position":[[147,4]]},"83":{"position":[[129,4]]}},"keywords":{}}],["dict(urllib.parse.parse_qsl(response_url))['access_token",{"_index":2392,"title":{},"content":{"61":{"position":[[2317,58]]}},"keywords":{}}],["dictionari",{"_index":3922,"title":{},"content":{"121":{"position":[[2433,10]]}},"keywords":{}}],["didn't",{"_index":136,"title":{},"content":{"3":{"position":[[45,6],[252,6]]},"40":{"position":[[716,6]]},"76":{"position":[[2943,6]]},"97":{"position":[[3083,6],[5808,6]]},"125":{"position":[[7251,6],[9813,6],[10472,6]]},"143":{"position":[[336,6]]},"158":{"position":[[96,6]]},"163":{"position":[[2460,6]]},"165":{"position":[[56,6]]}},"keywords":{}}],["die",{"_index":2559,"title":{},"content":{"68":{"position":[[348,3],[396,4]]},"70":{"position":[[23,3],[50,3]]},"71":{"position":[[10,3],[107,3],[1093,3],[1121,4]]},"74":{"position":[[318,3],[1547,4]]},"75":{"position":[[1290,4]]},"76":{"position":[[82,3],[1076,3]]},"80":{"position":[[29,3],[65,3]]}},"keywords":{}}],["differ",{"_index":142,"title":{},"content":{"3":{"position":[[182,9],[343,9]]},"9":{"position":[[168,10]]},"15":{"position":[[1261,10]]},"22":{"position":[[2794,9]]},"23":{"position":[[68,9]]},"30":{"position":[[7297,10]]},"38":{"position":[[271,9]]},"39":{"position":[[257,10]]},"43":{"position":[[1132,9]]},"45":{"position":[[1034,9]]},"51":{"position":[[2583,9],[3211,9]]},"53":{"position":[[34,10]]},"68":{"position":[[352,7]]},"72":{"position":[[569,9]]},"74":{"position":[[392,9]]},"85":{"position":[[348,9]]},"86":{"position":[[310,9],[339,9],[1187,9]]},"89":{"position":[[525,9],[757,10]]},"101":{"position":[[969,11],[1095,10]]},"102":{"position":[[843,10],[1151,9]]},"125":{"position":[[7816,9]]},"127":{"position":[[1553,12]]},"135":{"position":[[510,9]]},"153":{"position":[[53,9]]},"161":{"position":[[648,11]]},"163":{"position":[[679,9]]},"165":{"position":[[227,10]]},"169":{"position":[[209,11]]},"172":{"position":[[426,9],[729,9]]},"181":{"position":[[840,9]]},"182":{"position":[[70,9]]},"183":{"position":[[20,10],[267,10]]},"188":{"position":[[2894,11]]},"193":{"position":[[3084,9]]},"196":{"position":[[701,9],[1700,10]]},"199":{"position":[[58,10]]}},"keywords":{}}],["difficult",{"_index":1049,"title":{},"content":{"24":{"position":[[989,9]]},"25":{"position":[[709,9]]},"74":{"position":[[168,9]]},"97":{"position":[[812,9]]},"104":{"position":[[1308,9]]},"106":{"position":[[334,9]]},"120":{"position":[[541,9]]},"139":{"position":[[145,9],[847,9]]},"142":{"position":[[217,9]]}},"keywords":{}}],["difficulti",{"_index":383,"title":{},"content":{"7":{"position":[[129,11]]},"68":{"position":[[186,11]]}},"keywords":{}}],["dig",{"_index":2322,"title":{},"content":{"58":{"position":[[114,7]]},"122":{"position":[[930,3]]},"127":{"position":[[1581,3]]}},"keywords":{}}],["digit",{"_index":3459,"title":{},"content":{"100":{"position":[[235,7]]}},"keywords":{}}],["digress",{"_index":4223,"title":{},"content":{"127":{"position":[[128,8]]}},"keywords":{}}],["dim",{"_index":2005,"title":{},"content":{"45":{"position":[[2243,3],[3023,3]]}},"keywords":{}}],["dim_rang",{"_index":2001,"title":{},"content":{"45":{"position":[[2171,9],[2250,11],[2951,9],[3030,11]]}},"keywords":{}}],["dimens",{"_index":1893,"title":{},"content":{"43":{"position":[[1465,10]]},"45":{"position":[[751,10],[1616,11],[1688,10]]},"103":{"position":[[1179,10]]}},"keywords":{}}],["dimension",{"_index":56,"title":{"44":{"position":[[0,14]]},"45":{"position":[[0,14]]}},"content":{"1":{"position":[[630,11]]},"44":{"position":[[37,14]]},"45":{"position":[[328,14],[697,14],[892,14],[1056,14],[1143,14],[1579,14],[3511,12]]},"46":{"position":[[115,11]]},"73":{"position":[[675,11]]},"85":{"position":[[425,11]]},"102":{"position":[[146,14],[1112,14]]}},"keywords":{}}],["dir",{"_index":4116,"title":{},"content":{"125":{"position":[[5333,3],[5881,3]]}},"keywords":{}}],["dir(8",{"_index":4310,"title":{},"content":{"129":{"position":[[2125,6]]}},"keywords":{}}],["direct",{"_index":1132,"title":{},"content":{"24":{"position":[[3331,9]]},"26":{"position":[[362,9]]}},"keywords":{}}],["directli",{"_index":4172,"title":{},"content":{"125":{"position":[[8760,9]]},"152":{"position":[[640,8]]},"189":{"position":[[150,8]]},"190":{"position":[[928,8]]}},"keywords":{}}],["directori",{"_index":3694,"title":{},"content":{"110":{"position":[[224,9],[322,9]]},"112":{"position":[[510,10],[915,9]]},"134":{"position":[[250,9]]}},"keywords":{}}],["dirti",{"_index":3836,"title":{},"content":{"117":{"position":[[1919,5]]}},"keywords":{}}],["dirtier",{"_index":3313,"title":{},"content":{"95":{"position":[[545,7]]}},"keywords":{}}],["disabl",{"_index":4544,"title":{},"content":{"153":{"position":[[364,7]]},"173":{"position":[[854,7]]}},"keywords":{}}],["disagr",{"_index":4149,"title":{},"content":{"125":{"position":[[7582,12]]}},"keywords":{}}],["disappear",{"_index":4401,"title":{"152":{"position":[[16,12]]}},"content":{"136":{"position":[[912,10]]}},"keywords":{}}],["discard",{"_index":3151,"title":{},"content":{"91":{"position":[[4041,9]]},"199":{"position":[[703,7]]}},"keywords":{}}],["disclaim",{"_index":1677,"title":{"36":{"position":[[14,11]]}},"content":{},"keywords":{}}],["discourag",{"_index":1949,"title":{},"content":{"44":{"position":[[1681,13]]}},"keywords":{}}],["discov",{"_index":1963,"title":{},"content":{"45":{"position":[[247,10]]},"125":{"position":[[1972,9]]}},"keywords":{}}],["discret",{"_index":2572,"title":{},"content":{"68":{"position":[[890,8]]}},"keywords":{}}],["discuss",{"_index":1251,"title":{},"content":{"28":{"position":[[1606,7],[3392,7]]},"73":{"position":[[312,7]]},"125":{"position":[[1876,8],[2689,10],[3645,8]]},"198":{"position":[[347,10]]}},"keywords":{}}],["discussedissu",{"_index":3968,"title":{},"content":{"123":{"position":[[56,15]]}},"keywords":{}}],["disect",{"_index":2951,"title":{},"content":{"89":{"position":[[503,6]]}},"keywords":{}}],["dish",{"_index":4749,"title":{},"content":{"161":{"position":[[1125,4],[1327,4]]}},"keywords":{}}],["dispatch",{"_index":4601,"title":{},"content":{"156":{"position":[[809,11]]},"197":{"position":[[48,8],[100,8],[151,8],[233,8],[682,8],[1496,8]]}},"keywords":{}}],["display",{"_index":406,"title":{},"content":{"7":{"position":[[592,7]]},"17":{"position":[[81,7]]},"121":{"position":[[1930,8]]}},"keywords":{}}],["display("expect",{"_index":855,"title":{},"content":{"20":{"position":[[2510,22],[2655,22]]}},"keywords":{}}],["display("hold",{"_index":848,"title":{},"content":{"20":{"position":[[2342,23]]}},"keywords":{}}],["display(drawdown",{"_index":769,"title":{},"content":{"20":{"position":[[334,18]]}},"keywords":{}}],["display(optimal.messag",{"_index":847,"title":{},"content":{"20":{"position":[[2317,24]]}},"keywords":{}}],["display(sharp",{"_index":754,"title":{},"content":{"19":{"position":[[416,16]]}},"keywords":{}}],["display({tick",{"_index":728,"title":{},"content":{"18":{"position":[[146,14]]}},"keywords":{}}],["display_motion(full_mot",{"_index":523,"title":{},"content":{"11":{"position":[[549,27]]}},"keywords":{}}],["display_motion(mot",{"_index":403,"title":{},"content":{"7":{"position":[[539,22]]},"8":{"position":[[211,22]]}},"keywords":{}}],["dist",{"_index":2164,"title":{},"content":{"51":{"position":[[4117,4],[4216,5]]}},"keywords":{}}],["dist/app.j",{"_index":4170,"title":{},"content":{"125":{"position":[[8681,13]]}},"keywords":{}}],["dist/app_loader.j",{"_index":4171,"title":{},"content":{"125":{"position":[[8697,20],[9148,20]]}},"keywords":{}}],["dist/electron_yew_wasm.j",{"_index":4169,"title":{},"content":{"125":{"position":[[8651,27]]}},"keywords":{}}],["dist/electron_yew_wasm_bg.wasm",{"_index":4166,"title":{},"content":{"125":{"position":[[8480,32],[8616,32]]}},"keywords":{}}],["dist/stdweb_electron.j",{"_index":4179,"title":{},"content":{"125":{"position":[[9120,25]]}},"keywords":{}}],["dist/stdweb_electron_bg.wasm",{"_index":4177,"title":{},"content":{"125":{"position":[[8950,30],[9087,30]]}},"keywords":{}}],["distanc",{"_index":5301,"title":{},"content":{"193":{"position":[[2269,10]]}},"keywords":{}}],["distance(&middl",{"_index":5297,"title":{},"content":{"193":{"position":[[1928,21],[2883,21]]}},"keywords":{}}],["distance(&start",{"_index":5294,"title":{},"content":{"193":{"position":[[1879,20],[2834,20]]}},"keywords":{}}],["distance(a",{"_index":5279,"title":{},"content":{"193":{"position":[[1055,11],[2459,11]]}},"keywords":{}}],["distance_borrowed(a",{"_index":5307,"title":{},"content":{"193":{"position":[[3535,20]]}},"keywords":{}}],["distance_moved(a",{"_index":5306,"title":{},"content":{"193":{"position":[[3234,17]]}},"keywords":{}}],["distil",{"_index":4646,"title":{},"content":{"160":{"position":[[22,10]]}},"keywords":{}}],["distinct",{"_index":3771,"title":{},"content":{"115":{"position":[[904,8]]},"160":{"position":[[1596,12]]},"182":{"position":[[255,11]]}},"keywords":{}}],["distribut",{"_index":1821,"title":{},"content":{"40":{"position":[[2192,12],[3702,12]]},"44":{"position":[[1289,12]]},"49":{"position":[[68,12],[199,12],[418,12],[449,12]]},"51":{"position":[[384,12],[740,14],[1610,13],[1878,13],[3182,13],[3526,13]]},"68":{"position":[[249,12],[323,12],[369,12],[643,15],[668,12],[920,13],[983,13]]},"69":{"position":[[63,12]]},"70":{"position":[[1339,12]]},"71":{"position":[[172,13],[1139,12]]},"72":{"position":[[545,12],[653,12]]},"73":{"position":[[798,12],[865,13]]},"74":{"position":[[322,14],[485,13],[1514,13]]},"75":{"position":[[238,12],[311,12],[1269,12]]},"76":{"position":[[3154,12]]},"77":{"position":[[219,12]]},"78":{"position":[[84,13],[547,14],[637,14],[749,14]]},"82":{"position":[[1187,12],[1275,12]]},"83":{"position":[[109,12],[365,12]]},"125":{"position":[[1403,13]]},"176":{"position":[[369,14]]},"190":{"position":[[461,12],[642,12],[721,11]]}},"keywords":{}}],["distribution?distribut",{"_index":2062,"title":{},"content":{"49":{"position":[[562,25]]}},"keywords":{}}],["ditch",{"_index":2022,"title":{},"content":{"45":{"position":[[2752,5]]}},"keywords":{}}],["div",{"_index":890,"title":{},"content":{"22":{"position":[[346,5]]}},"keywords":{}}],["dive",{"_index":1187,"title":{},"content":{"26":{"position":[[865,4]]}},"keywords":{}}],["divest",{"_index":3189,"title":{},"content":{"93":{"position":[[327,9]]}},"keywords":{}}],["divid",{"_index":1610,"title":{},"content":{"34":{"position":[[1175,6]]},"106":{"position":[[746,7]]}},"keywords":{}}],["dividend",{"_index":379,"title":{},"content":{"7":{"position":[[96,8]]},"9":{"position":[[230,8]]}},"keywords":{}}],["divis",{"_index":825,"title":{},"content":{"20":{"position":[[1645,8],[1665,8]]},"103":{"position":[[971,9]]},"193":{"position":[[957,8]]}},"keywords":{}}],["djia",{"_index":1007,"title":{},"content":{"23":{"position":[[431,4]]},"24":{"position":[[2501,4],[2653,4]]},"25":{"position":[[2224,4],[2376,4]]}},"keywords":{}}],["djia_close_ret",{"_index":1142,"title":{},"content":{"25":{"position":[[512,14],[1435,15]]}},"keywords":{}}],["djia_open_ret",{"_index":1040,"title":{},"content":{"24":{"position":[[795,13],[1714,14]]}},"keywords":{}}],["dnd_ndn",{"_index":1557,"title":{},"content":{"32":{"position":[[2114,8]]},"34":{"position":[[262,11],[3175,8]]}},"keywords":{}}],["do",{"_index":508,"title":{},"content":{"11":{"position":[[67,5]]},"28":{"position":[[121,5]]},"29":{"position":[[45,5]]},"30":{"position":[[9156,5]]},"51":{"position":[[36,5],[1010,5]]},"52":{"position":[[97,5]]},"55":{"position":[[77,5]]},"71":{"position":[[1163,5]]},"103":{"position":[[1964,5]]},"104":{"position":[[948,5],[1948,5]]},"112":{"position":[[201,5]]},"115":{"position":[[3053,5]]},"118":{"position":[[88,5]]},"125":{"position":[[56,5],[11743,5]]},"135":{"position":[[666,6]]},"137":{"position":[[155,6]]},"139":{"position":[[730,5]]},"148":{"position":[[194,5]]},"158":{"position":[[328,5]]},"161":{"position":[[1470,5]]},"172":{"position":[[660,5]]}},"keywords":{}}],["do_cal",{"_index":5350,"title":{},"content":{"197":{"position":[[1154,9]]}},"keywords":{}}],["do_pan",{"_index":4526,"title":{},"content":{"152":{"position":[[1198,9]]},"156":{"position":[[1281,9]]}},"keywords":{}}],["do_panic.load(ordering::seqcst",{"_index":4531,"title":{},"content":{"152":{"position":[[1375,31],[1542,31]]},"156":{"position":[[1458,31],[1625,31]]}},"keywords":{}}],["do_panic.store(fals",{"_index":4523,"title":{},"content":{"152":{"position":[[1063,21]]},"156":{"position":[[1168,21]]}},"keywords":{}}],["do_panic.store(tru",{"_index":4514,"title":{},"content":{"152":{"position":[[535,20]]},"156":{"position":[[976,20]]}},"keywords":{}}],["doc",{"_index":4571,"title":{},"content":{"155":{"position":[[875,4]]},"160":{"position":[[4207,5],[4422,4],[4542,4]]}},"keywords":{}}],["docsgo",{"_index":5355,"title":{},"content":{"198":{"position":[[85,6]]}},"keywords":{}}],["document",{"_index":40,"title":{},"content":{"1":{"position":[[454,13]]},"54":{"position":[[84,9]]},"96":{"position":[[962,13]]},"97":{"position":[[311,13],[561,14],[3041,13],[3205,13]]},"116":{"position":[[2494,13]]},"159":{"position":[[96,8]]},"166":{"position":[[734,10]]},"188":{"position":[[4273,13]]}},"keywords":{}}],["does_trend_down",{"_index":3158,"title":{},"content":{"91":{"position":[[4367,16],[5177,16],[5560,16]]}},"keywords":{}}],["does_trend_down(tick",{"_index":3125,"title":{},"content":{"91":{"position":[[2417,23]]}},"keywords":{}}],["does_trend_up",{"_index":3179,"title":{},"content":{"92":{"position":[[1142,14],[1700,14],[1859,14]]}},"keywords":{}}],["does_trend_up(tick",{"_index":3178,"title":{},"content":{"92":{"position":[[232,21]]}},"keywords":{}}],["doesn't",{"_index":1376,"title":{},"content":{"30":{"position":[[2595,7],[2734,7],[7760,7]]},"34":{"position":[[572,7]]},"39":{"position":[[344,7]]},"40":{"position":[[2238,7]]},"45":{"position":[[1329,7]]},"76":{"position":[[1561,7]]},"82":{"position":[[1248,7]]},"91":{"position":[[3139,7],[3157,7],[3245,7],[3976,7],[4598,7],[5447,7]]},"92":{"position":[[951,7],[969,7],[1057,7]]},"96":{"position":[[798,7]]},"108":{"position":[[640,7]]},"113":{"position":[[2057,7]]},"115":{"position":[[629,7],[866,7]]},"116":{"position":[[884,7],[3040,7]]},"120":{"position":[[1083,7]]},"124":{"position":[[413,7]]},"125":{"position":[[2162,7],[9316,7],[10024,8]]},"145":{"position":[[302,7]]},"146":{"position":[[445,7]]},"147":{"position":[[334,7]]},"152":{"position":[[840,7]]},"153":{"position":[[113,7]]},"166":{"position":[[850,7]]},"173":{"position":[[2217,7]]},"188":{"position":[[2703,7],[3429,7]]},"199":{"position":[[946,7],[1319,7]]}},"keywords":{}}],["doing"",{"_index":4358,"title":{},"content":{"132":{"position":[[938,11]]}},"keywords":{}}],["dollar",{"_index":498,"title":{},"content":{"10":{"position":[[379,6]]},"34":{"position":[[3092,7],[3189,7]]},"127":{"position":[[406,6]]}},"keywords":{}}],["dom",{"_index":46,"title":{},"content":{"1":{"position":[[533,3]]}},"keywords":{}}],["domain",{"_index":1317,"title":{},"content":{"29":{"position":[[419,6]]}},"keywords":{}}],["don't",{"_index":798,"title":{},"content":{"20":{"position":[[963,5]]},"22":{"position":[[2851,5]]},"30":{"position":[[9245,5]]},"34":{"position":[[464,5]]},"38":{"position":[[667,5],[1150,5]]},"40":{"position":[[3058,5]]},"50":{"position":[[40,5]]},"51":{"position":[[177,5]]},"53":{"position":[[869,5]]},"61":{"position":[[85,6]]},"64":{"position":[[1515,5]]},"73":{"position":[[413,5]]},"74":{"position":[[1458,5]]},"85":{"position":[[512,5]]},"90":{"position":[[444,5],[463,5]]},"91":{"position":[[1550,5],[3750,5],[3899,5]]},"96":{"position":[[2019,5]]},"97":{"position":[[104,5],[3002,5],[3139,5],[4325,5]]},"98":{"position":[[682,5]]},"101":{"position":[[187,5]]},"106":{"position":[[194,5],[865,5],[1082,5]]},"108":{"position":[[155,5]]},"112":{"position":[[165,5]]},"115":{"position":[[2791,5]]},"121":{"position":[[745,5],[834,5]]},"123":{"position":[[782,5]]},"125":{"position":[[361,5],[1088,5],[1164,5],[1226,5],[7512,5],[10618,5]]},"127":{"position":[[369,5]]},"129":{"position":[[224,5]]},"137":{"position":[[17,5]]},"143":{"position":[[156,5],[268,5]]},"155":{"position":[[830,5]]},"158":{"position":[[125,5]]},"159":{"position":[[1203,5]]},"161":{"position":[[1073,5]]},"163":{"position":[[599,5]]},"166":{"position":[[674,5]]},"172":{"position":[[1043,5],[2414,5]]},"181":{"position":[[900,5]]},"189":{"position":[[1532,5]]},"194":{"position":[[191,5]]},"196":{"position":[[503,5],[828,5]]}},"keywords":{}}],["done",{"_index":484,"title":{},"content":{"10":{"position":[[104,4]]},"35":{"position":[[214,4]]},"43":{"position":[[207,4]]},"51":{"position":[[959,4],[1488,5]]},"53":{"position":[[835,5]]},"64":{"position":[[385,5]]},"89":{"position":[[333,4]]},"93":{"position":[[1071,5]]},"95":{"position":[[225,4],[321,4]]},"97":{"position":[[2427,5]]},"108":{"position":[[801,4]]},"111":{"position":[[151,4]]},"112":{"position":[[11,4]]},"124":{"position":[[58,5],[628,4]]},"125":{"position":[[6089,4],[6982,4]]},"183":{"position":[[820,5]]},"197":{"position":[[1585,5]]}},"keywords":{}}],["door",{"_index":4495,"title":{},"content":{"150":{"position":[[458,4]]}},"keywords":{}}],["dope",{"_index":3849,"title":{},"content":{"120":{"position":[[173,5]]}},"keywords":{}}],["doubl",{"_index":674,"title":{},"content":{"15":{"position":[[501,6]]},"127":{"position":[[241,6]]},"188":{"position":[[1932,6]]}},"keywords":{}}],["dough",{"_index":4737,"title":{},"content":{"161":{"position":[[603,5],[706,5],[767,5],[907,6],[1028,5]]}},"keywords":{}}],["dow",{"_index":993,"title":{},"content":{"23":{"position":[[111,3]]},"24":{"position":[[2544,3],[2716,3],[2938,3],[3029,3],[3446,3]]},"25":{"position":[[2267,3],[2439,3]]},"26":{"position":[[507,3]]}},"keywords":{}}],["down",{"_index":300,"title":{"91":{"position":[[23,4]]},"120":{"position":[[5,5]]}},"content":{"4":{"position":[[1527,5]]},"28":{"position":[[4396,4]]},"30":{"position":[[2369,4]]},"33":{"position":[[1097,4]]},"40":{"position":[[1596,5]]},"57":{"position":[[113,5],[123,5],[133,4]]},"62":{"position":[[344,4]]},"65":{"position":[[1343,4]]},"88":{"position":[[2774,4],[3170,4],[3639,5],[3747,5]]},"89":{"position":[[579,4]]},"91":{"position":[[90,4],[329,4],[1442,4],[1519,4],[2990,4],[3185,4],[4539,4],[5054,4],[5363,4]]},"92":{"position":[[135,4],[802,4],[997,4]]},"96":{"position":[[151,4]]},"101":{"position":[[418,4]]},"103":{"position":[[1928,4]]},"104":{"position":[[106,5]]},"116":{"position":[[2838,5]]},"121":{"position":[[2172,4]]},"125":{"position":[[6782,4]]},"129":{"position":[[506,4]]},"136":{"position":[[1006,4]]}},"keywords":{}}],["down."",{"_index":3074,"title":{},"content":{"91":{"position":[[212,11]]}},"keywords":{}}],["download",{"_index":873,"title":{"22":{"position":[[0,11]]}},"content":{"22":{"position":[[2996,11]]},"93":{"position":[[3735,11]]},"108":{"position":[[674,8]]},"160":{"position":[[2970,8]]}},"keywords":{}}],["downtrend",{"_index":3126,"title":{},"content":{"91":{"position":[[2492,9]]}},"keywords":{}}],["downturn",{"_index":763,"title":{},"content":{"20":{"position":[[170,9]]}},"keywords":{}}],["downward",{"_index":2952,"title":{},"content":{"89":{"position":[[661,8]]}},"keywords":{}}],["dr",{"_index":2409,"title":{"153":{"position":[[0,3]]}},"content":{"62":{"position":[[637,2],[830,3]]}},"keywords":{}}],["draft",{"_index":2254,"title":{},"content":{"53":{"position":[[1187,5]]}},"keywords":{}}],["dragon",{"_index":4067,"title":{},"content":{"125":{"position":[[2665,8]]}},"keywords":{}}],["dramat",{"_index":4216,"title":{},"content":{"125":{"position":[[11536,12]]},"174":{"position":[[1069,13]]}},"keywords":{}}],["drastic",{"_index":3542,"title":{},"content":{"103":{"position":[[1912,11]]}},"keywords":{}}],["drawdown",{"_index":704,"title":{"20":{"position":[[16,9]]}},"content":{"17":{"position":[[43,8]]},"20":{"position":[[231,8],[270,9],[902,8],[2682,9],[3008,9]]}},"keywords":{}}],["drawdown(returns[tick",{"_index":768,"title":{},"content":{"20":{"position":[[289,23]]}},"keywords":{}}],["drawdown_limit",{"_index":806,"title":{},"content":{"20":{"position":[[1076,14],[1734,14]]}},"keywords":{}}],["drawdowns[tick",{"_index":816,"title":{},"content":{"20":{"position":[[1322,16]]}},"keywords":{}}],["dream",{"_index":2196,"title":{},"content":{"53":{"position":[[66,7]]},"106":{"position":[[506,5]]}},"keywords":{}}],["dri",{"_index":4747,"title":{},"content":{"161":{"position":[[1039,6]]}},"keywords":{}}],["drift",{"_index":335,"title":{},"content":{"6":{"position":[[488,5]]},"9":{"position":[[142,5]]},"11":{"position":[[270,6]]}},"keywords":{}}],["drive",{"_index":2255,"title":{},"content":{"53":{"position":[[1204,6]]},"120":{"position":[[867,6]]},"139":{"position":[[634,7]]}},"keywords":{}}],["driven",{"_index":4667,"title":{},"content":{"160":{"position":[[917,6]]}},"keywords":{}}],["driver",{"_index":4997,"title":{},"content":{"174":{"position":[[1288,8]]}},"keywords":{}}],["drop",{"_index":985,"title":{"104":{"position":[[0,4]]}},"content":{"22":{"position":[[3021,4]]},"40":{"position":[[2289,4]]},"65":{"position":[[1338,4]]},"90":{"position":[[4922,7]]},"121":{"position":[[2164,7]]},"139":{"position":[[198,5]]},"143":{"position":[[77,4]]},"145":{"position":[[320,4],[390,4]]},"152":{"position":[[746,4]]},"155":{"position":[[1360,4],[1422,4],[1484,4],[1547,4]]},"156":{"position":[[644,4]]}},"keywords":{}}],["drop(i",{"_index":4520,"title":{},"content":{"152":{"position":[[765,8]]}},"keywords":{}}],["drop(x",{"_index":4602,"title":{},"content":{"156":{"position":[[1083,8]]}},"keywords":{}}],["drum",{"_index":3551,"title":{},"content":{"103":{"position":[[2407,5]]}},"keywords":{}}],["dt",{"_index":1490,"title":{},"content":{"30":{"position":[[9812,2],[9855,4],[9881,3],[9939,4]]}},"keywords":{}}],["dt_indic",{"_index":1478,"title":{},"content":{"30":{"position":[[9292,10],[9446,11]]}},"keywords":{}}],["dt_merg",{"_index":1480,"title":{},"content":{"30":{"position":[[9403,8],[9818,9]]}},"keywords":{}}],["dtpars",{"_index":3969,"title":{"136":{"position":[[11,8]]}},"content":{"123":{"position":[[139,8]]},"124":{"position":[[350,7],[518,8]]},"132":{"position":[[35,7]]},"136":{"position":[[252,10],[496,7]]}},"keywords":{}}],["dtparse::pars",{"_index":4379,"title":{},"content":{"135":{"position":[[443,15]]},"136":{"position":[[62,15]]}},"keywords":{}}],["dtparsehyp",{"_index":4346,"title":{},"content":{"132":{"position":[[400,12]]}},"keywords":{}}],["dtparser.parse(date_str",{"_index":942,"title":{},"content":{"22":{"position":[[1539,27]]}},"keywords":{}}],["dtype=int64",{"_index":1875,"title":{},"content":{"43":{"position":[[635,12]]}},"keywords":{}}],["dualiti",{"_index":4007,"title":{},"content":{"125":{"position":[[96,7]]}},"keywords":{}}],["due",{"_index":1807,"title":{},"content":{"40":{"position":[[1318,3]]},"91":{"position":[[3795,3]]},"115":{"position":[[2462,3]]},"116":{"position":[[2320,3]]},"169":{"position":[[225,3]]},"189":{"position":[[1296,3]]}},"keywords":{}}],["durat",{"_index":3517,"title":{},"content":{"103":{"position":[[638,8]]},"172":{"position":[[323,8]]}},"keywords":{}}],["dure",{"_index":1350,"title":{},"content":{"30":{"position":[[1026,6],[4579,6]]},"40":{"position":[[1528,6],[3230,6],[3453,6]]},"51":{"position":[[2602,6]]},"54":{"position":[[1,6]]},"101":{"position":[[691,6]]},"125":{"position":[[8446,6]]},"135":{"position":[[276,6],[362,6],[436,6]]},"136":{"position":[[46,6]]},"147":{"position":[[403,6],[551,6]]},"161":{"position":[[1476,6],[1619,6]]},"166":{"position":[[877,6]]},"172":{"position":[[2391,6]]},"176":{"position":[[495,6]]},"183":{"position":[[887,6]]},"199":{"position":[[677,6]]}},"keywords":{}}],["dutch",{"_index":4746,"title":{},"content":{"161":{"position":[[978,5],[1085,5]]}},"keywords":{}}],["dword",{"_index":4261,"title":{},"content":{"128":{"position":[[523,5],[636,5],[870,5],[1588,5]]},"183":{"position":[[387,5],[533,5]]}},"keywords":{}}],["dwrensha",{"_index":4802,"title":{},"content":{"164":{"position":[[150,8]]}},"keywords":{}}],["dyn",{"_index":5338,"title":{},"content":{"197":{"position":[[125,3]]}},"keywords":{}}],["dynam",{"_index":3310,"title":{"154":{"position":[[21,7]]}},"content":{"95":{"position":[[404,7]]},"97":{"position":[[915,11],[6267,12]]},"141":{"position":[[338,11]]},"155":{"position":[[168,7]]},"156":{"position":[[62,7],[177,7]]},"160":{"position":[[1722,7]]},"197":{"position":[[92,7],[143,7],[225,7],[674,7],[1488,7]]}},"keywords":{}}],["e",{"_index":1493,"title":{},"content":{"30":{"position":[[9905,2]]},"93":{"position":[[2554,1]]}},"keywords":{}}],["e.dat",{"_index":3242,"title":{},"content":{"93":{"position":[[2816,8]]}},"keywords":{}}],["e.earnings_offset",{"_index":3239,"title":{},"content":{"93":{"position":[[2726,17],[2797,18]]}},"keywords":{}}],["e.feed(str(s.get(base_url",{"_index":3237,"title":{},"content":{"93":{"position":[[2669,26]]}},"keywords":{}}],["e.g",{"_index":4922,"title":{},"content":{"172":{"position":[[1585,5]]}},"keywords":{}}],["each",{"_index":154,"title":{},"content":{"3":{"position":[[439,4],[1433,4]]},"4":{"position":[[1205,4]]},"7":{"position":[[1054,4]]},"18":{"position":[[32,4]]},"22":{"position":[[128,4]]},"24":{"position":[[64,4],[226,4]]},"28":{"position":[[734,4]]},"38":{"position":[[871,4]]},"51":{"position":[[1569,4]]},"71":{"position":[[1077,4]]},"74":{"position":[[443,4],[773,4],[873,4],[1542,4]]},"75":{"position":[[351,4],[605,4],[1285,4]]},"76":{"position":[[252,4],[539,4]]},"85":{"position":[[230,4]]},"86":{"position":[[1006,4]]},"90":{"position":[[76,4],[4292,4],[4504,4],[4611,4],[4789,4],[5097,4],[5274,4]]},"91":{"position":[[287,4],[1763,4]]},"104":{"position":[[205,4]]},"124":{"position":[[563,4]]},"135":{"position":[[201,4]]},"159":{"position":[[373,4]]},"163":{"position":[[106,4]]},"164":{"position":[[1060,4]]},"165":{"position":[[776,4],[1249,4]]},"167":{"position":[[281,4]]},"169":{"position":[[177,4]]},"172":{"position":[[190,4],[416,4]]},"188":{"position":[[2787,4]]},"189":{"position":[[1488,4]]},"193":{"position":[[55,4]]},"196":{"position":[[655,4]]},"197":{"position":[[892,4]]},"199":{"position":[[979,4]]}},"keywords":{}}],["each.mak",{"_index":1176,"title":{},"content":{"26":{"position":[[672,11]]}},"keywords":{}}],["earli",{"_index":3910,"title":{},"content":{"121":{"position":[[1844,5]]}},"keywords":{}}],["earlier",{"_index":2027,"title":{},"content":{"45":{"position":[[3404,7]]},"110":{"position":[[340,7]]},"111":{"position":[[546,8]]},"118":{"position":[[250,7]]},"127":{"position":[[534,8]]},"185":{"position":[[371,7],[557,7]]}},"keywords":{}}],["earlierstruct",{"_index":3424,"title":{},"content":{"97":{"position":[[5392,14]]}},"keywords":{}}],["earlybirthday",{"_index":2237,"title":{},"content":{"53":{"position":[[922,14]]}},"keywords":{}}],["earn",{"_index":1225,"title":{"87":{"position":[[18,8]]}},"content":{"28":{"position":[[812,6]]},"88":{"position":[[2115,8],[3672,8],[3757,8]]},"89":{"position":[[189,8],[435,8],[615,8],[872,8]]},"91":{"position":[[1479,8],[2130,8],[4565,8],[4742,8],[4918,8],[5091,9]]},"92":{"position":[[1389,8]]},"93":{"position":[[121,8],[238,8],[347,8],[1898,8]]}},"keywords":{}}],["earnings_data",{"_index":3113,"title":{},"content":{"91":{"position":[[2069,13]]},"93":{"position":[[4482,13]]}},"keywords":{}}],["earnings_data.item",{"_index":3121,"title":{},"content":{"91":{"position":[[2318,22]]}},"keywords":{}}],["earnings_data[tick",{"_index":3282,"title":{},"content":{"93":{"position":[[4837,21],[5252,21]]}},"keywords":{}}],["earnings_offset",{"_index":3204,"title":{},"content":{"93":{"position":[[1511,15]]}},"keywords":{}}],["earnings_releases(tick",{"_index":3218,"title":{},"content":{"93":{"position":[[2261,26]]}},"keywords":{}}],["earningspars",{"_index":3233,"title":{},"content":{"93":{"position":[[2558,16]]}},"keywords":{}}],["earningsparser(htmlpars",{"_index":3202,"title":{},"content":{"93":{"position":[[1463,27]]}},"keywords":{}}],["easi",{"_index":54,"title":{},"content":{"1":{"position":[[612,5]]},"20":{"position":[[13,4]]},"64":{"position":[[190,4]]},"66":{"position":[[407,4]]},"72":{"position":[[54,4]]},"90":{"position":[[142,4]]},"91":{"position":[[2193,4]]},"95":{"position":[[437,4]]},"96":{"position":[[102,4]]},"97":{"position":[[1092,4]]},"104":{"position":[[1236,4],[1893,4]]},"106":{"position":[[675,4]]},"108":{"position":[[491,4]]},"110":{"position":[[509,5]]},"121":{"position":[[569,4],[1818,4]]},"122":{"position":[[662,5]]},"128":{"position":[[337,4]]},"134":{"position":[[184,5]]},"158":{"position":[[402,4]]}},"keywords":{}}],["easier",{"_index":998,"title":{},"content":{"23":{"position":[[211,7]]},"39":{"position":[[330,7]]},"74":{"position":[[1184,6]]},"116":{"position":[[133,6]]}},"keywords":{}}],["easiest",{"_index":4446,"title":{},"content":{"144":{"position":[[5,7]]}},"keywords":{}}],["easili",{"_index":378,"title":{},"content":{"7":{"position":[[80,6]]}},"keywords":{}}],["eaten",{"_index":2270,"title":{},"content":{"53":{"position":[[1420,5]]}},"keywords":{}}],["eax",{"_index":4265,"title":{},"content":{"128":{"position":[[631,4],[663,3],[729,4]]}},"keywords":{}}],["echo",{"_index":3321,"title":{},"content":{"96":{"position":[[352,4]]},"97":{"position":[[3817,4],[4591,7],[4715,6],[6422,5]]},"104":{"position":[[1624,5]]}},"keywords":{}}],["echo.handl",{"_index":3408,"title":{},"content":{"97":{"position":[[3906,12]]}},"keywords":{}}],["echo.handle(req",{"_index":3413,"title":{},"content":{"97":{"position":[[4463,17],[4899,17]]}},"keywords":{}}],["echo_handler(request",{"_index":3324,"title":{},"content":{"96":{"position":[[464,22]]}},"keywords":{}}],["echohandl",{"_index":3401,"title":{},"content":{"97":{"position":[[3572,11],[3621,11],[3824,11],[4138,13]]}},"keywords":{}}],["ecosystem",{"_index":3935,"title":{},"content":{"122":{"position":[[169,10]]},"125":{"position":[[7452,10]]}},"keywords":{}}],["edg",{"_index":2285,"title":{"69":{"position":[[4,4]]},"70":{"position":[[0,4]]},"71":{"position":[[0,4]]}},"content":{"53":{"position":[[1948,4],[2067,4]]},"68":{"position":[[151,4]]},"69":{"position":[[110,4]]},"72":{"position":[[267,4]]},"105":{"position":[[19,4]]}},"keywords":{}}],["edi",{"_index":4264,"title":{},"content":{"128":{"position":[[619,7],[658,4],[832,7],[889,3],[1418,4],[1605,3]]},"181":{"position":[[174,4],[301,4],[432,4]]}},"keywords":{}}],["edit",{"_index":4254,"title":{},"content":{"128":{"position":[[433,6],[1258,6]]}},"keywords":{}}],["editor",{"_index":3911,"title":{},"content":{"121":{"position":[[1918,6]]}},"keywords":{}}],["effect",{"_index":2360,"title":{},"content":{"61":{"position":[[905,12]]},"90":{"position":[[3597,11]]},"91":{"position":[[2965,12]]},"92":{"position":[[777,12]]},"104":{"position":[[2041,7]]},"117":{"position":[[2052,7]]},"130":{"position":[[141,8]]},"176":{"position":[[1036,7]]},"188":{"position":[[1782,11],[3301,11]]},"189":{"position":[[1941,11]]},"196":{"position":[[687,7]]}},"keywords":{}}],["effici",{"_index":2094,"title":{},"content":{"51":{"position":[[974,9]]},"130":{"position":[[207,9]]},"132":{"position":[[413,10]]},"137":{"position":[[62,9]]},"175":{"position":[[361,9]]}},"keywords":{}}],["effort",{"_index":2017,"title":{},"content":{"45":{"position":[[2513,6]]},"97":{"position":[[2221,7]]},"125":{"position":[[10163,6]]}},"keywords":{}}],["eight",{"_index":5323,"title":{},"content":{"195":{"position":[[762,5]]}},"keywords":{}}],["eightk",{"_index":4550,"title":{},"content":{"153":{"position":[[590,6],[668,8]]},"195":{"position":[[287,6],[382,8]]}},"keywords":{}}],["eightm",{"_index":4552,"title":{},"content":{"153":{"position":[[709,6],[835,8]]},"195":{"position":[[601,6]]}},"keywords":{}}],["eightm::default",{"_index":4555,"title":{},"content":{"153":{"position":[[1007,18]]},"195":{"position":[[823,18]]}},"keywords":{}}],["eject",{"_index":165,"title":{},"content":{"3":{"position":[[605,5]]}},"keywords":{}}],["elaps",{"_index":3160,"title":{},"content":{"91":{"position":[[4468,7],[5278,7],[5661,7]]},"92":{"position":[[1241,7],[1799,7],[1958,7]]}},"keywords":{}}],["electron",{"_index":4029,"title":{},"content":{"125":{"position":[[831,8],[1436,9],[1463,8],[1613,8],[1721,8],[3560,8],[3824,8],[4634,9],[4852,8],[6215,8],[6272,8],[6855,8],[7171,8],[10561,8],[10692,8],[11223,8],[11684,8]]}},"keywords":{}}],["electron/wasm/rust",{"_index":4204,"title":{},"content":{"125":{"position":[[10997,18]]}},"keywords":{}}],["elem",{"_index":3134,"title":{},"content":{"91":{"position":[[3010,5]]},"92":{"position":[[822,5]]}},"keywords":{}}],["element",{"_index":3585,"title":{},"content":{"105":{"position":[[756,7]]},"156":{"position":[[750,8]]},"185":{"position":[[291,8],[594,7]]},"194":{"position":[[510,7]]}},"keywords":{}}],["elementsin",{"_index":4831,"title":{},"content":{"165":{"position":[[882,10]]}},"keywords":{}}],["elif",{"_index":958,"title":{},"content":{"22":{"position":[[1969,4],[2041,4],[2112,4],[2182,4]]},"93":{"position":[[2113,4]]},"121":{"position":[[1665,4]]}},"keywords":{}}],["elimin",{"_index":4519,"title":{},"content":{"152":{"position":[[754,10]]}},"keywords":{}}],["elseif",{"_index":648,"title":{},"content":{"14":{"position":[[1758,6]]},"15":{"position":[[1148,6]]}},"keywords":{}}],["elsewher",{"_index":3302,"title":{},"content":{"95":{"position":[[96,9]]},"188":{"position":[[725,10]]}},"keywords":{}}],["em",{"_index":2827,"title":{},"content":{"86":{"position":[[148,2],[611,2],[760,2],[1035,2]]}},"keywords":{}}],["emb",{"_index":4101,"title":{},"content":{"125":{"position":[[4817,5]]}},"keywords":{}}],["embed",{"_index":4098,"title":{},"content":{"125":{"position":[[4426,9]]},"160":{"position":[[1771,8],[2649,8],[2812,8]]}},"keywords":{}}],["emerg",{"_index":3171,"title":{},"content":{"91":{"position":[[5416,8]]}},"keywords":{}}],["emphasi",{"_index":4701,"title":{},"content":{"160":{"position":[[3287,8]]}},"keywords":{}}],["emscripten",{"_index":4065,"title":{},"content":{"125":{"position":[[2551,11]]}},"keywords":{}}],["enabl",{"_index":5059,"title":{},"content":{"178":{"position":[[224,7]]},"190":{"position":[[975,7]]}},"keywords":{}}],["encod",{"_index":3489,"title":{"166":{"position":[[14,9]]}},"content":{"102":{"position":[[45,8],[1480,8]]},"104":{"position":[[1696,8]]},"110":{"position":[[578,6]]},"164":{"position":[[828,10]]}},"keywords":{}}],["encount",{"_index":80,"title":{},"content":{"2":{"position":[[78,12]]}},"keywords":{}}],["encourag",{"_index":4839,"title":{},"content":{"166":{"position":[[173,11]]}},"keywords":{}}],["end",{"_index":219,"title":{},"content":{"4":{"position":[[3,5],[1399,4]]},"7":{"position":[[508,3],[526,3],[923,3],[1030,3],[1205,3],[1352,4]]},"9":{"position":[[821,4]]},"11":{"position":[[545,3]]},"12":{"position":[[506,3],[530,3]]},"13":{"position":[[889,3],[893,3],[1086,3],[1090,3],[1439,3],[1654,3]]},"14":{"position":[[696,3],[840,3],[951,3],[1033,3],[1907,3],[1911,3],[2120,3],[2124,3],[2511,3],[2737,3]]},"15":{"position":[[1575,3],[1579,3],[1788,3],[1792,3],[2183,3],[2411,3]]},"30":{"position":[[10354,3]]},"32":{"position":[[1153,4]]},"33":{"position":[[479,4]]},"34":{"position":[[1351,4],[1582,3],[2511,3],[2694,3],[3004,4],[3244,3]]},"39":{"position":[[2171,4]]},"40":{"position":[[1236,3]]},"45":{"position":[[952,4],[1437,3],[2643,3]]},"46":{"position":[[588,3]]},"51":{"position":[[3127,4]]},"53":{"position":[[1627,5]]},"58":{"position":[[337,6],[820,6]]},"76":{"position":[[2153,3],[3306,6]]},"78":{"position":[[318,3]]},"88":{"position":[[595,5],[2463,4]]},"93":{"position":[[4010,5]]},"95":{"position":[[525,3]]},"101":{"position":[[38,6]]},"102":{"position":[[404,3]]},"103":{"position":[[597,3],[1654,3]]},"104":{"position":[[1940,4]]},"105":{"position":[[3327,3]]},"118":{"position":[[272,5]]},"125":{"position":[[4792,3]]},"137":{"position":[[8,4]]},"150":{"position":[[384,4]]},"153":{"position":[[452,3]]},"160":{"position":[[3675,3]]},"161":{"position":[[1507,4]]},"164":{"position":[[1436,4]]},"193":{"position":[[1837,3],[2792,3]]},"199":{"position":[[729,5]]}},"keywords":{}}],["end=datetime(year",{"_index":1241,"title":{},"content":{"28":{"position":[[1304,18],[3104,18]]},"30":{"position":[[1670,18],[3019,18],[4943,18],[6087,18],[9352,18]]}},"keywords":{}}],["end_dat",{"_index":2408,"title":{},"content":{"62":{"position":[[604,8],[668,9]]},"90":{"position":[[3750,8],[3832,9]]}},"keywords":{}}],["end_date=end.strftime(q_format",{"_index":2858,"title":{},"content":{"88":{"position":[[847,32]]},"93":{"position":[[4262,32]]}},"keywords":{}}],["ending_pric",{"_index":1741,"title":{},"content":{"39":{"position":[[2002,12],[2041,12],[2089,12]]}},"keywords":{}}],["end{align*}cn​i=1∑n−1​oi​di​​+on​cn​dn​​on​cn​dn​​−dn​dn​(on​cn​−on​​)dn​​>i=1∑n−1​di​+dn​>i=1∑n−1​(di​−oi​cn​di​​)>i=1∑n−1​di​(1−oi​cn​​)>cn​−on​on​​i=1∑n−1​di​(1−oi​1",{"_index":1555,"title":{},"content":{"32":{"position":[[1906,184]]}},"keywords":{}}],["end{align*}d1​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​e[d1​]=3.5​d2​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​e[d2​]=3.5​e[d1​+d2​]=7=e[dfair​+dfair",{"_index":2609,"title":{},"content":{"71":{"position":[[844,188]]}},"keywords":{}}],["end{align*}d1​=⎩⎨⎧​123456​w.p.1/3w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12​e[d1​]=2.5​d2​=⎩⎨⎧​123456​w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3w.p.1/3​e[d2​]=4.5​e[d1​+d2​]=7=e[dfair​+dfair",{"_index":2592,"title":{},"content":{"70":{"position":[[744,188]]}},"keywords":{}}],["end{align*}l(x)=⎩⎨⎧​p2​p3​…p11​p12​​x=2x=3x=11x=12",{"_index":2641,"title":{},"content":{"74":{"position":[[712,53]]}},"keywords":{}}],["end{align*}l(x)​=i=1∏n​l(x",{"_index":2648,"title":{},"content":{"74":{"position":[[1124,29]]}},"keywords":{}}],["end{align*}log(l)​=i=1∑n​log(l",{"_index":2661,"title":{},"content":{"74":{"position":[[1727,33]]}},"keywords":{}}],["end{align*}max",{"_index":790,"title":{},"content":{"20":{"position":[[752,15]]}},"keywords":{}}],["end{array",{"_index":2585,"title":{},"content":{"70":{"position":[[423,11],[597,11],[670,13]]},"71":{"position":[[523,11],[697,11],[770,13]]},"74":{"position":[[692,11]]}},"keywords":{}}],["end{equation*}hrq​⋅n−hrd​⋅(n−m",{"_index":2461,"title":{},"content":{"64":{"position":[[570,33]]},"65":{"position":[[466,33]]}},"keywords":{}}],["enforc",{"_index":3822,"title":{},"content":{"117":{"position":[[636,7],[818,8]]}},"keywords":{}}],["engin",{"_index":2148,"title":{},"content":{"51":{"position":[[3553,6]]},"125":{"position":[[3393,11]]}},"keywords":{}}],["enhanced_packet",{"_index":4776,"title":{},"content":{"163":{"position":[[1684,16]]}},"keywords":{}}],["enhanced_packet_block(input",{"_index":4779,"title":{},"content":{"163":{"position":[[1744,28]]}},"keywords":{}}],["enjoy",{"_index":1183,"title":{},"content":{"26":{"position":[[821,7],[843,7]]},"41":{"position":[[19,8]]},"125":{"position":[[7258,5]]},"130":{"position":[[279,5]]},"150":{"position":[[184,5],[605,5]]},"165":{"position":[[333,7],[1396,7]]}},"keywords":{}}],["enough",{"_index":827,"title":{},"content":{"20":{"position":[[1693,6]]},"25":{"position":[[2781,6]]},"45":{"position":[[2688,6]]},"53":{"position":[[1403,6]]},"74":{"position":[[1637,7]]},"88":{"position":[[139,6]]},"102":{"position":[[278,7]]},"106":{"position":[[67,7]]},"124":{"position":[[114,7]]},"125":{"position":[[7952,6]]},"132":{"position":[[361,7]]},"150":{"position":[[638,6]]},"161":{"position":[[847,7]]},"181":{"position":[[583,6],[892,7]]},"194":{"position":[[97,6]]},"195":{"position":[[113,7]]}},"keywords":{}}],["enough"",{"_index":3576,"title":{},"content":{"105":{"position":[[238,12]]}},"keywords":{}}],["enougho",{"_index":3669,"title":{},"content":{"108":{"position":[[451,8]]}},"keywords":{}}],["ensur",{"_index":2697,"title":{},"content":{"76":{"position":[[1007,6]]},"90":{"position":[[434,6]]},"160":{"position":[[1391,6]]},"196":{"position":[[1902,7]]}},"keywords":{}}],["enter_protect",{"_index":4466,"title":{},"content":{"146":{"position":[[264,18]]}},"keywords":{}}],["entir",{"_index":2023,"title":{},"content":{"45":{"position":[[2776,6]]},"58":{"position":[[775,6]]},"63":{"position":[[117,6]]},"74":{"position":[[1010,6]]},"88":{"position":[[661,6]]},"91":{"position":[[3229,6]]},"92":{"position":[[1041,6]]},"93":{"position":[[76,6],[481,6],[4076,6]]},"103":{"position":[[2424,8]]},"144":{"position":[[30,6]]},"174":{"position":[[918,9]]}},"keywords":{}}],["entri",{"_index":178,"title":{},"content":{"3":{"position":[[850,5]]},"136":{"position":[[230,5]]}},"keywords":{}}],["enum",{"_index":3886,"title":{"194":{"position":[[0,6]]}},"content":{"121":{"position":[[866,6]]},"159":{"position":[[651,6]]},"194":{"position":[[170,4],[219,4],[478,4],[610,4],[656,5]]}},"keywords":{}}],["enum_compar",{"_index":5314,"title":{},"content":{"194":{"position":[[306,14]]}},"keywords":{}}],["enumerate(all_word",{"_index":2105,"title":{},"content":{"51":{"position":[[1337,20]]}},"keywords":{}}],["env",{"_index":4167,"title":{},"content":{"125":{"position":[[8552,5],[9020,5]]}},"keywords":{}}],["environ",{"_index":3676,"title":{},"content":{"108":{"position":[[755,11]]},"113":{"position":[[469,11]]},"176":{"position":[[1318,11],[1378,11]]}},"keywords":{}}],["epoch",{"_index":1471,"title":{},"content":{"30":{"position":[[8933,5],[9024,6]]}},"keywords":{}}],["eq",{"_index":838,"title":{},"content":{"20":{"position":[[2040,5]]}},"keywords":{}}],["equal",{"_index":4518,"title":{},"content":{"152":{"position":[[712,6]]}},"keywords":{}}],["equipmentfor",{"_index":5008,"title":{},"content":{"175":{"position":[[426,12]]}},"keywords":{}}],["equival",{"_index":3566,"title":{},"content":{"104":{"position":[[1132,10]]},"132":{"position":[[104,10]]},"173":{"position":[[292,10]]},"196":{"position":[[1486,10]]}},"keywords":{}}],["eric",{"_index":2257,"title":{},"content":{"53":{"position":[[1228,4]]}},"keywords":{}}],["error",{"_index":94,"title":{},"content":{"2":{"position":[[298,6]]},"3":{"position":[[67,6]]},"74":{"position":[[1445,6]]},"96":{"position":[[260,5],[1242,6],[1771,6],[1780,6]]},"97":{"position":[[1794,7],[4070,7],[4080,6],[4511,6]]},"98":{"position":[[1009,6]]},"115":{"position":[[913,6],[2446,6],[2480,6],[2565,6]]},"116":{"position":[[903,6],[2304,6],[2338,6],[2638,5]]},"125":{"position":[[4527,6],[7727,6],[8471,5],[8531,6],[8941,5],[8999,6],[11244,5]]},"127":{"position":[[703,5],[719,5],[743,6],[815,5]]},"153":{"position":[[499,7]]},"160":{"position":[[4266,5]]},"179":{"position":[[1754,6]]},"184":{"position":[[974,5]]},"188":{"position":[[3659,6]]},"190":{"position":[[773,6]]}},"keywords":{}}],["error=()>",{"_index":4476,"title":{},"content":{"147":{"position":[[250,12]]}},"keywords":{}}],["error[e0204",{"_index":5367,"title":{},"content":{"198":{"position":[[1032,13]]}},"keywords":{}}],["error[e0277",{"_index":3378,"title":{},"content":{"97":{"position":[[1835,13]]},"115":{"position":[[927,13],[1241,13],[1621,13],[1898,13]]},"116":{"position":[[926,13],[1193,13],[1526,13],[1803,13]]},"184":{"position":[[1025,13]]},"185":{"position":[[706,13]]}},"keywords":{}}],["error[e0369",{"_index":3338,"title":{},"content":{"96":{"position":[[1251,13]]}},"keywords":{}}],["error[e0373",{"_index":3414,"title":{},"content":{"97":{"position":[[4520,13]]}},"keywords":{}}],["error[e0507",{"_index":3422,"title":{},"content":{"97":{"position":[[4978,13]]}},"keywords":{}}],["es",{"_index":4185,"title":{},"content":{"125":{"position":[[9474,2]]}},"keywords":{}}],["es6",{"_index":4143,"title":{},"content":{"125":{"position":[[6792,3]]}},"keywords":{}}],["especi",{"_index":2957,"title":{},"content":{"89":{"position":[[901,10]]},"139":{"position":[[204,10]]},"142":{"position":[[153,10]]},"150":{"position":[[751,10]]}},"keywords":{}}],["essenti",{"_index":2352,"title":{},"content":{"61":{"position":[[190,11]]},"96":{"position":[[840,11]]},"97":{"position":[[5410,11]]},"102":{"position":[[1262,11]]},"125":{"position":[[9876,9]]},"133":{"position":[[380,11]]}},"keywords":{}}],["essentiallyjust",{"_index":4845,"title":{},"content":{"166":{"position":[[474,15]]}},"keywords":{}}],["establish",{"_index":4085,"title":{},"content":{"125":{"position":[[3704,11]]}},"keywords":{}}],["estim",{"_index":2118,"title":{},"content":{"51":{"position":[[2030,9]]},"57":{"position":[[587,8]]},"58":{"position":[[444,9],[657,10]]},"65":{"position":[[156,8],[2213,8]]},"105":{"position":[[391,8],[903,8]]}},"keywords":{}}],["etc",{"_index":1911,"title":{},"content":{"44":{"position":[[554,4]]},"91":{"position":[[3991,6]]},"92":{"position":[[1463,6]]},"96":{"position":[[1990,5]]},"97":{"position":[[3112,4]]},"98":{"position":[[608,5]]},"104":{"position":[[1724,5]]},"125":{"position":[[1426,4],[6495,5]]},"159":{"position":[[995,5],[1075,5]]},"160":{"position":[[2579,5]]},"178":{"position":[[110,6]]}},"keywords":{}}],["etern",{"_index":4624,"title":{},"content":{"158":{"position":[[222,9]]}},"keywords":{}}],["etf",{"_index":1824,"title":{},"content":{"40":{"position":[[2600,5],[3360,3],[3598,3]]},"93":{"position":[[2948,3]]}},"keywords":{}}],["etf'",{"_index":1835,"title":{},"content":{"40":{"position":[[3262,5]]}},"keywords":{}}],["etf/1449138789749.ajax",{"_index":3249,"title":{},"content":{"93":{"position":[[3087,24]]}},"keywords":{}}],["ethic",{"_index":2261,"title":{},"content":{"53":{"position":[[1264,6],[1980,6]]}},"keywords":{}}],["eurosfor",{"_index":5003,"title":{},"content":{"175":{"position":[[73,8]]}},"keywords":{}}],["evalu",{"_index":4712,"title":{},"content":{"160":{"position":[[3892,10]]}},"keywords":{}}],["evaluate_gnb(dim",{"_index":1994,"title":{},"content":{"45":{"position":[[2016,19],[2220,18],[3000,18]]}},"keywords":{}}],["evaluate_gnb_full(dim",{"_index":2024,"title":{},"content":{"45":{"position":[[2798,24]]}},"keywords":{}}],["evaluation_tim",{"_index":1746,"title":{},"content":{"39":{"position":[[2262,16],[2587,17]]}},"keywords":{}}],["even",{"_index":34,"title":{},"content":{"1":{"position":[[376,7]]},"3":{"position":[[31,4],[784,4]]},"14":{"position":[[169,4]]},"22":{"position":[[2821,4]]},"30":{"position":[[2623,4],[4301,4]]},"32":{"position":[[121,4],[1362,4],[2146,5]]},"33":{"position":[[1196,4]]},"34":{"position":[[257,4]]},"38":{"position":[[409,4]]},"40":{"position":[[1376,4],[3478,4]]},"46":{"position":[[393,4]]},"58":{"position":[[267,4]]},"61":{"position":[[1037,4]]},"65":{"position":[[2559,7]]},"66":{"position":[[498,4]]},"71":{"position":[[1045,4]]},"83":{"position":[[177,4],[378,4]]},"85":{"position":[[8,4]]},"89":{"position":[[110,4]]},"93":{"position":[[256,4]]},"97":{"position":[[297,4]]},"101":{"position":[[681,4]]},"106":{"position":[[414,4],[457,4],[734,4]]},"122":{"position":[[1037,4],[1296,4]]},"125":{"position":[[2249,4],[10188,4]]},"134":{"position":[[391,4]]},"145":{"position":[[268,4]]},"148":{"position":[[229,4]]},"174":{"position":[[1301,4]]},"179":{"position":[[436,4]]},"181":{"position":[[828,5]]},"184":{"position":[[226,4]]},"185":{"position":[[430,4]]},"188":{"position":[[1826,4],[3164,4]]},"193":{"position":[[2399,4]]},"195":{"position":[[1023,4]]},"196":{"position":[[1068,4],[1448,4],[1657,4]]},"197":{"position":[[1179,4]]}},"keywords":{}}],["evening/weekend/christma",{"_index":4488,"title":{},"content":{"150":{"position":[[69,25]]}},"keywords":{}}],["event",{"_index":2688,"title":{"87":{"position":[[0,5]]},"90":{"position":[[0,5]]},"91":{"position":[[0,5]]},"92":{"position":[[0,5]]}},"content":{"76":{"position":[[544,6]]},"90":{"position":[[63,5],[797,5],[2182,5],[3204,7],[3280,6],[3371,7],[3943,5],[3952,7],[4020,6],[4297,7],[4886,7],[5119,6],[5296,6]]},"91":{"position":[[19,5],[1752,6],[2441,6],[2478,7],[2615,7],[3436,5],[3500,6],[4028,6],[4091,7],[4241,7]]},"92":{"position":[[254,6],[291,7],[427,7]]},"93":{"position":[[1200,5],[3779,5],[4859,6],[4886,5],[5274,6],[5301,5]]}},"keywords":{}}],["event.th",{"_index":3067,"title":{},"content":{"90":{"position":[[5215,9]]}},"keywords":{}}],["event_d",{"_index":3041,"title":{},"content":{"90":{"position":[[4027,11],[4156,12]]}},"keywords":{}}],["event_data",{"_index":3035,"title":{},"content":{"90":{"position":[[3842,10]]},"91":{"position":[[3569,10],[3703,12]]}},"keywords":{}}],["event_str",{"_index":3281,"title":{},"content":{"93":{"position":[[4824,10],[4895,11],[5239,10],[5310,11]]}},"keywords":{}}],["eventu",{"_index":2065,"title":{},"content":{"50":{"position":[[130,10]]},"76":{"position":[[930,10]]},"111":{"position":[[112,10]]},"125":{"position":[[8815,10]]},"199":{"position":[[565,10]]}},"keywords":{}}],["everybodi",{"_index":3486,"title":{},"content":{"101":{"position":[[943,10]]}},"keywords":{}}],["everyon",{"_index":2264,"title":{},"content":{"53":{"position":[[1303,8],[2018,9]]}},"keywords":{}}],["everyth",{"_index":8,"title":{},"content":{"1":{"position":[[44,10]]},"43":{"position":[[1069,10]]},"52":{"position":[[527,10]]},"61":{"position":[[668,10]]},"75":{"position":[[1187,10]]},"76":{"position":[[1446,10]]},"91":{"position":[[3837,10]]},"105":{"position":[[432,10]]},"109":{"position":[[598,10]]},"112":{"position":[[16,10]]},"120":{"position":[[462,10]]},"124":{"position":[[188,10]]},"125":{"position":[[2191,10],[2674,10],[3950,10],[4157,10],[9436,10]]},"133":{"position":[[358,10]]},"156":{"position":[[223,10]]},"159":{"position":[[574,10]]},"196":{"position":[[287,10]]}},"keywords":{}}],["everything'",{"_index":5272,"title":{},"content":{"193":{"position":[[110,12]]}},"keywords":{}}],["everywher",{"_index":4036,"title":{},"content":{"125":{"position":[[1072,11]]},"180":{"position":[[589,11]]}},"keywords":{}}],["evid",{"_index":1413,"title":{},"content":{"30":{"position":[[5693,8]]},"89":{"position":[[139,8]]}},"keywords":{}}],["ex",{"_index":3211,"title":{},"content":{"93":{"position":[[1948,3]]}},"keywords":{}}],["exact",{"_index":2478,"title":{},"content":{"64":{"position":[[1198,5]]}},"keywords":{}}],["exactli",{"_index":1556,"title":{},"content":{"32":{"position":[[2106,7]]},"44":{"position":[[1274,7]]},"45":{"position":[[3333,7]]},"58":{"position":[[282,7]]},"65":{"position":[[173,7],[1562,7]]},"73":{"position":[[85,7],[224,7],[706,7]]},"91":{"position":[[177,7],[3760,7]]},"97":{"position":[[6186,7]]},"101":{"position":[[501,7]]},"112":{"position":[[228,7]]},"125":{"position":[[7987,7]]},"128":{"position":[[1889,7]]},"132":{"position":[[470,7]]},"139":{"position":[[163,7],[881,7]]},"143":{"position":[[9,7]]},"160":{"position":[[3132,7]]},"170":{"position":[[475,7]]},"196":{"position":[[1028,7]]},"199":{"position":[[742,7]]}},"keywords":{}}],["examin",{"_index":1193,"title":{"28":{"position":[[0,9]]}},"content":{"28":{"position":[[354,7]]}},"keywords":{}}],["exampl",{"_index":185,"title":{"8":{"position":[[0,7]]},"105":{"position":[[17,8]]},"140":{"position":[[0,7]]},"141":{"position":[[0,7]]},"142":{"position":[[0,7]]}},"content":{"3":{"position":[[1002,8]]},"4":{"position":[[345,8],[1318,7]]},"10":{"position":[[170,7]]},"14":{"position":[[277,8],[577,7]]},"15":{"position":[[279,8],[538,7]]},"34":{"position":[[3894,8]]},"40":{"position":[[3046,8]]},"49":{"position":[[248,8],[300,7]]},"50":{"position":[[264,7]]},"51":{"position":[[3284,8]]},"52":{"position":[[106,7]]},"72":{"position":[[24,8],[408,8]]},"82":{"position":[[1110,9]]},"83":{"position":[[428,7]]},"86":{"position":[[737,7]]},"88":{"position":[[20,8]]},"89":{"position":[[30,9],[66,8]]},"90":{"position":[[3469,7],[4860,8]]},"91":{"position":[[393,8]]},"96":{"position":[[244,7],[623,8]]},"97":{"position":[[1062,9],[1122,7],[2825,8],[2907,7]]},"104":{"position":[[323,8]]},"112":{"position":[[1004,7],[1469,8]]},"113":{"position":[[2540,8]]},"125":{"position":[[2929,7],[8859,9],[8888,7]]},"129":{"position":[[270,9],[2804,7]]},"135":{"position":[[313,8]]},"155":{"position":[[704,8]]},"163":{"position":[[803,8],[2145,7]]},"164":{"position":[[663,8]]},"172":{"position":[[1021,8],[2601,8]]},"173":{"position":[[709,9]]},"176":{"position":[[936,8]]},"179":{"position":[[327,7],[1203,7]]},"181":{"position":[[383,8]]},"183":{"position":[[230,7]]},"185":{"position":[[379,8],[565,7]]},"186":{"position":[[211,7]]},"193":{"position":[[896,8]]},"196":{"position":[[660,7],[1513,8]]},"199":{"position":[[991,8]]}},"keywords":{}}],["example,refcell::new",{"_index":5127,"title":{},"content":{"184":{"position":[[892,22]]}},"keywords":{}}],["example::factor",{"_index":5118,"title":{},"content":{"183":{"position":[[404,17],[550,17]]}},"keywords":{}}],["example::main",{"_index":4270,"title":{},"content":{"128":{"position":[[1266,14]]},"129":{"position":[[512,14]]}},"keywords":{}}],["example::my_funct",{"_index":4272,"title":{},"content":{"128":{"position":[[1471,20],[1504,21]]}},"keywords":{}}],["examplerun",{"_index":4181,"title":{},"content":{"125":{"position":[[9296,14]]}},"keywords":{}}],["exce",{"_index":5321,"title":{},"content":{"195":{"position":[[414,7]]}},"keywords":{}}],["except",{"_index":627,"title":{},"content":{"14":{"position":[[104,9]]},"22":{"position":[[1692,6]]},"30":{"position":[[9885,6],[9892,9]]},"40":{"position":[[3157,10]]},"91":{"position":[[3107,6],[3716,6]]},"92":{"position":[[919,6],[1326,9]]},"93":{"position":[[5004,6],[5419,6]]},"97":{"position":[[5295,11]]},"116":{"position":[[2387,10]]},"121":{"position":[[1229,10]]},"160":{"position":[[2381,7]]}},"keywords":{}}],["excess",{"_index":4397,"title":{},"content":{"136":{"position":[[648,10]]}},"keywords":{}}],["exchang",{"_index":3255,"title":{},"content":{"93":{"position":[[3278,8]]}},"keywords":{}}],["excit",{"_index":1335,"title":{},"content":{"30":{"position":[[461,7]]},"98":{"position":[[1140,7]]},"121":{"position":[[651,8]]},"122":{"position":[[14,8]]}},"keywords":{}}],["exclud",{"_index":4945,"title":{},"content":{"173":{"position":[[586,9]]}},"keywords":{}}],["exclus",{"_index":4944,"title":{},"content":{"173":{"position":[[435,11]]}},"keywords":{}}],["execut",{"_index":3291,"title":{},"content":{"93":{"position":[[5066,7]]},"135":{"position":[[191,9],[342,10]]},"172":{"position":[[2007,9]]},"174":{"position":[[41,9]]},"178":{"position":[[365,10]]},"179":{"position":[[1530,8]]},"183":{"position":[[894,10]]}},"keywords":{}}],["exercis",{"_index":2449,"title":{},"content":{"63":{"position":[[148,9]]}},"keywords":{}}],["exist",{"_index":195,"title":{},"content":{"3":{"position":[[1177,8]]},"30":{"position":[[2603,5]]},"91":{"position":[[3147,6],[3984,6]]},"92":{"position":[[959,6]]},"122":{"position":[[1081,7]]},"124":{"position":[[705,7]]},"129":{"position":[[858,6],[1081,6],[2429,6]]},"137":{"position":[[105,5]]},"150":{"position":[[299,8]]}},"keywords":{}}],["exit",{"_index":3793,"title":{},"content":{"115":{"position":[[2983,5]]},"152":{"position":[[1052,4]]}},"keywords":{}}],["exit_protect",{"_index":4468,"title":{},"content":{"146":{"position":[[361,17]]}},"keywords":{}}],["exp",{"_index":398,"title":{},"content":{"7":{"position":[[457,6]]},"13":{"position":[[1791,5]]},"14":{"position":[[2874,4]]},"15":{"position":[[2548,4]]}},"keywords":{}}],["exp((prod(forward_structure[i:end",{"_index":571,"title":{},"content":{"13":{"position":[[843,35]]}},"keywords":{}}],["exp(forward_structure[i",{"_index":649,"title":{},"content":{"14":{"position":[[1820,24],[1879,24]]},"15":{"position":[[1411,24],[1547,24]]}},"keywords":{}}],["exp(sqrt(t",{"_index":400,"title":{},"content":{"7":{"position":[[479,11]]}},"keywords":{}}],["expans",{"_index":1955,"title":{},"content":{"44":{"position":[[1927,9]]},"45":{"position":[[557,10]]}},"keywords":{}}],["expect",{"_index":675,"title":{},"content":{"15":{"position":[[639,6]]},"20":{"position":[[2752,8],[2967,9],[2994,9]]},"24":{"position":[[299,6]]},"26":{"position":[[41,8]]},"33":{"position":[[1133,9]]},"34":{"position":[[684,12],[734,12],[1625,9],[2089,8],[3112,6]]},"39":{"position":[[1036,9],[1302,8],[2185,9]]},"40":{"position":[[1179,9]]},"41":{"position":[[492,8]]},"51":{"position":[[1905,9]]},"58":{"position":[[567,11],[587,10],[621,8]]},"69":{"position":[[308,8],[368,8]]},"70":{"position":[[1324,10]]},"71":{"position":[[1059,8]]},"72":{"position":[[83,8],[144,8],[293,8],[346,8]]},"88":{"position":[[2315,8]]},"96":{"position":[[1787,8],[1867,7]]},"103":{"position":[[2170,9]]},"106":{"position":[[124,9]]},"120":{"position":[[1091,6]]},"125":{"position":[[2184,6],[9858,6]]},"142":{"position":[[263,6]]},"148":{"position":[[209,7],[480,6]]},"161":{"position":[[1455,8]]},"172":{"position":[[1927,7]]},"175":{"position":[[784,6]]},"179":{"position":[[1012,8]]},"188":{"position":[[1900,8]]},"189":{"position":[[2034,9]]},"195":{"position":[[1054,8]]}},"keywords":{}}],["expected_clos",{"_index":1634,"title":{},"content":{"34":{"position":[[2053,14],[2151,15],[2261,14]]},"39":{"position":[[1268,14],[1362,15],[1481,14]]}},"keywords":{}}],["expected_drawdown",{"_index":857,"title":{},"content":{"20":{"position":[[2580,17]]}},"keywords":{}}],["expected_profit",{"_index":1639,"title":{},"content":{"34":{"position":[[2243,15]]},"39":{"position":[[1463,15]]}},"keywords":{}}],["expected_return",{"_index":853,"title":{},"content":{"20":{"position":[[2473,15]]}},"keywords":{}}],["expediti",{"_index":4720,"title":{},"content":{"160":{"position":[[4293,14]]}},"keywords":{}}],["expensivesystem",{"_index":4958,"title":{},"content":{"173":{"position":[[1081,15]]}},"keywords":{}}],["experi",{"_index":201,"title":{},"content":{"3":{"position":[[1244,11]]},"29":{"position":[[320,11]]},"35":{"position":[[396,10]]},"97":{"position":[[372,10],[990,10]]},"100":{"position":[[219,10]]},"106":{"position":[[971,11]]},"121":{"position":[[297,11]]},"150":{"position":[[522,11]]},"189":{"position":[[917,11]]}},"keywords":{}}],["experienc",{"_index":2031,"title":{},"content":{"46":{"position":[[365,11]]}},"keywords":{}}],["expires_in",{"_index":2379,"title":{},"content":{"61":{"position":[[1683,13]]}},"keywords":{}}],["explain",{"_index":2628,"title":{},"content":{"73":{"position":[[831,8]]},"74":{"position":[[937,8]]},"76":{"position":[[105,7]]},"97":{"position":[[5219,7]]},"104":{"position":[[496,7],[678,10]]},"129":{"position":[[1340,9]]}},"keywords":{}}],["explan",{"_index":3063,"title":{},"content":{"90":{"position":[[4723,11]]}},"keywords":{}}],["explicitli",{"_index":2302,"title":{},"content":{"55":{"position":[[171,10]]},"188":{"position":[[1186,10],[1343,10]]}},"keywords":{}}],["explod",{"_index":4442,"title":{},"content":{"143":{"position":[[245,8]]}},"keywords":{}}],["explor",{"_index":206,"title":{"43":{"position":[[5,12]]}},"content":{"3":{"position":[[1328,9]]},"28":{"position":[[27,7]]},"128":{"position":[[316,8],[1233,9]]},"129":{"position":[[392,8],[1374,8]]},"152":{"position":[[1671,8]]},"153":{"position":[[1042,8]]},"155":{"position":[[1619,8]]},"156":{"position":[[710,8]]},"180":{"position":[[537,8]]},"181":{"position":[[365,8]]},"183":{"position":[[632,8]]},"192":{"position":[[575,8]]},"193":{"position":[[1977,8],[2932,8],[3784,8]]},"194":{"position":[[445,8]]},"196":{"position":[[1204,9],[1615,9],[1817,9]]},"197":{"position":[[1430,8]]},"198":{"position":[[1178,8]]},"199":{"position":[[1718,8]]}},"keywords":{}}],["exploratori",{"_index":1860,"title":{},"content":{"43":{"position":[[48,11]]}},"keywords":{}}],["expor",{"_index":4709,"title":{},"content":{"160":{"position":[[3824,8]]}},"keywords":{}}],["export",{"_index":3197,"title":{},"content":{"93":{"position":[[1193,6]]},"125":{"position":[[6624,8]]}},"keywords":{}}],["expos",{"_index":4189,"title":{},"content":{"125":{"position":[[9667,7]]},"176":{"position":[[562,6]]}},"keywords":{}}],["express",{"_index":3928,"title":{},"content":{"121":{"position":[[2699,11]]},"196":{"position":[[107,11]]}},"keywords":{}}],["extend",{"_index":284,"title":{},"content":{"4":{"position":[[1177,6]]},"110":{"position":[[76,6]]}},"keywords":{}}],["extens",{"_index":3927,"title":{},"content":{"121":{"position":[[2667,11]]}},"keywords":{}}],["extern",{"_index":3700,"title":{},"content":{"111":{"position":[[303,6]]},"113":{"position":[[334,6]]},"190":{"position":[[615,8]]}},"keywords":{}}],["extra",{"_index":1704,"title":{},"content":{"38":{"position":[[1104,5]]},"88":{"position":[[2182,5]]},"111":{"position":[[734,5]]},"113":{"position":[[222,5]]},"120":{"position":[[202,6]]},"124":{"position":[[439,5]]},"140":{"position":[[201,5]]},"160":{"position":[[2165,5]]},"192":{"position":[[606,5]]},"193":{"position":[[3484,5]]}},"keywords":{}}],["extrapol",{"_index":2335,"title":{"63":{"position":[[5,14]]}},"content":{"58":{"position":[[521,13],[758,13]]},"62":{"position":[[178,13]]},"66":{"position":[[221,13]]}},"keywords":{}}],["extrem",{"_index":5041,"title":{},"content":{"176":{"position":[[84,7]]}},"keywords":{}}],["eyebrow",{"_index":1514,"title":{},"content":{"32":{"position":[[94,8]]}},"keywords":{}}],["f",{"_index":1269,"title":{},"content":{"28":{"position":[[2075,1],[3730,1]]},"30":{"position":[[2052,1],[3546,1],[3745,1],[5302,1],[6620,1],[6825,1]]},"88":{"position":[[1071,2],[2679,2]]},"90":{"position":[[1310,2]]},"91":{"position":[[408,2]]}},"keywords":{}}],["f.line(year",{"_index":1275,"title":{},"content":{"28":{"position":[[2222,13],[3895,13]]},"30":{"position":[[2175,13],[3661,13],[3880,13],[5434,13],[6734,13],[6959,13]]}},"keywords":{}}],["f.set_size_inches(18",{"_index":2937,"title":{},"content":{"88":{"position":[[3529,21]]},"91":{"position":[[438,21]]}},"keywords":{}}],["f64",{"_index":3941,"title":{},"content":{"122":{"position":[[409,4]]}},"keywords":{}}],["f_{i",{"_index":467,"title":{},"content":{"9":{"position":[[447,4]]}},"keywords":{}}],["face",{"_index":2698,"title":{},"content":{"76":{"position":[[1080,4]]}},"keywords":{}}],["facebook",{"_index":2888,"title":{},"content":{"88":{"position":[[1734,9],[2329,8],[3694,9]]}},"keywords":{}}],["fact",{"_index":1286,"title":{},"content":{"28":{"position":[[2605,4]]},"30":{"position":[[4340,4]]},"96":{"position":[[829,5]]}},"keywords":{}}],["facto",{"_index":3955,"title":{},"content":{"122":{"position":[[1160,5]]}},"keywords":{}}],["factor",{"_index":2228,"title":{},"content":{"53":{"position":[[777,6]]},"181":{"position":[[78,7],[205,6],[333,6],[342,6],[396,6]]},"183":{"position":[[303,7],[429,6],[454,6],[575,6],[600,6],[609,6],[742,6]]}},"keywords":{}}],["fail",{"_index":2673,"title":{},"content":{"75":{"position":[[1060,4],[1137,4]]},"76":{"position":[[2250,6]]},"82":{"position":[[1314,5]]},"188":{"position":[[456,4]]}},"keywords":{}}],["fair",{"_index":2558,"title":{},"content":{"68":{"position":[[244,4],[343,4],[875,4]]},"69":{"position":[[49,4],[397,4]]},"71":{"position":[[1116,4]]},"72":{"position":[[116,4],[178,4],[375,4],[588,4]]},"76":{"position":[[1993,4]]},"77":{"position":[[156,4]]},"81":{"position":[[27,4]]},"86":{"position":[[11,4]]}},"keywords":{}}],["fair_1",{"_index":2560,"title":{},"content":{"68":{"position":[[492,6]]}},"keywords":{}}],["fair_2",{"_index":2563,"title":{},"content":{"68":{"position":[[532,6]]}},"keywords":{}}],["fair_2).plot(kind='hist",{"_index":2565,"title":{},"content":{"68":{"position":[[591,25]]}},"keywords":{}}],["fairli",{"_index":1122,"title":{},"content":{"24":{"position":[[3037,6]]},"40":{"position":[[3122,6]]},"41":{"position":[[551,6]]},"93":{"position":[[1090,6]]},"150":{"position":[[22,6]]},"160":{"position":[[1219,6]]}},"keywords":{}}],["fall",{"_index":2823,"title":{},"content":{"85":{"position":[[518,4]]},"156":{"position":[[335,4]]}},"keywords":{}}],["fals",{"_index":928,"title":{},"content":{"22":{"position":[[1212,5],[1232,5],[2318,5]]},"91":{"position":[[3309,5]]},"92":{"position":[[1121,5]]},"93":{"position":[[1505,5],[2251,5]]},"121":{"position":[[1058,5],[1082,6]]},"136":{"position":[[421,6],[428,6],[441,6]]}},"keywords":{}}],["famili",{"_index":1201,"title":{},"content":{"28":{"position":[[179,6]]},"172":{"position":[[1451,6]]}},"keywords":{}}],["familiar",{"_index":3400,"title":{},"content":{"97":{"position":[[3341,9]]},"110":{"position":[[133,8]]},"128":{"position":[[1297,9]]},"155":{"position":[[559,9]]},"163":{"position":[[581,9]]}},"keywords":{}}],["fan",{"_index":1024,"title":{},"content":{"24":{"position":[[474,3]]},"25":{"position":[[199,3]]},"40":{"position":[[2337,4]]}},"keywords":{}}],["fanci",{"_index":2818,"title":{},"content":{"85":{"position":[[37,5]]},"192":{"position":[[612,5]]}},"keywords":{}}],["fang",{"_index":1783,"title":{},"content":{"40":{"position":[[36,4],[1396,4],[1614,4]]}},"keywords":{}}],["fang_df",{"_index":1785,"title":{},"content":{"40":{"position":[[108,7]]}},"keywords":{}}],["fang_df.xs('day",{"_index":1790,"title":{},"content":{"40":{"position":[[233,18]]}},"keywords":{}}],["fang_df.xs('scor",{"_index":1796,"title":{},"content":{"40":{"position":[[401,19]]}},"keywords":{}}],["fantast",{"_index":2942,"title":{},"content":{"88":{"position":[[3771,9]]}},"keywords":{}}],["far",{"_index":526,"title":{"64":{"position":[[23,5]]}},"content":{"12":{"position":[[171,3]]},"29":{"position":[[361,3]]},"39":{"position":[[97,4]]},"40":{"position":[[3380,3],[3494,3]]},"41":{"position":[[4,3],[574,4]]},"46":{"position":[[485,4]]},"54":{"position":[[301,4]]},"57":{"position":[[496,3],[521,3]]},"58":{"position":[[328,4],[504,3],[710,3]]},"64":{"position":[[84,4],[1767,4],[1896,4]]},"65":{"position":[[68,4]]},"71":{"position":[[1488,3]]},"82":{"position":[[10,3]]},"86":{"position":[[534,3],[1164,3]]},"97":{"position":[[3388,4]]},"101":{"position":[[606,3]]},"104":{"position":[[1299,3]]},"105":{"position":[[33,4]]},"111":{"position":[[592,4]]},"112":{"position":[[40,4]]},"125":{"position":[[4774,3]]},"160":{"position":[[603,3]]},"166":{"position":[[255,3]]},"170":{"position":[[315,3]]},"173":{"position":[[1399,3]]},"176":{"position":[[1063,3]]},"198":{"position":[[104,3]]}},"keywords":{}}],["far.most",{"_index":2334,"title":{},"content":{"58":{"position":[[467,8]]}},"keywords":{}}],["fast",{"_index":2506,"title":{},"content":{"65":{"position":[[741,4]]},"98":{"position":[[634,4]]},"125":{"position":[[11462,4]]},"160":{"position":[[1265,4],[1449,5]]},"164":{"position":[[1490,4]]}},"keywords":{}}],["faster",{"_index":243,"title":{},"content":{"4":{"position":[[536,7]]},"86":{"position":[[1069,6]]},"160":{"position":[[3093,6]]},"172":{"position":[[1268,6]]}},"keywords":{}}],["fastest",{"_index":4629,"title":{},"content":{"159":{"position":[[325,7]]},"170":{"position":[[208,7]]}},"keywords":{}}],["fatal",{"_index":5205,"title":{},"content":{"188":{"position":[[3646,5]]}},"keywords":{}}],["favor.clos",{"_index":1570,"title":{},"content":{"33":{"position":[[315,11]]}},"keywords":{}}],["favoriterust",{"_index":4837,"title":{},"content":{"166":{"position":[[54,12]]}},"keywords":{}}],["fb",{"_index":2889,"title":{},"content":{"88":{"position":[[1745,2],[3161,2],[3274,3],[3340,3]]},"91":{"position":[[1426,2]]}},"keywords":{}}],["fb[datetime(2016",{"_index":3079,"title":{},"content":{"91":{"position":[[549,17]]}},"keywords":{}}],["fb_plot",{"_index":3076,"title":{},"content":{"91":{"position":[[463,7],[525,8]]}},"keywords":{}}],["fb_plot.legend(loc=2",{"_index":3086,"title":{},"content":{"91":{"position":[[849,21]]}},"keywords":{}}],["fb_plot.plot(fb_truncated.index",{"_index":3083,"title":{},"content":{"91":{"position":[[657,32]]}},"keywords":{}}],["fb_plot.set_title('fb",{"_index":3087,"title":{},"content":{"91":{"position":[[871,21]]}},"keywords":{}}],["fb_plot.vlines(date2num(datetime(2016",{"_index":3085,"title":{},"content":{"91":{"position":[[718,38]]}},"keywords":{}}],["fb_truncat",{"_index":3078,"title":{},"content":{"91":{"position":[[534,12]]}},"keywords":{}}],["fb_truncated['close']/2",{"_index":3082,"title":{},"content":{"91":{"position":[[633,23]]}},"keywords":{}}],["fb_truncated['open']/2",{"_index":3081,"title":{},"content":{"91":{"position":[[608,22]]}},"keywords":{}}],["fear",{"_index":5310,"title":{},"content":{"194":{"position":[[154,4]]}},"keywords":{}}],["featur",{"_index":1887,"title":{},"content":{"43":{"position":[[1142,9]]},"44":{"position":[[335,8],[964,9]]},"45":{"position":[[230,8],[384,8]]},"97":{"position":[[23,7]]},"102":{"position":[[512,9],[565,8]]},"127":{"position":[[347,9]]},"130":{"position":[[268,8],[438,7]]},"160":{"position":[[855,8]]},"166":{"position":[[431,9]]},"188":{"position":[[333,9]]}},"keywords":{}}],["feature(alloc",{"_index":4680,"title":{},"content":{"160":{"position":[[1643,18]]}},"keywords":{}}],["features"",{"_index":3494,"title":{},"content":{"102":{"position":[[595,14]]}},"keywords":{}}],["februari",{"_index":2537,"title":{},"content":{"65":{"position":[[2521,8]]}},"keywords":{}}],["feedback",{"_index":3971,"title":{},"content":{"123":{"position":[[179,8],[305,8],[565,8]]}},"keywords":{}}],["feel",{"_index":2250,"title":{"150":{"position":[[11,4]]}},"content":{"53":{"position":[[1153,4],[2096,4],[2137,4]]},"55":{"position":[[83,5]]},"120":{"position":[[509,5]]},"125":{"position":[[1232,4],[2800,4]]},"164":{"position":[[1549,4]]}},"keywords":{}}],["fellow",{"_index":3410,"title":{},"content":{"97":{"position":[[4203,7]]}},"keywords":{}}],["fenc",{"_index":3741,"title":{},"content":{"113":{"position":[[1067,5]]}},"keywords":{}}],["fetch",{"_index":988,"title":{"23":{"position":[[0,8]]}},"content":{"59":{"position":[[220,5]]},"62":{"position":[[231,5]]},"95":{"position":[[68,5]]},"125":{"position":[[3879,7]]}},"keywords":{}}],["fetch_event_data('celg",{"_index":3045,"title":{},"content":{"90":{"position":[[4131,24]]}},"keywords":{}}],["fetch_event_data(tick",{"_index":3019,"title":{},"content":{"90":{"position":[[3179,24]]}},"keywords":{}}],["fetch_ticker('aapl",{"_index":2876,"title":{},"content":{"88":{"position":[[1419,20]]}},"keywords":{}}],["fetch_ticker('fb",{"_index":2890,"title":{},"content":{"88":{"position":[[1750,18]]}},"keywords":{}}],["fetch_ticker(fix",{"_index":3287,"title":{},"content":{"93":{"position":[[4952,19],[5367,19]]}},"keywords":{}}],["fetch_ticker(tick",{"_index":2851,"title":{},"content":{"88":{"position":[[567,20]]},"90":{"position":[[3799,20]]},"93":{"position":[[3982,20]]}},"keywords":{}}],["few",{"_index":1338,"title":{},"content":{"30":{"position":[[552,3],[5716,3]]},"51":{"position":[[2826,3]]},"58":{"position":[[58,3]]},"65":{"position":[[226,3]]},"68":{"position":[[770,3]]},"91":{"position":[[3863,3]]},"150":{"position":[[152,3]]},"173":{"position":[[487,3]]}},"keywords":{}}],["fewer",{"_index":2370,"title":{},"content":{"61":{"position":[[1400,5]]}},"keywords":{}}],["ffmpeg",{"_index":3504,"title":{},"content":{"103":{"position":[[238,7]]}},"keywords":{}}],["fibonacci",{"_index":5166,"title":{},"content":{"188":{"position":[[1227,11],[1414,11],[1527,9]]}},"keywords":{}}],["fibonacci(n",{"_index":5167,"title":{},"content":{"188":{"position":[[1259,12],[1442,12]]}},"keywords":{}}],["fibonacci(unsign",{"_index":5163,"title":{},"content":{"188":{"position":[[989,18]]}},"keywords":{}}],["field",{"_index":3335,"title":{},"content":{"96":{"position":[[1002,5]]},"127":{"position":[[954,6]]}},"keywords":{}}],["fifth",{"_index":2175,"title":{},"content":{"52":{"position":[[316,5],[437,6]]}},"keywords":{}}],["fight",{"_index":2235,"title":{"97":{"position":[[9,8]]}},"content":{"53":{"position":[[906,6]]},"97":{"position":[[409,9],[2520,5]]},"115":{"position":[[3124,8]]}},"keywords":{}}],["figur",{"_index":215,"title":{},"content":{"3":{"position":[[1514,6]]},"30":{"position":[[0,8],[121,7]]},"32":{"position":[[1380,6]]},"64":{"position":[[19,8]]},"65":{"position":[[1351,8],[1533,6],[2225,6]]},"73":{"position":[[213,6]]},"77":{"position":[[192,6]]},"91":{"position":[[2460,6]]},"92":{"position":[[273,6]]},"97":{"position":[[2116,6],[5194,6],[6175,6],[6476,6]]},"100":{"position":[[263,7]]},"122":{"position":[[970,6]]},"125":{"position":[[9993,6]]},"153":{"position":[[40,8]]},"161":{"position":[[443,7]]},"164":{"position":[[1105,6]]},"174":{"position":[[509,7],[743,6]]},"189":{"position":[[1685,6]]},"193":{"position":[[757,6]]},"196":{"position":[[637,6]]}},"keywords":{}}],["figure(title="",{"_index":1270,"title":{},"content":{"28":{"position":[[2079,21],[3734,21]]}},"keywords":{}}],["figure(title='monthli",{"_index":1362,"title":{},"content":{"30":{"position":[[2056,21],[3550,21],[3749,21],[5306,21],[6624,21],[6829,21]]}},"keywords":{}}],["file",{"_index":127,"title":{},"content":{"2":{"position":[[795,4]]},"30":{"position":[[907,5],[8108,4],[8150,4]]},"60":{"position":[[129,5],[191,4]]},"91":{"position":[[1781,4]]},"101":{"position":[[7,5],[31,6],[487,5],[671,4],[732,4],[873,4],[1025,5]]},"102":{"position":[[1402,5]]},"103":{"position":[[215,4]]},"105":{"position":[[2646,5]]},"108":{"position":[[57,5]]},"110":{"position":[[257,5]]},"111":{"position":[[175,4],[250,5],[625,5],[667,6],[740,5],[771,4]]},"112":{"position":[[603,4],[954,4]]},"113":{"position":[[633,4]]},"123":{"position":[[1042,5]]},"125":{"position":[[4013,4],[4675,7],[4832,4],[6614,4],[7147,4],[7543,5],[7790,4],[7878,5]]},"129":{"position":[[2466,4]]},"134":{"position":[[231,4]]},"163":{"position":[[829,6]]},"173":{"position":[[996,5]]},"188":{"position":[[3749,4],[3879,4],[3958,4]]}},"keywords":{}}],["file("schema/point.capnp"",{"_index":3704,"title":{},"content":{"111":{"position":[[406,37]]}},"keywords":{}}],["filetype=csv&filename=iwv_holdings&datatype=fund",{"_index":3250,"title":{},"content":{"93":{"position":[[3112,59]]}},"keywords":{}}],["fill",{"_index":2182,"title":{},"content":{"52":{"position":[[630,4]]},"113":{"position":[[904,7],[1635,4]]},"161":{"position":[[1153,4]]}},"keywords":{}}],["fillstrategiescan",{"_index":5025,"title":{},"content":{"175":{"position":[[1036,17]]}},"keywords":{}}],["filter",{"_index":3110,"title":{},"content":{"91":{"position":[[2005,8]]},"93":{"position":[[4418,8]]},"105":{"position":[[176,7]]}},"keywords":{}}],["filter(lambda",{"_index":3111,"title":{},"content":{"91":{"position":[[2016,13]]},"93":{"position":[[2832,13],[4429,13]]}},"keywords":{}}],["final",{"_index":524,"title":{"12":{"position":[[0,5]]},"26":{"position":[[0,5]]},"176":{"position":[[0,5]]}},"content":{"40":{"position":[[1194,5],[2561,5]]},"44":{"position":[[192,5]]},"57":{"position":[[450,5]]},"65":{"position":[[1445,7],[2183,5]]},"72":{"position":[[615,7]]},"81":{"position":[[11,7]]},"83":{"position":[[422,5]]},"88":{"position":[[126,7]]},"91":{"position":[[5701,8]]},"95":{"position":[[206,8]]},"97":{"position":[[6295,5]]},"98":{"position":[[829,5]]},"113":{"position":[[1742,8]]},"121":{"position":[[2386,8]]},"125":{"position":[[9487,8]]},"128":{"position":[[89,5]]},"143":{"position":[[493,8]]},"153":{"position":[[1,8]]},"155":{"position":[[732,8]]},"160":{"position":[[4348,8]]},"165":{"position":[[924,5]]},"172":{"position":[[2333,8]]},"173":{"position":[[826,8]]},"176":{"position":[[737,5],[1395,8]]},"181":{"position":[[633,8]]},"186":{"position":[[1,8]]},"188":{"position":[[3358,8],[4255,8]]},"189":{"position":[[2857,8]]},"190":{"position":[[812,8]]},"193":{"position":[[1537,5],[1640,8],[2942,8]]},"194":{"position":[[73,7]]},"196":{"position":[[238,7]]},"197":{"position":[[793,5]]}},"keywords":{}}],["final_d1",{"_index":2755,"title":{},"content":{"78":{"position":[[269,9]]}},"keywords":{}}],["final_d2",{"_index":2756,"title":{},"content":{"78":{"position":[[279,8]]}},"keywords":{}}],["final_mean",{"_index":593,"title":{},"content":{"13":{"position":[[1658,10],[1778,10]]},"14":{"position":[[2741,10],[2861,10]]},"15":{"position":[[2415,10],[2535,10]]}},"keywords":{}}],["final_mot",{"_index":529,"title":{},"content":{"12":{"position":[[336,12],[459,12],[517,12]]}},"keywords":{}}],["financi",{"_index":4999,"title":{},"content":{"175":{"position":[[27,9]]}},"keywords":{}}],["find",{"_index":184,"title":{},"content":{"3":{"position":[[983,4]]},"4":{"position":[[507,7]]},"15":{"position":[[530,4]]},"30":{"position":[[7064,4]]},"44":{"position":[[58,4]]},"45":{"position":[[1839,4]]},"51":{"position":[[876,4],[908,4],[2009,4],[2218,4]]},"64":{"position":[[1233,4]]},"65":{"position":[[1281,4]]},"74":{"position":[[1490,4]]},"96":{"position":[[368,4]]},"97":{"position":[[2898,4]]},"102":{"position":[[237,4],[524,4],[753,4]]},"104":{"position":[[125,4],[628,4],[764,4]]},"112":{"position":[[572,4],[681,4],[731,4]]},"122":{"position":[[555,4]]},"129":{"position":[[994,4]]},"160":{"position":[[2271,4]]},"164":{"position":[[655,4]]},"174":{"position":[[1333,7]]}},"keywords":{}}],["fine",{"_index":3450,"title":{},"content":{"98":{"position":[[886,4]]},"112":{"position":[[212,5]]},"120":{"position":[[5,5]]},"129":{"position":[[1664,4]]},"193":{"position":[[123,5]]},"199":{"position":[[1465,4]]}},"keywords":{}}],["finish",{"_index":2246,"title":{},"content":{"53":{"position":[[1097,8]]},"76":{"position":[[3375,8]]},"82":{"position":[[1085,6]]},"116":{"position":[[2816,6]]},"125":{"position":[[10912,6]]},"134":{"position":[[208,9]]},"188":{"position":[[2211,6]]},"190":{"position":[[8,10]]},"193":{"position":[[587,9]]}},"keywords":{}}],["fire",{"_index":4373,"title":{},"content":{"134":{"position":[[120,4]]}},"keywords":{}}],["firefox/46.0",{"_index":3229,"title":{},"content":{"93":{"position":[[2423,13]]}},"keywords":{}}],["firm",{"_index":5000,"title":{},"content":{"175":{"position":[[37,5]]}},"keywords":{}}],["first",{"_index":18,"title":{},"content":{"1":{"position":[[181,5]]},"2":{"position":[[15,5],[233,5]]},"3":{"position":[[1306,5]]},"6":{"position":[[127,6]]},"9":{"position":[[712,5]]},"18":{"position":[[4,5]]},"23":{"position":[[266,5]]},"24":{"position":[[201,5]]},"30":{"position":[[965,5]]},"34":{"position":[[3062,5]]},"38":{"position":[[450,6]]},"40":{"position":[[590,6],[905,5],[2148,5]]},"43":{"position":[[1,5]]},"44":{"position":[[4,5],[459,5]]},"51":{"position":[[70,6],[350,6],[400,5],[869,6],[2863,5]]},"52":{"position":[[153,5],[461,5],[574,5],[751,5],[920,5],[936,5]]},"53":{"position":[[467,5],[1181,5],[1277,5],[1993,6]]},"57":{"position":[[349,5]]},"61":{"position":[[1428,6]]},"64":{"position":[[5,5],[206,6],[1227,5]]},"65":{"position":[[265,5],[1508,6]]},"68":{"position":[[4,5],[198,5]]},"74":{"position":[[341,5]]},"85":{"position":[[75,5]]},"88":{"position":[[220,5]]},"90":{"position":[[478,5]]},"91":{"position":[[5,5],[1808,5]]},"93":{"position":[[4539,5]]},"96":{"position":[[1054,5]]},"97":{"position":[[1261,5]]},"100":{"position":[[384,5]]},"103":{"position":[[184,5],[930,6],[1580,6]]},"104":{"position":[[936,6]]},"106":{"position":[[179,5]]},"110":{"position":[[183,6]]},"112":{"position":[[1227,6]]},"115":{"position":[[6,5],[2890,6]]},"121":{"position":[[1148,5]]},"123":{"position":[[719,6]]},"125":{"position":[[3318,5],[3664,6],[4109,5],[5065,5],[10577,5]]},"127":{"position":[[357,6]]},"128":{"position":[[4,5]]},"129":{"position":[[2590,5]]},"132":{"position":[[8,5],[292,5]]},"136":{"position":[[752,5]]},"152":{"position":[[5,5]]},"155":{"position":[[5,5]]},"161":{"position":[[573,6]]},"164":{"position":[[76,5]]},"165":{"position":[[506,6]]},"173":{"position":[[506,6]]},"176":{"position":[[768,6],[860,5],[1528,5]]},"179":{"position":[[5,5],[988,5],[1488,5]]},"188":{"position":[[1457,6],[2328,5],[2960,5],[3251,5],[3741,7],[4076,6]]},"189":{"position":[[269,5],[1678,6],[2327,6],[2620,5]]},"190":{"position":[[134,6]]},"192":{"position":[[25,6],[234,5]]},"198":{"position":[[69,6]]}},"keywords":{}}],["first_word",{"_index":2084,"title":{},"content":{"51":{"position":[[519,11]]}},"keywords":{}}],["first_word_dist",{"_index":2088,"title":{},"content":{"51":{"position":[[619,15]]}},"keywords":{}}],["first_word_dist.reset_index()['index",{"_index":2162,"title":{},"content":{"51":{"position":[[4031,39]]}},"keywords":{}}],["first_words[first_words.str.isalpha",{"_index":2087,"title":{},"content":{"51":{"position":[[580,38]]}},"keywords":{}}],["first_words_alpha",{"_index":2086,"title":{},"content":{"51":{"position":[[560,17]]}},"keywords":{}}],["first_words_alpha.value_count",{"_index":2089,"title":{},"content":{"51":{"position":[[637,32]]}},"keywords":{}}],["fit",{"_index":1982,"title":{},"content":{"45":{"position":[[1357,3]]},"82":{"position":[[1256,3]]}},"keywords":{}}],["fitbit",{"_index":2311,"title":{},"content":{"57":{"position":[[188,6]]},"59":{"position":[[1,6]]},"60":{"position":[[53,7]]},"61":{"position":[[320,7],[453,7],[534,7],[656,7],[734,7],[2208,6]]},"62":{"position":[[211,6]]}},"keywords":{}}],["fitbit_uri",{"_index":2373,"title":{},"content":{"61":{"position":[[1514,10],[1781,10]]}},"keywords":{}}],["five",{"_index":2170,"title":{},"content":{"52":{"position":[[119,4]]}},"keywords":{}}],["five_day_ev",{"_index":3142,"title":{},"content":{"91":{"position":[[3357,15],[3657,15],[4129,15]]}},"keywords":{}}],["five_day_events[1",{"_index":3153,"title":{},"content":{"91":{"position":[[4147,21]]}},"keywords":{}}],["fix",{"_index":2544,"title":{"191":{"position":[[21,5]]}},"content":{"66":{"position":[[387,5]]},"91":{"position":[[3826,5]]},"93":{"position":[[4791,5],[5206,5]]},"97":{"position":[[5618,3]]},"98":{"position":[[845,5]]},"140":{"position":[[114,5]]},"159":{"position":[[421,5],[497,5]]},"160":{"position":[[2847,5]]},"164":{"position":[[1358,7]]},"175":{"position":[[1635,5]]},"180":{"position":[[264,5]]}},"keywords":{}}],["fi−1,if_{i",{"_index":469,"title":{},"content":{"9":{"position":[[488,10]]}},"keywords":{}}],["flac",{"_index":3471,"title":{},"content":{"101":{"position":[[373,5]]},"103":{"position":[[210,4]]}},"keywords":{}}],["flag",{"_index":4722,"title":{},"content":{"160":{"position":[[4379,4]]},"194":{"position":[[525,5]]}},"keywords":{}}],["flamegraph",{"_index":4377,"title":{"135":{"position":[[8,12]]}},"content":{},"keywords":{}}],["flatbuff",{"_index":4819,"title":{"165":{"position":[[0,12]]}},"content":{"165":{"position":[[112,11],[246,11],[347,12],[513,11],[1065,11],[1203,11],[1410,12]]},"166":{"position":[[342,11]]},"168":{"position":[[288,11]]},"169":{"position":[[401,11]]}},"keywords":{}}],["flexibl",{"_index":4192,"title":{},"content":{"125":{"position":[[9798,12]]},"165":{"position":[[303,12]]}},"keywords":{}}],["fli",{"_index":4925,"title":{},"content":{"172":{"position":[[1792,3]]}},"keywords":{}}],["flip",{"_index":1131,"title":{},"content":{"24":{"position":[[3243,5]]},"26":{"position":[[107,4],[259,4]]}},"keywords":{}}],["float",{"_index":3584,"title":{},"content":{"105":{"position":[[684,8],[733,7]]},"127":{"position":[[235,5]]}},"keywords":{}}],["float(str",{"_index":948,"title":{},"content":{"22":{"position":[[1667,14]]}},"keywords":{}}],["floor",{"_index":2214,"title":{},"content":{"53":{"position":[[500,5]]}},"keywords":{}}],["flounder",{"_index":133,"title":{"3":{"position":[[0,11]]}},"content":{},"keywords":{}}],["flow",{"_index":5015,"title":{},"content":{"175":{"position":[[634,4]]}},"keywords":{}}],["flung",{"_index":4658,"title":{},"content":{"160":{"position":[[607,5]]}},"keywords":{}}],["fn",{"_index":3327,"title":{},"content":{"96":{"position":[[653,2],[1072,2],[1602,2],[2148,2]]},"97":{"position":[[1460,2],[3635,2]]},"111":{"position":[[324,2]]},"113":{"position":[[726,2]]},"115":{"position":[[109,2]]},"116":{"position":[[209,2]]},"117":{"position":[[1001,2]]},"128":{"position":[[1106,2],[1132,2]]},"129":{"position":[[418,2],[1464,2],[1530,2]]},"136":{"position":[[267,2]]},"140":{"position":[[1,2]]},"141":{"position":[[1,2]]},"142":{"position":[[1,2]]},"144":{"position":[[174,2],[280,2]]},"145":{"position":[[138,2]]},"146":{"position":[[166,2]]},"147":{"position":[[189,2],[314,2]]},"152":{"position":[[470,2],[1106,2],[1320,2],[1485,2]]},"153":{"position":[[747,2]]},"155":{"position":[[1343,2],[1406,2],[1467,2],[1530,2]]},"156":{"position":[[627,2],[916,2],[1403,2],[1568,2]]},"163":{"position":[[1741,2]]},"178":{"position":[[646,2]]},"179":{"position":[[387,2],[565,2],[907,2],[973,2],[1281,2]]},"180":{"position":[[422,2]]},"181":{"position":[[102,2],[218,2]]},"183":{"position":[[327,2],[467,2]]},"184":{"position":[[311,2],[448,2],[556,2],[651,2],[684,2],[820,2],[925,3]]},"186":{"position":[[334,2]]},"192":{"position":[[188,2]]},"193":{"position":[[1052,2],[1742,2],[2456,2],[2697,2],[3231,2],[3532,2]]},"194":{"position":[[303,2]]},"195":{"position":[[635,2]]},"196":{"position":[[937,2],[1145,2],[1527,2],[1738,2]]},"197":{"position":[[308,2],[437,2],[586,2],[932,2],[1151,2]]},"199":{"position":[[1235,2],[1372,2],[1528,2]]}},"keywords":{}}],["fn(&mut",{"_index":3373,"title":{},"content":{"97":{"position":[[1500,11]]}},"keywords":{}}],["fnonc",{"_index":5333,"title":{},"content":{"196":{"position":[[961,8]]}},"keywords":{}}],["focu",{"_index":230,"title":{},"content":{"4":{"position":[[184,5],[1439,5]]},"92":{"position":[[173,5]]},"135":{"position":[[51,5]]},"160":{"position":[[580,5],[3412,5]]},"161":{"position":[[488,5]]},"176":{"position":[[1503,5]]}},"keywords":{}}],["folder",{"_index":144,"title":{},"content":{"3":{"position":[[245,6]]},"111":{"position":[[224,6]]},"112":{"position":[[674,6]]}},"keywords":{}}],["follow",{"_index":316,"title":{},"content":{"6":{"position":[[264,9]]},"9":{"position":[[392,7]]},"13":{"position":[[111,9]]},"14":{"position":[[251,9],[1222,9]]},"30":{"position":[[8117,9]]},"32":{"position":[[451,9]]},"49":{"position":[[45,9],[346,8],[387,8],[530,6]]},"51":{"position":[[3160,7]]},"71":{"position":[[162,9]]},"74":{"position":[[463,7]]},"75":{"position":[[117,8]]},"90":{"position":[[5106,9],[5202,9],[5283,9]]},"91":{"position":[[248,9],[5920,6]]},"102":{"position":[[470,8],[968,8]]},"108":{"position":[[831,9]]},"109":{"position":[[204,9]]},"110":{"position":[[401,9]]},"111":{"position":[[271,9]]},"112":{"position":[[1030,9]]},"122":{"position":[[454,6]]},"123":{"position":[[97,9]]},"156":{"position":[[1790,6]]},"165":{"position":[[612,10]]}},"keywords":{}}],["font",{"_index":945,"title":{},"content":{"22":{"position":[[1618,6]]}},"keywords":{}}],["fontsize=18",{"_index":1795,"title":{},"content":{"40":{"position":[[383,13],[540,13],[1917,13],[2076,13],[2860,13],[3020,13]]}},"keywords":{}}],["food",{"_index":2240,"title":{},"content":{"53":{"position":[[980,4]]}},"keywords":{}}],["fool",{"_index":4338,"title":{},"content":{"130":{"position":[[525,4]]}},"keywords":{}}],["foot",{"_index":3889,"title":{},"content":{"121":{"position":[[950,4]]}},"keywords":{}}],["for<'r",{"_index":3380,"title":{},"content":{"97":{"position":[[1865,11]]}},"keywords":{}}],["forc",{"_index":3418,"title":{},"content":{"97":{"position":[[4676,5],[5944,6]]},"98":{"position":[[747,7],[1071,6]]},"104":{"position":[[851,6],[1400,5]]},"122":{"position":[[920,6]]},"152":{"position":[[929,7]]},"156":{"position":[[194,6]]},"189":{"position":[[1510,5]]}},"keywords":{}}],["fordtlb_load_misses.miss_causes_a_walk",{"_index":5047,"title":{},"content":{"176":{"position":[[692,39]]}},"keywords":{}}],["forecast",{"_index":1429,"title":{},"content":{"30":{"position":[[7426,8],[8099,8],[9967,8],[10358,8]]},"89":{"position":[[310,8]]}},"keywords":{}}],["forecast.io",{"_index":1345,"title":{},"content":{"30":{"position":[[794,12]]}},"keywords":{}}],["forecast_bas",{"_index":1468,"title":{},"content":{"30":{"position":[[8790,13],[8875,13],[8969,13]]}},"keywords":{}}],["forecast_df",{"_index":1352,"title":{},"content":{"30":{"position":[[1257,11]]}},"keywords":{}}],["forecast_df['cari",{"_index":1354,"title":{},"content":{"30":{"position":[[1326,19]]}},"keywords":{}}],["forecasts_df",{"_index":1229,"title":{},"content":{"28":{"position":[[925,12]]}},"keywords":{}}],["foreword",{"_index":4644,"title":{"160":{"position":[[21,8]]}},"content":{},"keywords":{}}],["forextern",{"_index":5222,"title":{},"content":{"188":{"position":[[4287,11]]}},"keywords":{}}],["forg",{"_index":4132,"title":{},"content":{"125":{"position":[[6281,6],[6864,5]]}},"keywords":{}}],["forgot",{"_index":4752,"title":{},"content":{"161":{"position":[[1229,6]]}},"keywords":{}}],["form",{"_index":3334,"title":{},"content":{"96":{"position":[[937,5]]},"197":{"position":[[34,6]]}},"keywords":{}}],["formal",{"_index":4723,"title":{},"content":{"160":{"position":[[4504,8]]}},"keywords":{}}],["format",{"_index":2736,"title":{"162":{"position":[[7,6]]}},"content":{"76":{"position":[[2558,11]]},"96":{"position":[[1981,8],[2127,10]]},"101":{"position":[[360,7],[564,7]]},"108":{"position":[[97,6]]},"110":{"position":[[597,7]]},"120":{"position":[[341,7]]},"121":{"position":[[1753,6]]},"125":{"position":[[7933,6]]},"163":{"position":[[135,7],[314,6],[2189,7],[2320,8]]},"164":{"position":[[82,6],[1169,6]]},"165":{"position":[[288,6],[595,7]]},"166":{"position":[[201,6],[279,7],[828,7]]},"167":{"position":[[286,6]]},"168":{"position":[[108,6]]},"169":{"position":[[182,7],[243,6]]},"170":{"position":[[341,7]]}},"keywords":{}}],["format!("y",{"_index":3353,"title":{},"content":{"96":{"position":[[2252,17]]}},"keywords":{}}],["format(horizon,five_day_events.shape[0",{"_index":3156,"title":{},"content":{"91":{"position":[[4249,42]]}},"keywords":{}}],["format(i",{"_index":906,"title":{},"content":{"22":{"position":[[726,15]]}},"keywords":{}}],["format(lat",{"_index":1470,"title":{},"content":{"30":{"position":[[8900,20],[8994,23]]}},"keywords":{}}],["format(tick",{"_index":3232,"title":{},"content":{"93":{"position":[[2538,15]]}},"keywords":{}}],["format_str",{"_index":2407,"title":{},"content":{"62":{"position":[[546,10]]}},"keywords":{}}],["formul",{"_index":2943,"title":{"89":{"position":[[0,11]]}},"content":{},"keywords":{}}],["formula",{"_index":1527,"title":{"37":{"position":[[35,7]]}},"content":{"32":{"position":[[712,7],[789,8],[983,7],[1066,7]]},"33":{"position":[[36,7]]},"34":{"position":[[196,7],[385,7]]},"38":{"position":[[5,7],[242,7]]}},"keywords":{}}],["formula,w",{"_index":1591,"title":{},"content":{"34":{"position":[[42,10]]}},"keywords":{}}],["forth",{"_index":4337,"title":{},"content":{"130":{"position":[[515,5]]}},"keywords":{}}],["forward",{"_index":277,"title":{},"content":{"4":{"position":[[1056,7]]},"9":{"position":[[199,7],[321,7],[529,7]]},"11":{"position":[[226,7]]},"12":{"position":[[260,7]]},"63":{"position":[[168,8]]},"65":{"position":[[746,7]]},"91":{"position":[[2926,7]]},"92":{"position":[[738,7]]},"106":{"position":[[1138,7]]},"124":{"position":[[830,7]]},"161":{"position":[[1653,7]]},"175":{"position":[[1530,10]]}},"keywords":{}}],["forward"",{"_index":5028,"title":{},"content":{"175":{"position":[[1142,13]]}},"keywords":{}}],["forward[i",{"_index":531,"title":{},"content":{"12":{"position":[[378,11]]}},"keywords":{}}],["forward_structur",{"_index":566,"title":{},"content":{"13":{"position":[[695,18],[1094,17],[1242,18]]},"14":{"position":[[1552,18],[2128,17],[2303,18]]},"15":{"position":[[923,18],[1796,17],[1973,18]]}},"keywords":{}}],["forward_term",{"_index":471,"title":{},"content":{"9":{"position":[[544,12]]}},"keywords":{}}],["forward_term(term",{"_index":501,"title":{},"content":{"10":{"position":[[419,18]]},"12":{"position":[[284,19]]},"13":{"position":[[1114,18]]},"14":{"position":[[2148,18]]},"15":{"position":[[1816,18]]}},"keywords":{}}],["forward_yield",{"_index":500,"title":{},"content":{"10":{"position":[[403,13]]},"11":{"position":[[389,14]]}},"keywords":{}}],["forward_yield[1",{"_index":503,"title":{},"content":{"10":{"position":[[467,16]]}},"keywords":{}}],["found",{"_index":1988,"title":{},"content":{"45":{"position":[[1789,5]]},"96":{"position":[[767,5],[1186,5],[1724,5],[2270,5]]},"122":{"position":[[602,5]]},"125":{"position":[[8524,6],[8992,6]]},"160":{"position":[[4048,5]]},"193":{"position":[[559,5]]}},"keywords":{}}],["foundat",{"_index":311,"title":{},"content":{"6":{"position":[[151,10]]},"128":{"position":[[26,10]]}},"keywords":{}}],["four",{"_index":2512,"title":{},"content":{"65":{"position":[[1101,4],[1211,4]]},"91":{"position":[[1455,4]]},"115":{"position":[[899,4]]}},"keywords":{}}],["four_year_period",{"_index":2507,"title":{},"content":{"65":{"position":[[811,17],[898,17]]}},"keywords":{}}],["fourth",{"_index":2173,"title":{},"content":{"52":{"position":[[275,6],[429,7]]}},"keywords":{}}],["frac{1}{o_i",{"_index":1554,"title":{},"content":{"32":{"position":[[1891,14]]}},"keywords":{}}],["frac{c_n",{"_index":1548,"title":{},"content":{"32":{"position":[[1752,10]]}},"keywords":{}}],["frac{c_nd_i}{o_i",{"_index":1547,"title":{},"content":{"32":{"position":[[1726,21]]}},"keywords":{}}],["frac{c_nd_n}{o_n",{"_index":1542,"title":{},"content":{"32":{"position":[[1611,18],[1668,18]]}},"keywords":{}}],["frac{c_n}{o_i",{"_index":1551,"title":{},"content":{"32":{"position":[[1811,18]]}},"keywords":{}}],["frac{d_i}{o_i",{"_index":1531,"title":{},"content":{"32":{"position":[[838,15],[1593,15]]}},"keywords":{}}],["frac{o_n}{c_n",{"_index":1552,"title":{},"content":{"32":{"position":[[1844,14]]}},"keywords":{}}],["fragment",{"_index":4147,"title":{},"content":{"125":{"position":[[7441,10]]}},"keywords":{}}],["frame",{"_index":510,"title":{},"content":{"11":{"position":[[151,6]]},"28":{"position":[[1116,5],[1142,6],[2906,5],[2939,6]]},"30":{"position":[[1488,5],[1514,6],[4751,5],[4784,6]]},"121":{"position":[[1314,7]]}},"keywords":{}}],["frame.iloc[i",{"_index":1033,"title":{},"content":{"24":{"position":[[631,12]]}},"keywords":{}}],["frame.iloc[i].nam",{"_index":1031,"title":{},"content":{"24":{"position":[[598,18]]},"25":{"position":[[323,18]]}},"keywords":{}}],["frame.iloc[i]['clos",{"_index":1139,"title":{},"content":{"25":{"position":[[387,22]]}},"keywords":{}}],["frame.iloc[i]['open",{"_index":1036,"title":{},"content":{"24":{"position":[[667,21]]},"25":{"position":[[353,21]]}},"keywords":{}}],["frame['cloudcov",{"_index":1238,"title":{},"content":{"28":{"position":[[1156,19]]},"30":{"position":[[1528,19]]}},"keywords":{}}],["frame['precipprob",{"_index":1297,"title":{},"content":{"28":{"position":[[2953,26]]},"30":{"position":[[4798,26]]}},"keywords":{}}],["frames,130",{"_index":3903,"title":{},"content":{"121":{"position":[[1547,10]]}},"keywords":{}}],["framework",{"_index":186,"title":{},"content":{"3":{"position":[[1024,10],[1075,11],[1438,9]]},"4":{"position":[[892,10],[1136,11],[1210,9]]},"125":{"position":[[9743,9]]}},"keywords":{}}],["frameworks"",{"_index":4158,"title":{},"content":{"125":{"position":[[8248,17]]}},"keywords":{}}],["frank",{"_index":5105,"title":{},"content":{"181":{"position":[[963,6]]}},"keywords":{}}],["freak",{"_index":1844,"title":{},"content":{"40":{"position":[[3662,6]]},"53":{"position":[[826,8]]},"121":{"position":[[1406,7]]}},"keywords":{}}],["free",{"_index":3502,"title":{},"content":{"103":{"position":[[70,5]]},"121":{"position":[[2012,5]]},"125":{"position":[[2805,4]]},"133":{"position":[[396,5]]},"160":{"position":[[567,5]]},"173":{"position":[[354,4]]},"188":{"position":[[2380,4]]},"190":{"position":[[163,4],[231,4]]}},"keywords":{}}],["free"",{"_index":3453,"title":{},"content":{"98":{"position":[[998,10]]}},"keywords":{}}],["free/xxvii/01",{"_index":3509,"title":{},"content":{"103":{"position":[[294,13]]}},"keywords":{}}],["freez",{"_index":4907,"title":{},"content":{"172":{"position":[[514,6]]}},"keywords":{}}],["freq='d",{"_index":1242,"title":{},"content":{"28":{"position":[[1342,9],[3142,9]]},"30":{"position":[[1708,9],[3057,9],[4981,9],[6125,9]]}},"keywords":{}}],["freq='min",{"_index":2432,"title":{},"content":{"62":{"position":[[1399,11]]}},"keywords":{}}],["frequenc",{"_index":1891,"title":{},"content":{"43":{"position":[[1369,9]]},"104":{"position":[[513,9],[1260,9],[1338,9],[1516,9],[1553,9],[1767,9],[1825,9]]}},"keywords":{}}],["frequency"",{"_index":3555,"title":{},"content":{"104":{"position":[[359,15],[1185,15]]}},"keywords":{}}],["frequent",{"_index":2568,"title":{},"content":{"68":{"position":[[736,8]]},"174":{"position":[[1155,10]]}},"keywords":{}}],["friday",{"_index":3025,"title":{},"content":{"90":{"position":[[3495,6]]}},"keywords":{}}],["friend",{"_index":2180,"title":{},"content":{"52":{"position":[[482,7]]},"130":{"position":[[535,7]]},"173":{"position":[[1324,6]]}},"keywords":{}}],["frivol",{"_index":4659,"title":{},"content":{"160":{"position":[[618,9]]}},"keywords":{}}],["from=start",{"_index":1626,"title":{},"content":{"34":{"position":[[1671,11]]}},"keywords":{}}],["fromiex",{"_index":4762,"title":{},"content":{"163":{"position":[[87,8]]}},"keywords":{}}],["front",{"_index":4834,"title":{},"content":{"165":{"position":[[1240,5]]}},"keywords":{}}],["frustrat",{"_index":3391,"title":{},"content":{"97":{"position":[[2210,10]]},"115":{"position":[[2713,12]]}},"keywords":{}}],["fs",{"_index":3261,"title":{},"content":{"93":{"position":[[3397,2]]}},"keywords":{}}],["fs[futur",{"_index":3269,"title":{},"content":{"93":{"position":[[3628,10]]}},"keywords":{}}],["full",{"_index":507,"title":{"11":{"position":[[4,4]]}},"content":{"11":{"position":[[134,4]]},"12":{"position":[[43,4]]},"20":{"position":[[855,4]]},"61":{"position":[[1905,4],[2192,4]]},"104":{"position":[[307,4]]}},"keywords":{}}],["full_daterang",{"_index":2429,"title":{},"content":{"62":{"position":[[1321,14]]}},"keywords":{}}],["full_mot",{"_index":515,"title":{},"content":{"11":{"position":[[336,11],[500,11]]}},"keywords":{}}],["full_simul",{"_index":527,"title":{},"content":{"12":{"position":[[214,15]]}},"keywords":{}}],["full_simulation(s0",{"_index":535,"title":{},"content":{"12":{"position":[[540,19]]},"13":{"position":[[1321,19]]},"14":{"position":[[2393,19]]},"15":{"position":[[2065,19]]}},"keywords":{}}],["full_term",{"_index":516,"title":{},"content":{"11":{"position":[[363,9]]}},"keywords":{}}],["full_term[i",{"_index":519,"title":{},"content":{"11":{"position":[[418,13]]}},"keywords":{}}],["fulli",{"_index":2969,"title":{},"content":{"90":{"position":[[499,5]]},"98":{"position":[[761,5]]},"104":{"position":[[37,5]]}},"keywords":{}}],["fun",{"_index":294,"title":{},"content":{"4":{"position":[[1428,4]]},"20":{"position":[[2046,6],[2087,6],[2136,6],[2177,6]]},"50":{"position":[[94,3]]},"51":{"position":[[1512,3]]},"86":{"position":[[954,4]]},"100":{"position":[[330,3]]},"125":{"position":[[420,3]]},"163":{"position":[[2453,4]]}},"keywords":{}}],["function",{"_index":53,"title":{"74":{"position":[[24,9]]},"146":{"position":[[6,8]]},"193":{"position":[[0,8]]}},"content":{"1":{"position":[[603,8]]},"7":{"position":[[530,8]]},"8":{"position":[[60,9]]},"13":{"position":[[1270,10]]},"14":{"position":[[2342,10]]},"15":{"position":[[2014,10]]},"38":{"position":[[707,8],[1243,8]]},"73":{"position":[[760,8],[911,9]]},"74":{"position":[[26,9],[1239,8]]},"75":{"position":[[47,8],[636,8]]},"76":{"position":[[32,9]]},"85":{"position":[[437,8]]},"86":{"position":[[825,8]]},"97":{"position":[[1142,9],[1283,8],[1312,10],[1372,8],[1435,8],[1655,8],[1695,8],[2373,8],[2665,8],[3101,10],[3292,8],[4300,8],[4349,9],[4385,8],[4566,9],[4629,8],[6027,8],[6354,10]]},"98":{"position":[[55,13]]},"103":{"position":[[1524,9]]},"105":{"position":[[371,8]]},"113":{"position":[[2441,11]]},"120":{"position":[[830,8]]},"121":{"position":[[1213,14],[2343,9]]},"125":{"position":[[4215,8]]},"127":{"position":[[1495,8]]},"128":{"position":[[1657,12],[1826,10],[1932,8]]},"129":{"position":[[844,8],[1019,8],[1067,8],[1131,8],[1261,9],[1298,8],[1693,8],[1812,9],[1875,8]]},"135":{"position":[[206,9],[289,9],[378,9]]},"141":{"position":[[372,9]]},"144":{"position":[[37,8]]},"147":{"position":[[111,10],[414,8]]},"150":{"position":[[358,11]]},"153":{"position":[[287,8]]},"157":{"position":[[229,14]]},"160":{"position":[[589,13]]},"173":{"position":[[303,14]]},"181":{"position":[[493,10]]},"188":{"position":[[394,8],[773,8],[851,8],[1426,8],[2792,8],[4089,9],[4418,9],[4531,10]]},"189":{"position":[[260,8],[331,8],[500,9],[671,8],[1493,8],[1718,8],[2985,9]]},"190":{"position":[[236,9]]},"193":{"position":[[28,9],[188,9],[420,8],[574,8],[786,10],[1725,10],[2007,8],[2074,9],[2280,8]]},"195":{"position":[[718,8]]},"196":{"position":[[25,9],[379,10],[457,10],[488,9],[807,9],[1054,9],[1362,9],[1473,12]]},"197":{"position":[[763,8],[1102,8]]},"199":{"position":[[441,9],[686,8],[720,8]]}},"keywords":{}}],["function(current_open",{"_index":1604,"title":{},"content":{"34":{"position":[[1066,22]]}},"keywords":{}}],["function(current_pric",{"_index":1620,"title":{},"content":{"34":{"position":[[1424,23]]}},"keywords":{}}],["function(initial_pric",{"_index":564,"title":{},"content":{"13":{"position":[[616,23]]},"14":{"position":[[1457,23]]},"15":{"position":[[828,23]]}},"keywords":{}}],["function(invest",{"_index":1644,"title":{},"content":{"34":{"position":[[2712,21]]}},"keywords":{}}],["function(nam",{"_index":1622,"title":{},"content":{"34":{"position":[[1597,14]]}},"keywords":{}}],["function(s0",{"_index":388,"title":{},"content":{"7":{"position":[[277,12]]},"12":{"position":[[232,12]]}},"keywords":{}}],["function(yearly_term",{"_index":472,"title":{},"content":{"9":{"position":[[559,21]]}},"keywords":{}}],["functioncompil",{"_index":3917,"title":{},"content":{"121":{"position":[[2142,15]]}},"keywords":{}}],["functool",{"_index":1446,"title":{},"content":{"30":{"position":[[8343,9]]},"51":{"position":[[1066,9]]}},"keywords":{}}],["fundament",{"_index":2029,"title":{},"content":{"46":{"position":[[70,11],[287,13]]},"63":{"position":[[3,11]]},"101":{"position":[[768,11]]},"125":{"position":[[9634,11]]},"198":{"position":[[535,14]]}},"keywords":{}}],["further",{"_index":1412,"title":{"55":{"position":[[4,7]]}},"content":{"30":{"position":[[5685,7]]},"43":{"position":[[164,7]]},"90":{"position":[[23,8]]},"160":{"position":[[3397,8]]},"189":{"position":[[596,8]]}},"keywords":{}}],["futur",{"_index":874,"title":{"22":{"position":[[12,7]]}},"content":{"22":{"position":[[1165,7]]},"23":{"position":[[22,7]]},"24":{"position":[[69,7],[231,6],[315,7],[1883,7],[2033,8],[2107,6],[2117,8],[2146,8],[2192,6],[2202,8],[2236,8],[2286,6],[2296,8],[2953,7],[3282,7],[3406,7]]},"25":{"position":[[1607,7],[1757,8],[1831,6],[1841,8],[1870,8],[1916,6],[1926,8],[1960,8],[2010,6],[2020,8],[2635,7]]},"26":{"position":[[65,7],[394,7],[444,7],[737,7]]},"30":{"position":[[8261,6]]},"38":{"position":[[1007,7],[1269,7]]},"39":{"position":[[1816,6]]},"91":{"position":[[2943,6]]},"92":{"position":[[755,6]]},"93":{"position":[[1437,7],[3588,6]]},"98":{"position":[[147,7],[197,6]]},"106":{"position":[[1185,7]]},"125":{"position":[[3251,6]]},"148":{"position":[[466,7]]},"158":{"position":[[490,6]]},"160":{"position":[[4394,6]]},"161":{"position":[[1684,7]]},"173":{"position":[[2089,6]]},"184":{"position":[[1224,6]]}},"keywords":{}}],["future<item=vec<u8>",{"_index":4475,"title":{},"content":{"147":{"position":[[220,29]]}},"keywords":{}}],["future.result",{"_index":3272,"title":{},"content":{"93":{"position":[[3714,18]]}},"keywords":{}}],["futures.as_completed(f",{"_index":3268,"title":{},"content":{"93":{"position":[[3598,25]]}},"keywords":{}}],["futures.threadpoolexecutor(max_workers=8",{"_index":3259,"title":{},"content":{"93":{"position":[[3346,41]]}},"keywords":{}}],["futures::future::futur",{"_index":4472,"title":{},"content":{"147":{"position":[[127,24]]}},"keywords":{}}],["futures::future::ok",{"_index":4473,"title":{},"content":{"147":{"position":[[156,20]]}},"keywords":{}}],["g1",{"_index":4906,"title":{},"content":{"172":{"position":[[500,2]]}},"keywords":{}}],["gain",{"_index":2361,"title":{},"content":{"61":{"position":[[948,4]]}},"keywords":{}}],["game",{"_index":2619,"title":{},"content":{"72":{"position":[[687,5]]},"139":{"position":[[951,5]]}},"keywords":{}}],["gap",{"_index":2183,"title":{},"content":{"52":{"position":[[639,3]]}},"keywords":{}}],["garbag",{"_index":3445,"title":{},"content":{"98":{"position":[[575,7]]},"132":{"position":[[159,7]]},"172":{"position":[[1,7],[36,7]]},"176":{"position":[[467,7]]},"199":{"position":[[579,7]]}},"keywords":{}}],["garden",{"_index":4756,"title":{},"content":{"161":{"position":[[1486,6]]}},"keywords":{}}],["gatsbi",{"_index":283,"title":{},"content":{"4":{"position":[[1160,6]]}},"keywords":{}}],["gaug",{"_index":1381,"title":{},"content":{"30":{"position":[[2869,5]]}},"keywords":{}}],["gaussian",{"_index":1978,"title":{},"content":{"45":{"position":[[1232,8],[1653,8]]}},"keywords":{}}],["gaussiannb",{"_index":1990,"title":{},"content":{"45":{"position":[[1933,10],[2109,12],[2889,12]]}},"keywords":{}}],["gave",{"_index":187,"title":{},"content":{"3":{"position":[[1037,4]]},"97":{"position":[[2582,4]]},"113":{"position":[[2003,4]]},"132":{"position":[[766,4]]},"174":{"position":[[72,4],[122,4]]}},"keywords":{}}],["gbm",{"_index":385,"title":{},"content":{"7":{"position":[[227,3]]}},"keywords":{}}],["gc",{"_index":4905,"title":{},"content":{"172":{"position":[[486,2],[1118,2]]}},"keywords":{}}],["gc_threshold",{"_index":4899,"title":{},"content":{"172":{"position":[[250,12]]}},"keywords":{}}],["ge",{"_index":783,"title":{},"content":{"20":{"position":[[671,3]]}},"keywords":{}}],["gecko/20100101",{"_index":3228,"title":{},"content":{"93":{"position":[[2407,15]]}},"keywords":{}}],["gener",{"_index":764,"title":{"197":{"position":[[0,9]]}},"content":{"20":{"position":[[187,8]]},"24":{"position":[[3132,7]]},"30":{"position":[[952,8],[2350,9],[8084,10],[8136,9]]},"64":{"position":[[267,10]]},"74":{"position":[[249,7]]},"75":{"position":[[384,8]]},"89":{"position":[[300,9]]},"90":{"position":[[3992,8],[5194,7]]},"104":{"position":[[1681,8]]},"106":{"position":[[169,8]]},"108":{"position":[[133,10]]},"109":{"position":[[501,9]]},"111":{"position":[[82,9]]},"112":{"position":[[111,9],[245,9],[339,9],[464,9],[1210,9]]},"113":{"position":[[64,8],[831,7],[1939,7],[2138,7]]},"121":{"position":[[1105,8]]},"125":{"position":[[6713,9]]},"128":{"position":[[392,10],[1191,9],[1630,9]]},"141":{"position":[[308,9]]},"155":{"position":[[289,7]]},"172":{"position":[[195,10],[335,12]]},"190":{"position":[[680,9]]},"197":{"position":[[823,9]]},"199":{"position":[[1128,10]]}},"keywords":{}}],["generator"",{"_index":4767,"title":{},"content":{"163":{"position":[[649,16]]}},"keywords":{}}],["genuin",{"_index":254,"title":{},"content":{"4":{"position":[[722,7]]}},"keywords":{}}],["geom.lin",{"_index":439,"title":{},"content":{"7":{"position":[[1244,10]]}},"keywords":{}}],["get",{"_index":481,"title":{"59":{"position":[[0,7]]}},"content":{"10":{"position":[[66,7]]},"30":{"position":[[9119,7]]},"65":{"position":[[2143,4]]},"66":{"position":[[462,4]]},"91":{"position":[[5752,7]]},"95":{"position":[[532,7]]},"97":{"position":[[2499,7],[4791,7]]},"102":{"position":[[788,4]]},"115":{"position":[[2630,7]]},"121":{"position":[[1364,7]]},"123":{"position":[[973,7]]},"181":{"position":[[642,7]]},"183":{"position":[[436,4],[582,4]]},"188":{"position":[[76,4]]},"196":{"position":[[1372,7]]}},"keywords":{}}],["get_forecast(*loc",{"_index":1492,"title":{},"content":{"30":{"position":[[9862,18]]}},"keywords":{}}],["get_forecast(lat",{"_index":1465,"title":{},"content":{"30":{"position":[[8754,17]]}},"keywords":{}}],["get_i",{"_index":3727,"title":{},"content":{"112":{"position":[[1531,8],[1617,7]]}},"keywords":{}}],["get_int(&self",{"_index":5340,"title":{},"content":{"197":{"position":[[311,18],[440,18],[589,18]]}},"keywords":{}}],["get_x",{"_index":3725,"title":{},"content":{"112":{"position":[[1513,8],[1605,7]]}},"keywords":{}}],["getint",{"_index":5339,"title":{},"content":{"197":{"position":[[299,6],[415,6],[563,6],[918,9],[960,7]]}},"keywords":{}}],["gil",{"_index":4900,"title":{"187":{"position":[[12,3]]}},"content":{"172":{"position":[[299,3]]},"188":{"position":[[306,4],[430,4],[568,3],[965,4],[1209,3],[1332,3],[1772,4],[2354,4],[2930,3],[3207,3],[3337,3],[3406,3],[4195,4],[4354,4],[4458,3],[4513,3]]},"189":{"position":[[656,3],[841,3],[1277,3],[1999,3],[2299,3],[2602,3],[2903,3]]},"190":{"position":[[159,3],[227,3],[340,4],[841,3],[948,3]]}},"keywords":{}}],["gil/lib/python3.7/sit",{"_index":5210,"title":{},"content":{"188":{"position":[[3799,22]]}},"keywords":{}}],["git",{"_index":4072,"title":{},"content":{"125":{"position":[[3049,3]]}},"keywords":{}}],["github",{"_index":99,"title":{},"content":{"2":{"position":[[368,6]]},"148":{"position":[[397,7]]}},"keywords":{}}],["give",{"_index":1346,"title":{},"content":{"30":{"position":[[822,4]]},"40":{"position":[[3535,4]]},"51":{"position":[[3271,4]]},"61":{"position":[[881,4]]},"65":{"position":[[197,4],[2583,5]]},"68":{"position":[[173,4]]},"69":{"position":[[145,4]]},"88":{"position":[[178,4],[623,6]]},"90":{"position":[[5146,4]]},"93":{"position":[[4038,6]]},"97":{"position":[[1114,4],[2311,4],[3975,4],[5436,4],[5634,4],[5795,4]]},"98":{"position":[[906,4]]},"102":{"position":[[1418,4]]},"106":{"position":[[789,4]]},"120":{"position":[[728,4],[959,5]]},"123":{"position":[[894,6]]},"125":{"position":[[9780,4]]},"128":{"position":[[325,5],[692,4],[1450,4]]},"129":{"position":[[885,6],[1121,4],[1311,4],[1892,4]]}},"keywords":{}}],["given",{"_index":404,"title":{},"content":{"7":{"position":[[567,5]]},"9":{"position":[[252,5]]},"17":{"position":[[18,5]]},"25":{"position":[[1,5]]},"26":{"position":[[384,5]]},"34":{"position":[[447,5]]},"49":{"position":[[1,5],[221,5],[601,5]]},"51":{"position":[[805,5],[3196,5]]},"57":{"position":[[652,5]]},"65":{"position":[[1187,5]]},"69":{"position":[[1,5],[212,6]]},"74":{"position":[[105,5]]},"83":{"position":[[1,5],[134,5]]},"85":{"position":[[414,5]]},"89":{"position":[[542,5]]},"90":{"position":[[764,5],[2149,5]]},"91":{"position":[[1390,5],[1674,5]]},"93":{"position":[[191,5]]},"100":{"position":[[196,5]]},"102":{"position":[[479,5],[717,5],[977,5]]},"123":{"position":[[14,5]]},"125":{"position":[[1570,5]]},"137":{"position":[[174,5]]},"142":{"position":[[98,5]]},"155":{"position":[[952,5]]},"163":{"position":[[55,5]]},"179":{"position":[[454,5]]},"193":{"position":[[96,5]]},"197":{"position":[[1014,5]]}},"keywords":{}}],["glass",{"_index":4754,"title":{},"content":{"161":{"position":[[1321,5],[1407,5]]}},"keywords":{}}],["global",{"_index":4371,"title":{"177":{"position":[[21,6]]}},"content":{"133":{"position":[[313,7]]},"159":{"position":[[391,6]]},"182":{"position":[[438,8]]},"185":{"position":[[106,8]]}},"keywords":{}}],["global_alloc",{"_index":4370,"title":{},"content":{"133":{"position":[[286,19]]},"144":{"position":[[115,19]]},"145":{"position":[[91,19]]},"146":{"position":[[119,19]]},"152":{"position":[[1128,19]]},"156":{"position":[[1211,19]]}},"keywords":{}}],["global_articl",{"_index":909,"title":{},"content":{"22":{"position":[[765,15],[1049,15]]}},"keywords":{}}],["globalalloc",{"_index":4529,"title":{},"content":{"152":{"position":[[1280,11]]},"156":{"position":[[1363,11]]}},"keywords":{}}],["gnb",{"_index":1998,"title":{},"content":{"45":{"position":[[2103,3],[2883,3]]}},"keywords":{}}],["gnb.fit(x_xform",{"_index":1999,"title":{},"content":{"45":{"position":[[2122,16],[2902,16]]}},"keywords":{}}],["gnb.score(x_xform",{"_index":2000,"title":{},"content":{"45":{"position":[[2149,18],[2929,18]]}},"keywords":{}}],["go",{"_index":308,"title":{},"content":{"6":{"position":[[92,2],[197,5]]},"7":{"position":[[706,5],[1123,5]]},"8":{"position":[[7,2]]},"9":{"position":[[117,5]]},"12":{"position":[[11,5]]},"14":{"position":[[1176,5]]},"15":{"position":[[559,2],[666,2]]},"22":{"position":[[7,5]]},"23":{"position":[[42,5]]},"26":{"position":[[727,2]]},"30":{"position":[[1089,5]]},"33":{"position":[[1156,2]]},"34":{"position":[[1148,5]]},"35":{"position":[[285,5]]},"40":{"position":[[2370,2]]},"43":{"position":[[80,5],[1080,5]]},"45":{"position":[[580,5],[1557,5]]},"49":{"position":[[146,2]]},"51":{"position":[[2758,2]]},"52":{"position":[[510,2],[554,5]]},"53":{"position":[[122,3],[1921,5]]},"57":{"position":[[333,5],[540,3],[634,2]]},"60":{"position":[[70,2]]},"61":{"position":[[1314,2],[1880,2]]},"64":{"position":[[95,5],[213,5],[1184,2],[1218,5]]},"66":{"position":[[756,5]]},"68":{"position":[[122,5]]},"76":{"position":[[1616,2]]},"77":{"position":[[7,2]]},"81":{"position":[[19,2]]},"88":{"position":[[2279,5],[2342,5],[3636,2]]},"90":{"position":[[11,2]]},"91":{"position":[[5048,5]]},"92":{"position":[[11,5],[1362,2],[1579,5]]},"95":{"position":[[516,5]]},"96":{"position":[[1344,5]]},"97":{"position":[[1231,5],[2086,5],[2134,5],[5210,5],[6203,5]]},"98":{"position":[[1204,5]]},"100":{"position":[[5,5]]},"101":{"position":[[415,2]]},"103":{"position":[[374,2],[431,5],[2276,5]]},"110":{"position":[[7,5],[196,5],[384,5]]},"112":{"position":[[260,2]]},"113":{"position":[[153,5],[267,2],[2497,2]]},"115":{"position":[[27,5]]},"120":{"position":[[214,2]]},"123":{"position":[[76,5],[326,5],[816,5]]},"124":{"position":[[336,5],[772,5]]},"125":{"position":[[1496,6],[1925,5],[2526,5],[2645,5],[9966,5],[10886,5]]},"128":{"position":[[1900,5]]},"130":{"position":[[512,2]]},"132":{"position":[[481,5]]},"135":{"position":[[42,5]]},"158":{"position":[[263,5]]},"160":{"position":[[751,5],[3386,5]]},"170":{"position":[[486,5]]},"174":{"position":[[1063,2]]},"175":{"position":[[506,5]]},"193":{"position":[[698,2]]}},"keywords":{}}],["goal",{"_index":236,"title":{},"content":{"4":{"position":[[301,5]]},"17":{"position":[[1,5]]},"125":{"position":[[3930,4]]},"186":{"position":[[174,6]]}},"keywords":{}}],["god",{"_index":2238,"title":{},"content":{"53":{"position":[[937,3]]}},"keywords":{}}],["godli",{"_index":2223,"title":{},"content":{"53":{"position":[[688,5]]}},"keywords":{}}],["goe",{"_index":1517,"title":{},"content":{"32":{"position":[[293,4]]},"33":{"position":[[911,4],[938,4]]},"38":{"position":[[196,4]]},"57":{"position":[[108,4]]},"58":{"position":[[598,4],[642,4]]},"61":{"position":[[213,4]]},"75":{"position":[[1198,4]]},"91":{"position":[[324,4]]},"193":{"position":[[2341,4]]},"196":{"position":[[1440,4]]}},"keywords":{}}],["gold",{"_index":1097,"title":{},"content":{"24":{"position":[[2564,4],[2756,4],[3154,4]]},"25":{"position":[[2287,4],[2479,4]]}},"keywords":{}}],["gone",{"_index":1347,"title":{},"content":{"30":{"position":[[861,4]]},"43":{"position":[[192,4]]},"103":{"position":[[2433,5]]},"125":{"position":[[324,5]]}},"keywords":{}}],["good",{"_index":191,"title":{},"content":{"3":{"position":[[1109,4]]},"4":{"position":[[329,4]]},"24":{"position":[[221,4]]},"26":{"position":[[464,4],[569,4]]},"40":{"position":[[1101,4]]},"44":{"position":[[154,4],[168,5],[413,4]]},"53":{"position":[[626,5],[1708,4],[1889,4]]},"82":{"position":[[1021,5],[1141,4]]},"83":{"position":[[77,4]]},"88":{"position":[[229,4]]},"98":{"position":[[9,4]]},"100":{"position":[[287,4]]},"122":{"position":[[678,4]]},"125":{"position":[[871,4],[1258,4],[10150,4],[11497,4],[11623,4]]},"150":{"position":[[257,4]]},"153":{"position":[[259,5]]},"173":{"position":[[1965,4]]},"193":{"position":[[837,4]]},"195":{"position":[[952,4]]}},"keywords":{}}],["goog/nasdaq_bib",{"_index":1828,"title":{},"content":{"40":{"position":[[2666,18]]}},"keywords":{}}],["goog/nasdaq_ibb",{"_index":1829,"title":{},"content":{"40":{"position":[[2685,19]]}},"keywords":{}}],["goog/nyse_voo",{"_index":716,"title":{},"content":{"17":{"position":[[206,15]]}},"keywords":{}}],["googl",{"_index":1748,"title":{},"content":{"39":{"position":[[2314,6]]},"96":{"position":[[1373,8],[1508,9]]},"175":{"position":[[294,7]]}},"keywords":{}}],["google'sbenchmark",{"_index":5052,"title":{},"content":{"176":{"position":[[1226,17]]}},"keywords":{}}],["gotten",{"_index":3316,"title":{},"content":{"96":{"position":[[125,6]]},"98":{"position":[[544,6]]},"113":{"position":[[31,6]]},"122":{"position":[[392,6]]}},"keywords":{}}],["govern",{"_index":5275,"title":{},"content":{"193":{"position":[[367,7]]}},"keywords":{}}],["graalvm",{"_index":4932,"title":{},"content":{"172":{"position":[[2192,7]]}},"keywords":{}}],["grammar",{"_index":2281,"title":{},"content":{"53":{"position":[[1773,7],[1832,8],[1894,7]]}},"keywords":{}}],["grant",{"_index":2368,"title":{},"content":{"61":{"position":[[1369,5]]}},"keywords":{}}],["granular",{"_index":2501,"title":{},"content":{"65":{"position":[[251,12]]}},"keywords":{}}],["graph",{"_index":1800,"title":{},"content":{"40":{"position":[[582,7]]},"45":{"position":[[3315,6]]}},"keywords":{}}],["graphic",{"_index":1888,"title":{},"content":{"43":{"position":[[1173,11]]}},"keywords":{}}],["great",{"_index":252,"title":{},"content":{"4":{"position":[[703,5]]},"24":{"position":[[3477,5]]},"29":{"position":[[314,5]]},"76":{"position":[[2318,5]]},"89":{"position":[[975,6]]},"120":{"position":[[801,5]]},"121":{"position":[[211,5]]},"125":{"position":[[11427,6]]},"132":{"position":[[582,5]]},"137":{"position":[[85,5]]},"158":{"position":[[252,5]]},"160":{"position":[[671,5],[929,5]]},"161":{"position":[[1535,6]]},"172":{"position":[[1664,5],[1825,5]]},"188":{"position":[[149,5]]},"194":{"position":[[734,5]]},"199":{"position":[[611,5]]}},"keywords":{}}],["greater",{"_index":1416,"title":{},"content":{"30":{"position":[[5971,7]]},"32":{"position":[[1161,7],[2201,7]]},"33":{"position":[[168,7],[640,7]]}},"keywords":{}}],["green",{"_index":3068,"title":{},"content":{"90":{"position":[[5225,5]]}},"keywords":{}}],["ground",{"_index":2213,"title":{},"content":{"53":{"position":[[493,6]]}},"keywords":{}}],["grow",{"_index":1200,"title":{},"content":{"28":{"position":[[163,7]]}},"keywords":{}}],["gt",{"_index":417,"title":{},"content":{"7":{"position":[[822,4]]},"13":{"position":[[976,4],[1165,4]]},"14":{"position":[[1994,4],[2199,4]]},"15":{"position":[[1042,4],[1161,4],[1662,4],[1867,4]]},"24":{"position":[[1375,4],[1398,4]]},"25":{"position":[[1095,4],[1118,4]]},"30":{"position":[[3277,4],[6345,4]]},"32":{"position":[[854,4]]},"34":{"position":[[1555,4]]},"39":{"position":[[747,4]]},"52":{"position":[[964,4]]},"76":{"position":[[2688,4],[2771,4]]},"92":{"position":[[909,5]]},"96":{"position":[[184,4],[692,4],[1111,4],[1641,4],[2187,4]]},"97":{"position":[[1495,4],[1522,4],[1943,4],[3678,4],[5030,4]]},"115":{"position":[[1096,4],[1443,4],[1726,4],[2184,4]]},"116":{"position":[[1048,4],[1348,4],[1631,4],[2042,4]]},"125":{"position":[[4285,4]]},"129":{"position":[[1489,4]]},"136":{"position":[[296,4]]},"147":{"position":[[210,4]]},"152":{"position":[[1357,4]]},"156":{"position":[[1440,4]]},"163":{"position":[[1785,4]]},"172":{"position":[[245,4]]},"180":{"position":[[447,4]]},"181":{"position":[[127,4],[249,4]]},"183":{"position":[[352,4],[498,4]]},"184":{"position":[[566,4]]},"189":{"position":[[1102,4],[1372,4],[3096,4]]},"193":{"position":[[1095,4],[2499,4],[3270,4],[3584,4]]},"196":{"position":[[951,4]]},"197":{"position":[[331,4],[460,4],[609,4]]}},"keywords":{}}],["gt;>>",{"_index":4309,"title":{},"content":{"129":{"position":[[2112,12],[2379,12],[2441,12],[2547,12],[2604,12],[2623,12]]}},"keywords":{}}],["guarante",{"_index":115,"title":{"31":{"position":[[0,10]]}},"content":{"2":{"position":[[618,9]]},"20":{"position":[[1136,9]]},"32":{"position":[[243,9],[392,9],[728,10],[1015,10],[1331,9],[2330,10]]},"36":{"position":[[58,9]]},"97":{"position":[[55,9],[146,10]]},"106":{"position":[[823,9]]},"115":{"position":[[2838,9]]},"117":{"position":[[378,12]]},"122":{"position":[[1100,10]]},"143":{"position":[[445,9]]},"159":{"position":[[532,9],[895,10]]},"160":{"position":[[3122,9]]},"172":{"position":[[1517,10]]},"175":{"position":[[600,10]]},"178":{"position":[[17,10]]},"181":{"position":[[700,10]]},"183":{"position":[[63,10],[178,9]]},"195":{"position":[[19,10]]}},"keywords":{}}],["guard",{"_index":3444,"title":{},"content":{"98":{"position":[[532,6]]},"158":{"position":[[476,5]]}},"keywords":{}}],["guardrail",{"_index":12,"title":{},"content":{"1":{"position":[[112,10]]}},"keywords":{}}],["guess",{"_index":1439,"title":{},"content":{"30":{"position":[[7828,5]]},"44":{"position":[[1031,5],[1519,5],[1630,5],[1703,5]]},"45":{"position":[[24,5],[179,5],[1004,6],[1893,6],[2606,5],[2707,5]]},"51":{"position":[[1919,8]]},"75":{"position":[[147,5],[228,5]]},"76":{"position":[[1984,8],[2122,7],[2324,7],[3291,6],[3313,5]]},"82":{"position":[[1146,6]]},"93":{"position":[[3,5]]},"97":{"position":[[4053,7]]},"120":{"position":[[13,5]]}},"keywords":{}}],["guess"",{"_index":1972,"title":{},"content":{"45":{"position":[[657,11],[2345,12],[2420,12],[3125,12],[3200,12]]}},"keywords":{}}],["gui",{"_index":4035,"title":{},"content":{"125":{"position":[[994,3]]}},"keywords":{}}],["guid",{"_index":4485,"title":{},"content":{"148":{"position":[[509,5]]},"172":{"position":[[1179,5],[2250,6]]},"176":{"position":[[743,7]]}},"keywords":{}}],["guide.xlabel(xlabel",{"_index":442,"title":{},"content":{"7":{"position":[[1297,21]]}},"keywords":{}}],["guide.xticks(ticks=x_tick",{"_index":440,"title":{},"content":{"7":{"position":[[1255,27]]}},"keywords":{}}],["guide.ylabel("value"",{"_index":443,"title":{},"content":{"7":{"position":[[1319,32]]}},"keywords":{}}],["guidelin",{"_index":5356,"title":{},"content":{"198":{"position":[[217,9]]}},"keywords":{}}],["guy"",{"_index":4730,"title":{},"content":{"161":{"position":[[354,9]]}},"keywords":{}}],["guywho",{"_index":3879,"title":{},"content":{"121":{"position":[[318,6]]}},"keywords":{}}],["h",{"_index":2130,"title":{},"content":{"51":{"position":[[2506,1]]}},"keywords":{}}],["h:%m:%",{"_index":2424,"title":{},"content":{"62":{"position":[[1115,11]]}},"keywords":{}}],["hack",{"_index":2362,"title":{},"content":{"61":{"position":[[1070,7]]}},"keywords":{}}],["half",{"_index":1133,"title":{},"content":{"24":{"position":[[3394,4]]},"26":{"position":[[432,4]]},"90":{"position":[[3293,4]]},"188":{"position":[[2774,4]]}},"keywords":{}}],["hall",{"_index":2575,"title":{},"content":{"68":{"position":[[978,4]]}},"keywords":{}}],["hand",{"_index":261,"title":{},"content":{"4":{"position":[[809,4]]},"58":{"position":[[939,5]]},"74":{"position":[[228,5]]},"77":{"position":[[184,4]]},"86":{"position":[[892,5]]},"111":{"position":[[795,5]]},"139":{"position":[[321,4]]},"163":{"position":[[793,5],[2504,5]]},"172":{"position":[[2223,5]]}},"keywords":{}}],["handl",{"_index":222,"title":{"61":{"position":[[0,8]]},"128":{"position":[[10,8]]}},"content":{"4":{"position":[[54,6]]},"39":{"position":[[2307,6]]},"61":{"position":[[1262,8]]},"90":{"position":[[3446,6]]},"95":{"position":[[36,6]]},"96":{"position":[[2000,6]]},"97":{"position":[[3320,8],[3485,8],[3984,6],[4121,8],[6511,8]]},"115":{"position":[[698,6],[1130,6],[1477,6],[1760,6],[2218,6]]},"116":{"position":[[717,6],[1082,6],[1382,6],[1665,6],[2076,6]]},"117":{"position":[[1574,6]]},"120":{"position":[[100,8]]},"125":{"position":[[6325,6]]},"127":{"position":[[1532,7]]},"129":{"position":[[2714,7]]},"130":{"position":[[71,7]]},"163":{"position":[[735,6]]},"165":{"position":[[550,6],[1144,7]]},"166":{"position":[[376,6]]},"173":{"position":[[1118,6],[1389,9],[1803,6],[1882,7],[2177,6]]},"175":{"position":[[1054,6],[1105,6]]},"196":{"position":[[583,6]]}},"keywords":{}}],["handle(&self",{"_index":3403,"title":{},"content":{"97":{"position":[[3638,17]]}},"keywords":{}}],["handle.join().unwrap",{"_index":3770,"title":{},"content":{"115":{"position":[[815,22]]},"116":{"position":[[835,23]]},"117":{"position":[[1855,23]]}},"keywords":{}}],["handle_data(self",{"_index":951,"title":{},"content":{"22":{"position":[[1729,17]]},"93":{"position":[[1718,17]]}},"keywords":{}}],["handle_endtag(self",{"_index":963,"title":{},"content":{"22":{"position":[[2273,19]]},"93":{"position":[[2187,19]]}},"keywords":{}}],["handle_starttag(self",{"_index":887,"title":{},"content":{"22":{"position":[[300,21],[1367,21]]},"93":{"position":[[1636,21]]}},"keywords":{}}],["handlebar",{"_index":3307,"title":{},"content":{"95":{"position":[[235,10]]}},"keywords":{}}],["handler",{"_index":52,"title":{},"content":{"1":{"position":[[589,7]]},"96":{"position":[[266,7]]},"97":{"position":[[637,7],[3232,7],[3609,7]]},"125":{"position":[[6870,7]]},"173":{"position":[[1490,7]]}},"keywords":{}}],["handlerhost",{"_index":4103,"title":{},"content":{"125":{"position":[[4914,11]]}},"keywords":{}}],["handles"",{"_index":4145,"title":{},"content":{"125":{"position":[[7091,13]]}},"keywords":{}}],["handshak",{"_index":5018,"title":{},"content":{"175":{"position":[[847,11]]}},"keywords":{}}],["hang",{"_index":3525,"title":{},"content":{"103":{"position":[[1021,7],[1104,9]]}},"keywords":{}}],["happen",{"_index":1135,"title":{},"content":{"25":{"position":[[138,8]]},"26":{"position":[[56,7]]},"28":{"position":[[2339,7]]},"30":{"position":[[7925,10]]},"40":{"position":[[1217,7],[1360,9]]},"44":{"position":[[1048,9],[1138,6]]},"51":{"position":[[2814,6]]},"61":{"position":[[2121,7]]},"70":{"position":[[6,7]]},"76":{"position":[[1652,7]]},"88":{"position":[[3717,9]]},"90":{"position":[[803,7],[2188,7]]},"91":{"position":[[4774,7]]},"125":{"position":[[2437,8],[10753,10],[10983,6]]},"135":{"position":[[353,8],[427,8],[494,8]]},"139":{"position":[[906,7]]},"143":{"position":[[217,9]]},"147":{"position":[[543,7]]},"156":{"position":[[1035,7]]},"161":{"position":[[744,7]]},"172":{"position":[[55,7],[286,8]]},"173":{"position":[[1373,7],[1710,9],[2225,7]]},"199":{"position":[[480,8]]}},"keywords":{}}],["happi",{"_index":1859,"title":{"42":{"position":[[30,9]]}},"content":{"43":{"position":[[918,6]]},"53":{"position":[[644,5]]},"122":{"position":[[1324,5]]},"123":{"position":[[548,5]]},"150":{"position":[[981,5]]}},"keywords":{}}],["hard",{"_index":1177,"title":{},"content":{"26":{"position":[[707,5]]},"53":{"position":[[1199,4]]},"69":{"position":[[253,4]]},"76":{"position":[[3388,4]]},"93":{"position":[[1023,4]]},"96":{"position":[[21,5],[222,5],[409,4]]},"122":{"position":[[697,5]]},"124":{"position":[[789,5]]},"125":{"position":[[900,4],[1013,5],[1140,4]]},"135":{"position":[[557,4]]},"176":{"position":[[627,4]]},"197":{"position":[[1445,4]]}},"keywords":{}}],["hardcor",{"_index":4692,"title":{},"content":{"160":{"position":[[2395,8]]}},"keywords":{}}],["harder",{"_index":5334,"title":{},"content":{"196":{"position":[[1407,7]]}},"keywords":{}}],["hardest",{"_index":4361,"title":{},"content":{"133":{"position":[[13,7]]}},"keywords":{}}],["hardwar",{"_index":4939,"title":{"174":{"position":[[0,9]]}},"content":{"173":{"position":[[70,9]]},"174":{"position":[[1275,8]]}},"keywords":{}}],["harnessforeachformat",{"_index":4851,"title":{},"content":{"167":{"position":[[23,21]]}},"keywords":{}}],["harri",{"_index":2221,"title":{},"content":{"53":{"position":[[665,6]]}},"keywords":{}}],["hasarrow",{"_index":5329,"title":{},"content":{"196":{"position":[[370,8]]}},"keywords":{}}],["hasgon",{"_index":4572,"title":{},"content":{"155":{"position":[[1133,7]]}},"keywords":{}}],["hashmap",{"_index":4640,"title":{},"content":{"159":{"position":[[1052,9]]}},"keywords":{}}],["hashtag",{"_index":2060,"title":{},"content":{"49":{"position":[[477,9],[591,9],[619,9],[668,8]]},"51":{"position":[[1522,9],[1553,8],[1676,8],[1941,8],[2182,8],[2228,8],[2257,8],[2593,8],[2661,7],[2912,8]]},"52":{"position":[[143,8],[357,7],[444,9],[599,9],[820,8]]}},"keywords":{}}],["hashtag_dist",{"_index":2127,"title":{},"content":{"51":{"position":[[2403,12],[3848,14]]},"52":{"position":[[383,13],[852,13]]}},"keywords":{}}],["hashtag_dist.hashtag",{"_index":2157,"title":{},"content":{"51":{"position":[[3886,22]]}},"keywords":{}}],["hashtag_dist.prob",{"_index":2158,"title":{},"content":{"51":{"position":[[3909,18]]}},"keywords":{}}],["hashtags)).strip",{"_index":2193,"title":{},"content":{"52":{"position":[[1163,18]]}},"keywords":{}}],["hashtags.fil",{"_index":2136,"title":{},"content":{"51":{"position":[[2964,13]]}},"keywords":{}}],["hashtags.mean",{"_index":2121,"title":{},"content":{"51":{"position":[[2093,15]]}},"keywords":{}}],["hashtags.plot(kind='hist",{"_index":2112,"title":{},"content":{"51":{"position":[[1744,26]]}},"keywords":{}}],["hashtags.unique().max",{"_index":2111,"title":{},"content":{"51":{"position":[[1720,23]]}},"keywords":{}}],["haskel",{"_index":2236,"title":{},"content":{"53":{"position":[[913,8]]}},"keywords":{}}],["hasmanydifferentcollectionalgorithmsto",{"_index":4903,"title":{},"content":{"172":{"position":[[364,38]]}},"keywords":{}}],["hasn't",{"_index":4205,"title":{},"content":{"125":{"position":[[11109,6]]}},"keywords":{}}],["hast",{"_index":2627,"title":{},"content":{"73":{"position":[[565,8]]}},"keywords":{}}],["hate",{"_index":4028,"title":{},"content":{"125":{"position":[[823,4]]}},"keywords":{}}],["have",{"_index":794,"title":{},"content":{"20":{"position":[[846,6]]},"28":{"position":[[1577,6],[3363,6]]},"30":{"position":[[7409,6]]},"61":{"position":[[160,6]]},"72":{"position":[[511,6]]},"97":{"position":[[173,6],[253,6]]},"98":{"position":[[559,6]]},"121":{"position":[[1,6],[666,6]]},"161":{"position":[[0,6]]},"175":{"position":[[115,6]]},"179":{"position":[[1460,6]]},"193":{"position":[[691,6]]}},"keywords":{}}],["haven't",{"_index":668,"title":{},"content":{"15":{"position":[[165,7]]},"34":{"position":[[3215,7]]},"106":{"position":[[1044,7]]},"124":{"position":[[644,7]]}},"keywords":{}}],["haze",{"_index":3365,"title":{},"content":{"97":{"position":[[606,7]]}},"keywords":{}}],["hcat(final_mot",{"_index":533,"title":{},"content":{"12":{"position":[[474,18]]}},"keywords":{}}],["hcat(full_mot",{"_index":522,"title":{},"content":{"11":{"position":[[514,17]]}},"keywords":{}}],["he'",{"_index":2960,"title":{},"content":{"89":{"position":[[970,4]]}},"keywords":{}}],["header",{"_index":3230,"title":{},"content":{"93":{"position":[[2437,7]]}},"keywords":{}}],["header=10",{"_index":3251,"title":{},"content":{"93":{"position":[[3172,10]]}},"keywords":{}}],["headers=headers).cont",{"_index":3238,"title":{},"content":{"93":{"position":[[2696,26]]}},"keywords":{}}],["headers={"us",{"_index":917,"title":{},"content":{"22":{"position":[[929,19],[2427,19]]}},"keywords":{}}],["health",{"_index":2321,"title":{},"content":{"58":{"position":[[33,6]]}},"keywords":{}}],["heap",{"_index":4437,"title":{"157":{"position":[[0,4]]}},"content":{"141":{"position":[[180,5],[292,4]]},"152":{"position":[[109,4],[530,4]]},"155":{"position":[[486,5],[647,4],[844,4],[971,4],[1193,4],[1247,4]]},"156":{"position":[[22,4],[209,4],[446,4],[509,5],[971,4]]},"157":{"position":[[78,5],[118,4],[715,4]]},"158":{"position":[[382,4]]},"159":{"position":[[277,4],[946,4],[1028,4],[1108,4],[1214,4]]},"160":{"position":[[1350,6]]},"164":{"position":[[384,4]]},"172":{"position":[[1058,4],[1154,4]]},"193":{"position":[[2038,4],[2127,4],[2414,4]]},"194":{"position":[[129,4],[201,4],[689,4]]},"195":{"position":[[1011,4]]},"196":{"position":[[155,4],[1918,4]]},"197":{"position":[[219,5],[1543,4]]},"198":{"position":[[491,4],[793,4],[858,4],[904,4]]},"199":{"position":[[550,5],[902,4],[970,5],[1050,4]]}},"keywords":{}}],["heaptrack",{"_index":4339,"title":{"131":{"position":[[16,9]]},"134":{"position":[[8,10]]}},"content":{"132":{"position":[[1052,10]]},"134":{"position":[[27,9],[147,9]]}},"keywords":{}}],["heaptrack.my_appplication.xxxx.gz",{"_index":4375,"title":{},"content":{"134":{"position":[[277,34]]}},"keywords":{}}],["heaptrack_gui",{"_index":4376,"title":{},"content":{"134":{"position":[[335,14]]}},"keywords":{}}],["hear",{"_index":1332,"title":{},"content":{"30":{"position":[[377,7]]},"101":{"position":[[960,4]]},"103":{"position":[[418,4]]},"104":{"position":[[440,4],[1879,5]]},"123":{"position":[[437,4]]}},"keywords":{}}],["heard",{"_index":257,"title":{},"content":{"4":{"position":[[746,5]]}},"keywords":{}}],["heart",{"_index":2317,"title":{},"content":{"57":{"position":[[681,5]]},"58":{"position":[[308,5],[545,5],[630,5]]},"62":{"position":[[93,5],[875,6],[999,5],[1719,5]]},"64":{"position":[[1970,5]]},"65":{"position":[[43,5],[184,5],[1314,5],[2577,5]]}},"keywords":{}}],["heart'][0]['datetim",{"_index":2417,"title":{},"content":{"62":{"position":[[939,22]]}},"keywords":{}}],["heartbeat",{"_index":2308,"title":{"64":{"position":[[9,10]]},"65":{"position":[[9,10]]}},"content":{"57":{"position":[[45,10]]},"58":{"position":[[685,10]]},"62":{"position":[[1607,10]]},"64":{"position":[[60,10],[628,10],[673,10],[1157,11],[1258,10],[1834,11],[1882,10],[1921,11]]},"65":{"position":[[286,10],[514,10],[549,10],[1034,10],[1143,10],[1992,10],[2092,10]]}},"keywords":{}}],["heartbeats_4year",{"_index":2503,"title":{},"content":{"65":{"position":[[630,16],[698,16],[849,16],[918,16]]}},"keywords":{}}],["heartbeats_quart",{"_index":2521,"title":{},"content":{"65":{"position":[[1662,18],[1809,18],[1878,18]]}},"keywords":{}}],["heartbeats_until_2016",{"_index":2488,"title":{},"content":{"64":{"position":[[1618,21],[1719,21]]}},"keywords":{}}],["heartrat",{"_index":2377,"title":{},"content":{"61":{"position":[[1644,12]]}},"keywords":{}}],["heavi",{"_index":2069,"title":{},"content":{"51":{"position":[[55,5]]}},"keywords":{}}],["heavili",{"_index":4280,"title":{},"content":{"129":{"position":[[490,7]]}},"keywords":{}}],["heck",{"_index":4382,"title":{},"content":{"135":{"position":[[640,4]]}},"keywords":{}}],["height=300",{"_index":1390,"title":{},"content":{"30":{"position":[[3836,11],[6915,11]]}},"keywords":{}}],["hell",{"_index":4031,"title":{},"content":{"125":{"position":[[922,4]]}},"keywords":{}}],["hello",{"_index":3839,"title":{"118":{"position":[[0,6]]}},"content":{},"keywords":{}}],["hello_world(req",{"_index":3328,"title":{},"content":{"96":{"position":[[656,16],[1075,16],[1605,16],[2151,16]]}},"keywords":{}}],["help",{"_index":13,"title":{},"content":{"1":{"position":[[123,4],[472,8]]},"3":{"position":[[259,5]]},"4":{"position":[[515,4]]},"24":{"position":[[3430,7]]},"44":{"position":[[1870,7]]},"89":{"position":[[940,7]]},"91":{"position":[[374,7]]},"96":{"position":[[1535,7]]},"97":{"position":[[587,7],[4225,5],[4233,5],[4648,7],[4667,5],[5874,5]]},"104":{"position":[[9,4]]},"105":{"position":[[383,4]]},"115":{"position":[[2512,4]]},"122":{"position":[[1333,4]]},"124":{"position":[[474,4]]},"137":{"position":[[114,4]]},"148":{"position":[[504,4]]},"159":{"position":[[78,7]]},"160":{"position":[[4011,8],[4101,7]]},"170":{"position":[[50,7]]},"174":{"position":[[370,4],[1122,8]]},"176":{"position":[[1179,8]]},"181":{"position":[[9,7]]}},"keywords":{}}],["henc",{"_index":270,"title":{},"content":{"4":{"position":[[930,6]]}},"keywords":{}}],["here",{"_index":630,"title":{"54":{"position":[[15,5]]}},"content":{"14":{"position":[[286,6]]},"15":{"position":[[546,5]]},"28":{"position":[[2530,5],[4031,5]]},"30":{"position":[[9529,4]]},"41":{"position":[[80,4]]},"51":{"position":[[1016,5]]},"53":{"position":[[113,4]]},"59":{"position":[[241,5]]},"61":{"position":[[259,4],[1335,5],[1838,4],[2108,5]]},"64":{"position":[[1409,4]]},"66":{"position":[[431,4]]},"91":{"position":[[3207,4]]},"92":{"position":[[1019,4],[1294,4]]},"96":{"position":[[1353,5]]},"97":{"position":[[1251,5],[2161,4]]},"103":{"position":[[2285,4]]},"105":{"position":[[2658,4]]},"108":{"position":[[311,5]]},"109":{"position":[[107,5]]},"113":{"position":[[184,4],[315,5],[376,4]]},"117":{"position":[[95,4]]},"118":{"position":[[115,4]]},"125":{"position":[[2050,4],[2700,4],[2794,5],[10942,4]]},"128":{"position":[[514,4]]},"129":{"position":[[614,4]]},"135":{"position":[[233,4]]},"145":{"position":[[199,5]]},"155":{"position":[[379,4],[693,5]]},"156":{"position":[[1043,4]]},"159":{"position":[[350,4]]},"198":{"position":[[137,5]]}},"keywords":{}}],["here'",{"_index":2357,"title":{},"content":{"61":{"position":[[636,6]]},"97":{"position":[[4943,6]]},"113":{"position":[[2462,6]]},"125":{"position":[[7463,6]]},"129":{"position":[[787,6]]},"182":{"position":[[389,6]]}},"keywords":{}}],["hereif",{"_index":3717,"title":{},"content":{"112":{"position":[[1012,6]]}},"keywords":{}}],["hesit",{"_index":3873,"title":{},"content":{"121":{"position":[[110,8]]}},"keywords":{}}],["hey",{"_index":4046,"title":{},"content":{"125":{"position":[[1337,3]]}},"keywords":{}}],["hidden",{"_index":2632,"title":{},"content":{"74":{"position":[[117,6]]}},"keywords":{}}],["hide_bann",{"_index":3505,"title":{},"content":{"103":{"position":[[247,11]]}},"keywords":{}}],["high",{"_index":797,"title":{"171":{"position":[[12,4]]}},"content":{"20":{"position":[[947,4]]},"30":{"position":[[4643,4]]},"45":{"position":[[126,5],[3506,4]]},"46":{"position":[[110,4]]},"70":{"position":[[64,5],[1250,7]]},"71":{"position":[[47,5],[135,5]]},"73":{"position":[[670,4]]},"82":{"position":[[159,5]]},"98":{"position":[[384,4]]},"104":{"position":[[508,4],[1333,4],[1548,4],[1762,4],[1820,4]]},"105":{"position":[[3322,4]]},"125":{"position":[[7005,4]]},"148":{"position":[[37,4],[437,4]]},"163":{"position":[[1263,6]]},"165":{"position":[[177,4]]},"166":{"position":[[137,4]]},"176":{"position":[[1,4],[1414,4]]}},"keywords":{}}],["higher",{"_index":1308,"title":{},"content":{"28":{"position":[[4268,6]]},"29":{"position":[[83,6]]},"38":{"position":[[494,6]]},"40":{"position":[[966,6]]},"75":{"position":[[685,6]]},"76":{"position":[[2538,7]]},"78":{"position":[[912,7]]},"82":{"position":[[287,7],[357,7],[427,7],[497,7],[567,7],[637,7],[707,7],[777,7],[847,7],[918,7]]},"88":{"position":[[3818,7]]},"170":{"position":[[319,6]]}},"keywords":{}}],["highest",{"_index":4708,"title":{},"content":{"160":{"position":[[3781,7]]}},"keywords":{}}],["highli",{"_index":1691,"title":{},"content":{"38":{"position":[[309,6],[1172,6]]},"173":{"position":[[1523,6]]}},"keywords":{}}],["highlight",{"_index":4360,"title":{},"content":{"132":{"position":[[985,9]]}},"keywords":{}}],["hilari",{"_index":2284,"title":{},"content":{"53":{"position":[[1938,9],[2057,9]]},"125":{"position":[[511,9]]}},"keywords":{}}],["hindsight",{"_index":177,"title":{},"content":{"3":{"position":[[839,10]]}},"keywords":{}}],["hire",{"_index":4499,"title":{},"content":{"150":{"position":[[580,6]]}},"keywords":{}}],["histogram",{"_index":1801,"title":{},"content":{"40":{"position":[[601,10]]}},"keywords":{}}],["histori",{"_index":1574,"title":{},"content":{"33":{"position":[[440,7]]},"50":{"position":[[29,8]]},"88":{"position":[[3140,9],[3519,9]]},"160":{"position":[[335,7]]}},"keywords":{}}],["hit",{"_index":1428,"title":{},"content":{"30":{"position":[[7129,3]]}},"keywords":{}}],["hold",{"_index":1535,"title":{},"content":{"32":{"position":[[991,5]]},"93":{"position":[[2990,8]]},"97":{"position":[[3450,4]]},"125":{"position":[[10427,5]]},"128":{"position":[[1392,7]]},"164":{"position":[[392,4]]},"192":{"position":[[93,4]]},"193":{"position":[[1164,4]]}},"keywords":{}}],["home",{"_index":3718,"title":{},"content":{"112":{"position":[[1049,5]]},"160":{"position":[[2931,4]]}},"keywords":{}}],["home/bspeice/development/isomorphic_rust/stdweb/dist",{"_index":4178,"title":{},"content":{"125":{"position":[[9029,55]]}},"keywords":{}}],["home/bspeice/development/isomorphic_rust/yew/dist",{"_index":4168,"title":{},"content":{"125":{"position":[[8561,52]]}},"keywords":{}}],["homebrew",{"_index":3670,"title":{},"content":{"108":{"position":[[476,8]]},"134":{"position":[[37,9]]}},"keywords":{}}],["homework",{"_index":2229,"title":{},"content":{"53":{"position":[[800,9]]}},"keywords":{}}],["honest",{"_index":3820,"title":{},"content":{"117":{"position":[[513,7]]}},"keywords":{}}],["honestli",{"_index":3188,"title":{},"content":{"93":{"position":[[181,9]]},"97":{"position":[[2993,8]]}},"keywords":{}}],["hood",{"_index":3547,"title":{},"content":{"103":{"position":[[2300,5]]},"125":{"position":[[6744,4]]},"127":{"position":[[905,5]]}},"keywords":{}}],["hope",{"_index":1181,"title":{},"content":{"26":{"position":[[809,4]]},"53":{"position":[[1682,5]]},"97":{"position":[[5864,4]]},"104":{"position":[[1484,4]]},"115":{"position":[[506,6]]},"121":{"position":[[2598,4]]},"124":{"position":[[599,6]]},"148":{"position":[[410,6]]},"197":{"position":[[1055,4]]}},"keywords":{}}],["hopefulli",{"_index":1222,"title":{},"content":{"28":{"position":[[765,9]]},"45":{"position":[[1822,10]]},"46":{"position":[[558,9]]},"51":{"position":[[3064,10]]}},"keywords":{}}],["horizon",{"_index":3023,"title":{},"content":{"90":{"position":[[3329,7]]},"91":{"position":[[1680,8],[2448,9],[2512,9],[2661,9],[3507,9],[4987,7],[5734,8],[5912,7],[5975,9]]},"92":{"position":[[261,9],[324,9],[473,9]]}},"keywords":{}}],["horizon*2",{"_index":3144,"title":{},"content":{"91":{"position":[[3388,9]]}},"keywords":{}}],["horizon+1",{"_index":3021,"title":{},"content":{"90":{"position":[[3230,9]]}},"keywords":{}}],["horizon=5",{"_index":3020,"title":{},"content":{"90":{"position":[[3212,11]]}},"keywords":{}}],["horribl",{"_index":3117,"title":{},"content":{"91":{"position":[[2222,8]]}},"keywords":{}}],["horror",{"_index":258,"title":{},"content":{"4":{"position":[[761,6]]}},"keywords":{}}],["hot",{"_index":2218,"title":{},"content":{"53":{"position":[[599,3]]},"161":{"position":[[1432,3]]}},"keywords":{}}],["hour",{"_index":1022,"title":{},"content":{"24":{"position":[[391,5]]},"26":{"position":[[183,5]]},"46":{"position":[[25,5]]},"97":{"position":[[895,5],[2201,5],[5185,5]]}},"keywords":{}}],["hr_d",{"_index":2460,"title":{},"content":{"64":{"position":[[553,4]]},"65":{"position":[[447,4]]}},"keywords":{}}],["hr_datafram",{"_index":2425,"title":{},"content":{"62":{"position":[[1137,13]]}},"keywords":{}}],["hr_df_concat",{"_index":2427,"title":{},"content":{"62":{"position":[[1210,12]]}},"keywords":{}}],["hr_df_concat.index",{"_index":2431,"title":{},"content":{"62":{"position":[[1375,19]]}},"keywords":{}}],["hr_df_concat.reindex(full_daterang",{"_index":2434,"title":{},"content":{"62":{"position":[[1424,36]]}},"keywords":{}}],["hr_df_full",{"_index":2433,"title":{},"content":{"62":{"position":[[1411,10]]}},"keywords":{}}],["hr_df_full.index",{"_index":2438,"title":{},"content":{"62":{"position":[[1554,17]]}},"keywords":{}}],["hr_df_full.index.day",{"_index":2469,"title":{},"content":{"64":{"position":[[885,21]]},"65":{"position":[[1730,21]]}},"keywords":{}}],["hr_df_full['value'].mean",{"_index":2484,"title":{},"content":{"64":{"position":[[1486,26]]}},"keywords":{}}],["hr_df_full['value'].sum",{"_index":2439,"title":{},"content":{"62":{"position":[[1576,27]]},"64":{"position":[[795,25]]}},"keywords":{}}],["hr_df_full[(hr_df_full.index.month",{"_index":2468,"title":{},"content":{"64":{"position":[[838,34]]},"65":{"position":[[1683,34]]}},"keywords":{}}],["hr_q",{"_index":2459,"title":{},"content":{"64":{"position":[[538,4]]},"65":{"position":[[432,4]]}},"keywords":{}}],["hr_respons",{"_index":2413,"title":{},"content":{"62":{"position":[[757,12],[1196,13]]}},"keywords":{}}],["href",{"_index":896,"title":{},"content":{"22":{"position":[[510,4],[547,7]]}},"keywords":{}}],["hrqhr_qhrq",{"_index":2462,"title":{},"content":{"64":{"position":[[605,12]]},"65":{"position":[[501,12]]}},"keywords":{}}],["hrq⋅n−hrd⋅(n−m)\\begin{equ",{"_index":2458,"title":{},"content":{"64":{"position":[[505,32]]},"65":{"position":[[399,32]]}},"keywords":{}}],["html",{"_index":878,"title":{},"content":{"22":{"position":[[27,4]]},"125":{"position":[[3852,4]]}},"keywords":{}}],["html.parser",{"_index":3198,"title":{},"content":{"93":{"position":[[1270,11]]}},"keywords":{}}],["html5ever",{"_index":3304,"title":{},"content":{"95":{"position":[[124,9]]}},"keywords":{}}],["htmlparser",{"_index":3199,"title":{},"content":{"93":{"position":[[1289,10]]}},"keywords":{}}],["http://itouchmap.com/latlong.html",{"_index":1449,"title":{},"content":{"30":{"position":[[8436,33]]}},"keywords":{}}],["http://math.stackexchange.com/a/1710392/320784",{"_index":2679,"title":{},"content":{"76":{"position":[[295,46]]}},"keywords":{}}],["http://matplotlib.org/examples/pylab_examples/finance_demo.html",{"_index":2862,"title":{},"content":{"88":{"position":[[992,63]]}},"keywords":{}}],["http://www.streetinsider.com/ec_earnings.php?q",{"_index":3231,"title":{},"content":{"93":{"position":[[2485,52]]}},"keywords":{}}],["http://www.treasury.gov/resourc",{"_index":490,"title":{},"content":{"10":{"position":[[207,32]]}},"keywords":{}}],["https://api.fitbit.com/1/us",{"_index":2411,"title":{},"content":{"62":{"position":[[684,31]]}},"keywords":{}}],["https://doc.rust",{"_index":5139,"title":{},"content":{"186":{"position":[[232,16]]}},"keywords":{}}],["https://github.com/rust",{"_index":3744,"title":{},"content":{"113":{"position":[[1185,23]]}},"keywords":{}}],["https://github.com/speic",{"_index":4073,"title":{},"content":{"125":{"position":[[3059,25]]}},"keywords":{}}],["https://www.fitbit.com/oauth2/author",{"_index":2374,"title":{},"content":{"61":{"position":[[1527,41]]}},"keywords":{}}],["huge",{"_index":799,"title":{},"content":{"20":{"position":[[974,4]]},"24":{"position":[[469,4]]},"25":{"position":[[194,4]]},"40":{"position":[[2253,4]]},"46":{"position":[[227,4]]},"93":{"position":[[201,4]]},"101":{"position":[[60,5],[98,5]]},"106":{"position":[[380,4]]},"125":{"position":[[3378,4],[4558,4]]},"161":{"position":[[643,4]]},"172":{"position":[[1416,4]]},"174":{"position":[[785,4]]}},"keywords":{}}],["huh",{"_index":3433,"title":{},"content":{"97":{"position":[[6125,4]]}},"keywords":{}}],["human",{"_index":2546,"title":{},"content":{"66":{"position":[[534,6]]},"104":{"position":[[1654,6]]},"123":{"position":[[756,5]]},"176":{"position":[[974,6],[1044,6]]},"189":{"position":[[1011,6]]}},"keywords":{}}],["humansvszombi",{"_index":2256,"title":{},"content":{"53":{"position":[[1211,16]]}},"keywords":{}}],["humantimecould",{"_index":3998,"title":{},"content":{"124":{"position":[[459,14]]}},"keywords":{}}],["hype",{"_index":2207,"title":{},"content":{"53":{"position":[[368,5]]}},"keywords":{}}],["hyper",{"_index":3301,"title":{},"content":{"95":{"position":[[59,5]]},"97":{"position":[[2282,5]]},"173":{"position":[[897,5]]}},"keywords":{}}],["hypervisor",{"_index":4990,"title":{},"content":{"174":{"position":[[859,10]]}},"keywords":{}}],["i'd",{"_index":1134,"title":{},"content":{"25":{"position":[[35,3]]},"28":{"position":[[420,3]]},"32":{"position":[[688,3]]},"38":{"position":[[1015,3]]},"41":{"position":[[219,3]]},"43":{"position":[[1032,3]]},"44":{"position":[[1893,3]]},"50":{"position":[[118,3]]},"54":{"position":[[116,3]]},"61":{"position":[[2027,3]]},"65":{"position":[[107,3]]},"96":{"position":[[431,3]]},"124":{"position":[[135,3]]},"125":{"position":[[10231,3]]}},"keywords":{}}],["i'll",{"_index":1189,"title":{},"content":{"26":{"position":[[897,4]]},"29":{"position":[[368,4]]},"30":{"position":[[7997,4]]},"32":{"position":[[1357,4]]},"38":{"position":[[771,4]]},"49":{"position":[[657,4]]},"50":{"position":[[240,4]]},"51":{"position":[[1,4]]},"53":{"position":[[1722,4]]},"61":{"position":[[691,4],[1309,4]]},"62":{"position":[[110,4],[273,4]]},"63":{"position":[[158,4]]},"64":{"position":[[1391,4]]},"65":{"position":[[1485,4]]},"74":{"position":[[894,4]]},"100":{"position":[[110,4]]},"103":{"position":[[76,4]]},"104":{"position":[[78,4]]},"108":{"position":[[253,4]]},"112":{"position":[[1081,4]]},"118":{"position":[[0,4]]},"122":{"position":[[186,4]]},"125":{"position":[[2500,4]]},"132":{"position":[[980,4]]},"160":{"position":[[4357,4]]},"161":{"position":[[301,4]]},"170":{"position":[[421,4]]},"194":{"position":[[773,4]]},"198":{"position":[[146,4]]}},"keywords":{}}],["i'm",{"_index":233,"title":{},"content":{"4":{"position":[[234,3]]},"7":{"position":[[1065,3]]},"22":{"position":[[2702,3]]},"24":{"position":[[459,3]]},"25":{"position":[[184,3]]},"30":{"position":[[327,3],[691,3],[8212,3]]},"35":{"position":[[281,3],[466,3]]},"39":{"position":[[395,3]]},"41":{"position":[[8,3]]},"43":{"position":[[406,3]]},"45":{"position":[[411,3],[572,3]]},"46":{"position":[[321,3],[354,3]]},"50":{"position":[[1,3]]},"51":{"position":[[996,3],[1915,3]]},"53":{"position":[[192,3],[581,3],[1959,4]]},"55":{"position":[[1,3],[73,3]]},"57":{"position":[[468,3]]},"58":{"position":[[7,3],[371,3],[754,3]]},"63":{"position":[[61,3]]},"64":{"position":[[1214,3],[1419,3]]},"65":{"position":[[1521,3],[2263,3]]},"73":{"position":[[261,3]]},"86":{"position":[[221,3]]},"95":{"position":[[512,3]]},"96":{"position":[[274,3]]},"97":{"position":[[227,3],[3122,3],[5206,3]]},"98":{"position":[[1136,3]]},"100":{"position":[[1,3]]},"102":{"position":[[418,3],[1520,3]]},"113":{"position":[[149,3],[2481,3]]},"117":{"position":[[521,3]]},"118":{"position":[[222,3]]},"121":{"position":[[95,3],[466,3],[1454,3],[2566,3]]},"122":{"position":[[848,3],[916,3],[996,3]]},"123":{"position":[[72,3],[322,3],[544,3],[664,3],[963,3]]},"124":{"position":[[588,3],[768,3],[818,3]]},"125":{"position":[[1794,3],[1889,3],[1921,3],[2032,3],[2636,3],[2685,3],[2845,3],[9183,3],[10871,3],[11739,3]]},"127":{"position":[[12,3]]},"132":{"position":[[373,3]]},"148":{"position":[[406,3]]},"150":{"position":[[977,3]]},"161":{"position":[[116,3],[408,3],[1641,3],[1710,3]]},"163":{"position":[[419,3]]}},"keywords":{}}],["i'v",{"_index":256,"title":{},"content":{"4":{"position":[[741,4]]},"30":{"position":[[367,4],[856,4]]},"43":{"position":[[179,4]]},"51":{"position":[[3432,4]]},"52":{"position":[[1,4]]},"53":{"position":[[1415,4]]},"55":{"position":[[153,4]]},"57":{"position":[[544,4]]},"58":{"position":[[212,4],[454,4],[491,4]]},"60":{"position":[[1,4]]},"61":{"position":[[243,4],[2073,4]]},"64":{"position":[[71,4],[1125,4]]},"65":{"position":[[55,4],[2506,4]]},"76":{"position":[[1386,4]]},"91":{"position":[[3821,4]]},"98":{"position":[[539,4]]},"104":{"position":[[1040,4]]},"112":{"position":[[987,4]]},"115":{"position":[[2495,4]]},"118":{"position":[[192,4]]},"121":{"position":[[281,4]]},"122":{"position":[[133,4]]},"124":{"position":[[7,4]]},"130":{"position":[[588,4]]},"132":{"position":[[444,4]]},"150":{"position":[[133,4]]},"161":{"position":[[914,4],[1590,4]]},"166":{"position":[[79,4]]}},"keywords":{}}],["i*d",{"_index":1724,"title":{},"content":{"39":{"position":[[597,4]]}},"keywords":{}}],["i*tick_width",{"_index":428,"title":{},"content":{"7":{"position":[[1016,13]]}},"keywords":{}}],["i.",{"_index":1898,"title":{},"content":{"44":{"position":[[105,5]]},"74":{"position":[[1369,5]]},"75":{"position":[[472,4]]},"91":{"position":[[3935,5]]},"97":{"position":[[5655,5]]},"113":{"position":[[2011,5]]}},"keywords":{}}],["i/o",{"_index":4957,"title":{},"content":{"173":{"position":[[1042,3]]}},"keywords":{}}],["i32",{"_index":4268,"title":{},"content":{"128":{"position":[[1124,4]]}},"keywords":{}}],["i64",{"_index":5278,"title":{},"content":{"193":{"position":[[924,4],[932,4],[1100,3],[2229,4],[2237,4],[2504,3],[3195,4],[3203,4],[3275,3],[3589,3]]}},"keywords":{}}],["i=1:(n",{"_index":395,"title":{},"content":{"7":{"position":[[416,6]]}},"keywords":{}}],["i=1:length(invest",{"_index":1646,"title":{},"content":{"34":{"position":[[2781,24]]}},"keywords":{}}],["i=1:m",{"_index":584,"title":{},"content":{"13":{"position":[[1411,6]]},"14":{"position":[[2483,6]]},"15":{"position":[[2155,6]]}},"keywords":{}}],["i=1:num_simul",{"_index":588,"title":{},"content":{"13":{"position":[[1485,19]]},"14":{"position":[[2557,19]]},"15":{"position":[[2229,19]]}},"keywords":{}}],["i=1:round(num_tick",{"_index":426,"title":{},"content":{"7":{"position":[[971,20]]}},"keywords":{}}],["i=1:t",{"_index":518,"title":{},"content":{"11":{"position":[[408,5]]},"12":{"position":[[368,5]]},"13":{"position":[[760,5],[1305,6]]},"14":{"position":[[1617,5],[2377,6]]},"15":{"position":[[1004,5],[2049,6]]}},"keywords":{}}],["i=1:year",{"_index":478,"title":{},"content":{"9":{"position":[[810,10]]}},"keywords":{}}],["ic⋅i",{"_index":551,"title":{},"content":{"13":{"position":[[331,4]]}},"keywords":{}}],["id",{"_index":203,"title":{},"content":{"3":{"position":[[1283,3]]},"43":{"position":[[568,5]]},"108":{"position":[[877,2]]},"163":{"position":[[1177,2]]}},"keywords":{}}],["id.1",{"_index":1871,"title":{},"content":{"43":{"position":[[574,8]]}},"keywords":{}}],["idea",{"_index":1892,"title":{},"content":{"43":{"position":[[1421,4]]},"54":{"position":[[50,5]]},"57":{"position":[[425,4]]},"90":{"position":[[5157,4]]},"101":{"position":[[439,4]]},"102":{"position":[[188,4],[957,4],[1429,4]]},"106":{"position":[[161,4]]},"112":{"position":[[1129,4]]},"125":{"position":[[11729,4]]},"127":{"position":[[555,4]]},"129":{"position":[[1214,4]]},"132":{"position":[[588,5],[913,4]]},"160":{"position":[[2904,4]]}},"keywords":{}}],["ideal",{"_index":1689,"title":{},"content":{"38":{"position":[[158,8]]},"73":{"position":[[741,8]]}},"keywords":{}}],["ident",{"_index":5243,"title":{},"content":{"189":{"position":[[1953,9]]}},"keywords":{}}],["identifi",{"_index":2482,"title":{},"content":{"64":{"position":[[1446,11]]},"104":{"position":[[1064,10]]}},"keywords":{}}],["identifywhere/when",{"_index":5048,"title":{},"content":{"176":{"position":[[866,18]]}},"keywords":{}}],["idiomat",{"_index":3877,"title":{},"content":{"121":{"position":[[261,9]]}},"keywords":{}}],["idiot",{"_index":2034,"title":{},"content":{"46":{"position":[[475,6]]}},"keywords":{}}],["iex",{"_index":4796,"title":{},"content":{"163":{"position":[[2203,3]]},"167":{"position":[[230,3]]},"168":{"position":[[79,3]]}},"keywords":{}}],["ifnum_alloc",{"_index":4897,"title":{},"content":{"172":{"position":[[219,11]]}},"keywords":{}}],["ignor",{"_index":138,"title":{},"content":{"3":{"position":[[76,7]]},"28":{"position":[[1548,6],[3334,6]]},"51":{"position":[[1032,6]]},"65":{"position":[[1630,6]]},"66":{"position":[[132,7]]},"189":{"position":[[1025,7]]}},"keywords":{}}],["ignore.we'l",{"_index":4704,"title":{},"content":{"160":{"position":[[3524,12]]}},"keywords":{}}],["iii",{"_index":552,"title":{},"content":{"13":{"position":[[341,3]]},"32":{"position":[[650,3]]}},"keywords":{}}],["iiicic_ici",{"_index":1523,"title":{},"content":{"32":{"position":[[524,11]]}},"keywords":{}}],["iiidid_idi",{"_index":1524,"title":{},"content":{"32":{"position":[[574,11]]}},"keywords":{}}],["illeg",{"_index":5065,"title":{},"content":{"179":{"position":[[139,8]]}},"keywords":{}}],["illustr",{"_index":479,"title":{"10":{"position":[[0,12]]}},"content":{},"keywords":{}}],["imagin",{"_index":5354,"title":{},"content":{"197":{"position":[[1453,7]]}},"keywords":{}}],["imit",{"_index":2066,"title":{},"content":{"50":{"position":[[175,7]]}},"keywords":{}}],["imitatemor",{"_index":4220,"title":{},"content":{"125":{"position":[[11639,11]]}},"keywords":{}}],["immedi",{"_index":2613,"title":{},"content":{"72":{"position":[[196,11],[700,11]]},"189":{"position":[[1849,11]]},"193":{"position":[[1109,11]]},"196":{"position":[[761,11],[1148,11]]}},"keywords":{}}],["immut",{"_index":3724,"title":{},"content":{"112":{"position":[[1444,9]]},"136":{"position":[[679,9],[832,10]]},"179":{"position":[[196,9],[463,9]]},"186":{"position":[[384,10]]}},"keywords":{}}],["imp\\sigma_{imp}σimp",{"_index":339,"title":{},"content":{"6":{"position":[[534,21]]}},"keywords":{}}],["impact",{"_index":1702,"title":{},"content":{"38":{"position":[[1052,6]]},"122":{"position":[[91,7]]},"143":{"position":[[484,7]]},"172":{"position":[[98,8],[1421,7]]}},"keywords":{}}],["impecc",{"_index":2282,"title":{},"content":{"53":{"position":[[1821,10]]}},"keywords":{}}],["impl",{"_index":3402,"title":{"129":{"position":[[0,4]]}},"content":{"97":{"position":[[3604,4]]},"112":{"position":[[1490,4],[1587,4]]},"129":{"position":[[151,4],[336,4],[1451,4]]},"147":{"position":[[215,4]]},"152":{"position":[[1275,4]]},"156":{"position":[[1358,4]]},"184":{"position":[[534,4]]},"185":{"position":[[463,4]]},"196":{"position":[[956,4]]},"197":{"position":[[76,4],[410,4],[558,4]]}},"keywords":{}}],["implem",{"_index":5358,"title":{},"content":{"198":{"position":[[258,11]]}},"keywords":{}}],["implement",{"_index":162,"title":{},"content":{"3":{"position":[[557,11]]},"40":{"position":[[752,12]]},"97":{"position":[[3272,10],[3470,9],[4820,9]]},"116":{"position":[[3048,9]]},"117":{"position":[[30,11]]},"121":{"position":[[2511,14]]},"125":{"position":[[588,15]]},"129":{"position":[[96,15]]},"153":{"position":[[296,12]]},"157":{"position":[[618,12]]},"166":{"position":[[775,14]]},"169":{"position":[[250,15]]},"182":{"position":[[596,9]]},"185":{"position":[[64,9],[240,9],[317,9]]},"196":{"position":[[720,15]]},"197":{"position":[[852,14],[907,10]]},"198":{"position":[[720,9],[766,9],[814,9],[1074,11]]}},"keywords":{}}],["impli",{"_index":315,"title":{},"content":{"6":{"position":[[252,7],[469,7],[575,7]]},"9":{"position":[[191,7],[673,7]]},"15":{"position":[[83,8]]},"45":{"position":[[3362,5]]},"46":{"position":[[242,7]]},"74":{"position":[[430,7]]},"91":{"position":[[4668,7]]},"103":{"position":[[1631,7]]}},"keywords":{}}],["implic",{"_index":1563,"title":{"33":{"position":[[12,13]]}},"content":{"160":{"position":[[3303,12]]},"173":{"position":[[2031,13]]},"195":{"position":[[891,12]]}},"keywords":{}}],["implicit",{"_index":2367,"title":{},"content":{"61":{"position":[[1360,8]]},"198":{"position":[[944,8]]}},"keywords":{}}],["implicitli",{"_index":5169,"title":{},"content":{"188":{"position":[[1367,10]]}},"keywords":{}}],["import",{"_index":208,"title":{},"content":{"3":{"position":[[1360,6]]},"4":{"position":[[160,10],[416,9]]},"17":{"position":[[74,6],[89,6],[117,6]]},"20":{"position":[[1002,6],[1041,6]]},"24":{"position":[[3298,9]]},"30":{"position":[[114,6],[171,6],[197,6],[217,6],[250,6],[266,6],[8318,6],[8353,6],[8367,6],[8397,6],[10054,6]]},"33":{"position":[[353,9]]},"39":{"position":[[414,6],[433,6],[453,6],[497,6],[3081,6]]},"43":{"position":[[267,6],[287,6],[306,6],[433,6]]},"44":{"position":[[586,6]]},"45":{"position":[[1926,6],[1971,6]]},"47":{"position":[[78,6]]},"51":{"position":[[83,6],[101,6],[432,6],[1076,6],[1625,6],[3587,6]]},"58":{"position":[[89,9]]},"60":{"position":[[138,6],[209,6]]},"61":{"position":[[1500,6]]},"62":{"position":[[387,6],[408,6],[442,6]]},"65":{"position":[[2301,6]]},"66":{"position":[[716,9]]},"68":{"position":[[402,6],[421,6],[441,6],[801,9]]},"73":{"position":[[593,9]]},"74":{"position":[[1276,9]]},"76":{"position":[[127,6],[157,6]]},"78":{"position":[[99,6]]},"88":{"position":[[264,6],[282,6],[336,6],[376,6],[422,6],[480,6],[508,6],[524,6]]},"90":{"position":[[176,6],[195,6],[243,6],[303,6],[342,6]]},"91":{"position":[[1841,6],[1874,6],[1904,6],[4680,9]]},"93":{"position":[[18,9],[1245,6],[1282,6],[1314,6],[1341,6],[1357,6],[1381,6],[1395,6],[1430,6],[1445,6],[3813,6],[3831,6],[3851,6],[3884,6],[3911,6],[3928,6],[3959,6]]},"98":{"position":[[284,9]]},"103":{"position":[[463,6],[490,6],[843,6],[854,6]]},"105":{"position":[[457,6],[473,6]]},"112":{"position":[[291,9]]},"125":{"position":[[3626,9],[10344,9]]},"139":{"position":[[361,9]]},"147":{"position":[[6,9]]},"152":{"position":[[286,9]]},"160":{"position":[[1465,9],[2678,9]]},"161":{"position":[[554,9]]},"166":{"position":[[112,9]]},"170":{"position":[[119,9]]},"173":{"position":[[192,9],[404,9],[455,9]]},"179":{"position":[[162,9]]},"188":{"position":[[2011,6]]},"189":{"position":[[3026,6]]},"190":{"position":[[24,9]]}},"keywords":{}}],["import.meta.url",{"_index":123,"title":{},"content":{"2":{"position":[[740,16]]}},"keywords":{}}],["important"",{"_index":3559,"title":{},"content":{"104":{"position":[[648,15]]}},"keywords":{}}],["importantli",{"_index":2389,"title":{},"content":{"61":{"position":[[2241,12]]}},"keywords":{}}],["imposs",{"_index":1566,"title":{},"content":{"33":{"position":[[97,10]]},"104":{"position":[[1865,10]]},"150":{"position":[[275,10]]},"165":{"position":[[1369,11]]},"178":{"position":[[587,10]]},"179":{"position":[[820,11]]},"190":{"position":[[1030,10]]},"198":{"position":[[457,10]]}},"keywords":{}}],["impress",{"_index":2217,"title":{},"content":{"53":{"position":[[528,10]]},"117":{"position":[[606,10]]}},"keywords":{}}],["improv",{"_index":1986,"title":{},"content":{"45":{"position":[[1751,8]]},"174":{"position":[[142,12]]}},"keywords":{}}],["in_font_tag",{"_index":929,"title":{},"content":{"22":{"position":[[1218,11]]}},"keywords":{}}],["inadvert",{"_index":5011,"title":{},"content":{"175":{"position":[[492,13]]}},"keywords":{}}],["inc",{"_index":3256,"title":{},"content":{"93":{"position":[[3287,7]]}},"keywords":{}}],["incargo.lock",{"_index":4150,"title":{},"content":{"125":{"position":[[7697,13]]}},"keywords":{}}],["inclin",{"_index":4037,"title":{},"content":{"125":{"position":[[1237,8]]}},"keywords":{}}],["includ",{"_index":1349,"title":{},"content":{"30":{"position":[[917,8]]},"51":{"position":[[183,7]]},"65":{"position":[[359,9]]},"90":{"position":[[3255,9],[3358,9]]},"92":{"position":[[1429,8]]},"111":{"position":[[782,9]]},"112":{"position":[[992,8]]},"113":{"position":[[430,9],[641,7]]},"125":{"position":[[2856,9]]},"150":{"position":[[940,8]]},"185":{"position":[[451,8]]},"189":{"position":[[1570,7]]},"197":{"position":[[1236,8]]}},"keywords":{}}],["include!(concat!(env!("out_dir"",{"_index":3736,"title":{},"content":{"113":{"position":[[649,43]]}},"keywords":{}}],["incorrectli",{"_index":163,"title":{},"content":{"3":{"position":[[572,12]]}},"keywords":{}}],["increas",{"_index":1589,"title":{},"content":{"33":{"position":[[1216,9]]},"65":{"position":[[237,10]]},"76":{"position":[[1063,8]]}},"keywords":{}}],["incred",{"_index":1706,"title":{},"content":{"39":{"position":[[18,10]]},"44":{"position":[[942,10],[1859,10]]},"45":{"position":[[115,10]]},"76":{"position":[[694,10]]},"86":{"position":[[513,10]]},"89":{"position":[[462,10]]},"91":{"position":[[4651,11],[4802,10],[5494,10],[5765,10],[5876,11]]},"96":{"position":[[316,10]]},"97":{"position":[[2952,10]]},"98":{"position":[[1087,10]]},"101":{"position":[[153,10]]},"103":{"position":[[2031,10],[2215,10]]},"105":{"position":[[2814,10]]},"121":{"position":[[1859,10]]},"125":{"position":[[10290,10]]},"129":{"position":[[1165,10]]},"130":{"position":[[79,10]]},"150":{"position":[[246,10]]},"161":{"position":[[1421,10]]},"170":{"position":[[39,10]]},"174":{"position":[[442,11]]}},"keywords":{}}],["increment",{"_index":2453,"title":{},"content":{"64":{"position":[[295,10]]}},"keywords":{}}],["incur",{"_index":1688,"title":{},"content":{"38":{"position":[[123,5],[1164,5]]}},"keywords":{}}],["inde",{"_index":1838,"title":{},"content":{"40":{"position":[[3423,7]]},"45":{"position":[[3441,6]]},"83":{"position":[[50,6]]},"86":{"position":[[685,7]]},"103":{"position":[[1864,6]]}},"keywords":{}}],["indefinit",{"_index":3984,"title":{},"content":{"123":{"position":[[822,13]]}},"keywords":{}}],["indent",{"_index":3912,"title":{},"content":{"121":{"position":[[1939,11]]}},"keywords":{}}],["index",{"_index":992,"title":{},"content":{"23":{"position":[[104,6]]},"24":{"position":[[1993,5]]},"25":{"position":[[1717,5]]},"39":{"position":[[382,5]]},"76":{"position":[[631,5]]},"90":{"position":[[814,5],[2199,5]]}},"keywords":{}}],["index'",{"_index":1017,"title":{},"content":{"24":{"position":[[107,7],[172,7]]}},"keywords":{}}],["index=b_class",{"_index":1918,"title":{},"content":{"44":{"position":[[757,14]]}},"keywords":{}}],["index_dict",{"_index":1071,"title":{},"content":{"24":{"position":[[1651,10]]},"25":{"position":[[1371,10]]}},"keywords":{}}],["index_dict[index",{"_index":1082,"title":{},"content":{"24":{"position":[[2084,18]]},"25":{"position":[[1808,18]]}},"keywords":{}}],["index_dict_dt",{"_index":1051,"title":{},"content":{"24":{"position":[[1090,13]]},"25":{"position":[[810,13]]}},"keywords":{}}],["index_dt",{"_index":1061,"title":{},"content":{"24":{"position":[[1248,8],[1310,8]]},"25":{"position":[[968,8],[1030,8]]}},"keywords":{}}],["index_valu",{"_index":1065,"title":{},"content":{"24":{"position":[[1330,11],[1386,11],[1433,11],[1478,11]]},"25":{"position":[[1050,11],[1106,11],[1153,11],[1198,11]]}},"keywords":{}}],["indic",{"_index":990,"title":{},"content":{"23":{"position":[[78,7]]},"24":{"position":[[1799,7],[2002,8],[3461,8],[3511,8]]},"25":{"position":[[1523,7],[1726,8]]},"26":{"position":[[522,8],[613,7]]},"41":{"position":[[139,8]]},"51":{"position":[[1312,7],[1410,8]]},"165":{"position":[[1265,8]]},"188":{"position":[[873,9]]},"192":{"position":[[708,9]]}},"keywords":{}}],["individu",{"_index":1952,"title":{},"content":{"44":{"position":[[1770,10]]},"71":{"position":[[1082,10]]},"74":{"position":[[448,10]]},"172":{"position":[[119,10]]}},"keywords":{}}],["induc",{"_index":824,"title":{},"content":{"20":{"position":[[1638,6]]}},"keywords":{}}],["industri",{"_index":1,"title":{"0":{"position":[[12,10]]}},"content":{"4":{"position":[[955,10]]},"23":{"position":[[121,11]]},"93":{"position":[[911,12]]},"174":{"position":[[1306,10]]},"176":{"position":[[41,9]]}},"keywords":{}}],["ineffici",{"_index":3118,"title":{},"content":{"91":{"position":[[2231,12]]}},"keywords":{}}],["ineq",{"_index":839,"title":{},"content":{"20":{"position":[[2079,7],[2126,7],[2169,7]]}},"keywords":{}}],["infer",{"_index":5300,"title":{},"content":{"193":{"position":[[2063,5],[2158,10]]}},"keywords":{}}],["infin",{"_index":829,"title":{},"content":{"20":{"position":[[1709,8]]}},"keywords":{}}],["influenc",{"_index":1853,"title":{},"content":{"41":{"position":[[507,9]]}},"keywords":{}}],["info",{"_index":3818,"title":{},"content":{"117":{"position":[[461,4]]}},"keywords":{}}],["inform",{"_index":1020,"title":{},"content":{"24":{"position":[[365,11]]},"35":{"position":[[304,11]]},"45":{"position":[[3566,6]]},"60":{"position":[[166,11]]},"61":{"position":[[1972,11]]},"64":{"position":[[1458,12]]},"83":{"position":[[506,11]]},"88":{"position":[[2188,12]]},"90":{"position":[[115,11]]},"97":{"position":[[662,11]]},"104":{"position":[[258,11],[407,11]]},"136":{"position":[[782,12]]},"155":{"position":[[890,12]]}},"keywords":{}}],["infrastructur",{"_index":5017,"title":{},"content":{"175":{"position":[[742,14]]}},"keywords":{}}],["ingest",{"_index":3305,"title":{},"content":{"95":{"position":[[147,6]]}},"keywords":{}}],["inherit",{"_index":4237,"title":{},"content":{"127":{"position":[[866,7],[1419,8]]}},"keywords":{}}],["inhow",{"_index":4655,"title":{},"content":{"160":{"position":[[382,5]]}},"keywords":{}}],["init",{"_index":1623,"title":{},"content":{"34":{"position":[[1619,5],[1811,6]]},"39":{"position":[[1030,5]]},"109":{"position":[[177,4]]},"173":{"position":[[674,4]]},"186":{"position":[[308,5],[365,6],[544,4]]}},"keywords":{}}],["init.call_onc",{"_index":5141,"title":{},"content":{"186":{"position":[[441,17],[601,17]]}},"keywords":{}}],["initi",{"_index":389,"title":{"180":{"position":[[0,15]]},"184":{"position":[[0,15]]}},"content":{"7":{"position":[[312,7]]},"8":{"position":[[79,7]]},"14":{"position":[[207,7]]},"30":{"position":[[7820,7]]},"34":{"position":[[3532,7]]},"39":{"position":[[2176,8]]},"44":{"position":[[1023,7]]},"45":{"position":[[624,7]]},"47":{"position":[[24,7]]},"91":{"position":[[4112,7]]},"178":{"position":[[285,14]]},"179":{"position":[[1472,11]]},"183":{"position":[[788,14]]},"184":{"position":[[24,15],[61,12],[826,10]]},"185":{"position":[[408,12]]}},"keywords":{}}],["initialization"",{"_index":4561,"title":{},"content":{"155":{"position":[[344,21]]}},"keywords":{}}],["inlin",{"_index":1721,"title":{},"content":{"39":{"position":[[528,6]]},"43":{"position":[[350,6]]},"51":{"position":[[1669,6]]},"68":{"position":[[485,6]]},"88":{"position":[[556,6]]},"113":{"position":[[242,7]]},"152":{"position":[[240,9]]},"159":{"position":[[796,11]]},"181":{"position":[[593,6]]},"193":{"position":[[2094,9],[2360,8],[2388,6]]}},"keywords":{}}],["inline(alway",{"_index":5304,"title":{},"content":{"193":{"position":[[2438,17]]}},"keywords":{}}],["inner",{"_index":5071,"title":{},"content":{"179":{"position":[[532,5]]}},"keywords":{}}],["innov",{"_index":4050,"title":{},"content":{"125":{"position":[[1583,11],[10742,10]]},"160":{"position":[[3863,11]]}},"keywords":{}}],["inopportun",{"_index":4507,"title":{},"content":{"150":{"position":[[889,11]]}},"keywords":{}}],["inopt",{"_index":5308,"title":{},"content":{"194":{"position":[[49,8]]}},"keywords":{}}],["input",{"_index":2051,"title":{},"content":{"49":{"position":[[10,5]]},"50":{"position":[[14,5]]},"97":{"position":[[2410,6]]},"163":{"position":[[2026,11]]}},"keywords":{}}],["input"",{"_index":3866,"title":{},"content":{"120":{"position":[[1061,11]]}},"keywords":{}}],["inrust",{"_index":5051,"title":{},"content":{"176":{"position":[[1214,7]]}},"keywords":{}}],["insid",{"_index":3767,"title":{},"content":{"115":{"position":[[477,6]]},"188":{"position":[[612,6]]}},"keywords":{}}],["insight",{"_index":1118,"title":{},"content":{"24":{"position":[[2922,9]]},"104":{"position":[[1599,8]]}},"keywords":{}}],["inspect",{"_index":4417,"title":{},"content":{"139":{"position":[[307,10]]}},"keywords":{}}],["inspir",{"_index":2830,"title":{},"content":{"86":{"position":[[706,8]]}},"keywords":{}}],["instal",{"_index":106,"title":{"108":{"position":[[8,10]]}},"content":{"2":{"position":[[449,10]]},"3":{"position":[[1272,7]]},"108":{"position":[[241,10],[285,12],[430,7],[496,7],[520,7]]},"113":{"position":[[10,7]]},"125":{"position":[[3138,7],[7644,9]]},"134":{"position":[[17,9]]},"176":{"position":[[339,9]]}},"keywords":{}}],["instanc",{"_index":3647,"title":{},"content":{"105":{"position":[[2562,9]]},"127":{"position":[[484,8]]},"129":{"position":[[899,8],[955,8],[1103,8],[1322,9],[1714,9],[1837,9],[1904,9],[2091,8],[2730,8]]},"130":{"position":[[306,8]]}},"keywords":{}}],["instantiatestream",{"_index":4110,"title":{},"content":{"125":{"position":[[5163,20],[5452,20]]}},"keywords":{}}],["instead",{"_index":89,"title":{},"content":{"2":{"position":[[219,8]]},"4":{"position":[[171,8]]},"30":{"position":[[9536,7]]},"34":{"position":[[3671,8]]},"45":{"position":[[1012,8]]},"74":{"position":[[1248,8]]},"86":{"position":[[282,7]]},"88":{"position":[[710,8],[2371,7]]},"92":{"position":[[64,8],[82,7]]},"93":{"position":[[4125,8]]},"97":{"position":[[843,8],[2619,8],[2687,7],[5679,7],[5704,7]]},"101":{"position":[[206,8]]},"125":{"position":[[1643,8],[5078,8]]},"129":{"position":[[914,7]]},"132":{"position":[[971,8]]},"135":{"position":[[299,8]]},"139":{"position":[[296,7]]},"152":{"position":[[203,8],[901,8]]},"160":{"position":[[1080,8]]},"172":{"position":[[2631,7]]},"183":{"position":[[776,8]]},"189":{"position":[[951,7]]},"194":{"position":[[145,8],[778,7]]}},"keywords":{}}],["instinct",{"_index":4621,"title":{},"content":{"158":{"position":[[188,9]]}},"keywords":{}}],["instruct",{"_index":3070,"title":{},"content":{"90":{"position":[[5308,9]]},"108":{"position":[[298,12]]},"128":{"position":[[984,12]]},"174":{"position":[[331,13]]},"181":{"position":[[185,11],[312,12],[442,11],[618,13]]},"192":{"position":[[618,12],[696,11]]},"193":{"position":[[295,12],[3496,12]]},"195":{"position":[[490,10]]},"196":{"position":[[1088,11],[1232,12],[1422,11],[1643,12],[1714,11],[1845,12]]}},"keywords":{}}],["int",{"_index":4226,"title":{},"content":{"127":{"position":[[226,3],[635,3],[750,3],[1161,3],[1285,3]]},"128":{"position":[[259,3],[272,3]]},"188":{"position":[[3529,3]]},"189":{"position":[[977,5],[1096,4],[1107,4],[1366,4],[1377,4],[3090,4],[3101,4]]},"199":{"position":[[116,3],[191,4],[276,3]]}},"keywords":{}}],["int((array.shape[1",{"_index":2979,"title":{},"content":{"90":{"position":[[898,19],[2283,19]]}},"keywords":{}}],["int(birthday_heartbeat",{"_index":2489,"title":{},"content":{"64":{"position":[[1642,23]]}},"keywords":{}}],["int(date.timestamp",{"_index":1472,"title":{},"content":{"30":{"position":[[8941,21]]}},"keywords":{}}],["int32",{"_index":3697,"title":{},"content":{"110":{"position":[[477,7],[490,7]]},"113":{"position":[[2039,5]]}},"keywords":{}}],["integ",{"_index":4242,"title":{},"content":{"127":{"position":[[1296,7],[1404,7]]},"193":{"position":[[949,7]]}},"keywords":{}}],["integer.valueof(x",{"_index":4243,"title":{},"content":{"127":{"position":[[1308,19]]}},"keywords":{}}],["integr",{"_index":293,"title":{},"content":{"4":{"position":[[1378,9]]},"101":{"position":[[846,9]]},"188":{"position":[[106,10]]}},"keywords":{}}],["intend",{"_index":1679,"title":{},"content":{"36":{"position":[[85,8]]},"55":{"position":[[133,8]]},"86":{"position":[[646,8]]},"90":{"position":[[87,7],[5134,8]]},"97":{"position":[[2737,7]]},"110":{"position":[[103,8]]},"125":{"position":[[2063,8]]},"160":{"position":[[3645,9]]},"165":{"position":[[124,7]]}},"keywords":{}}],["intent",{"_index":3573,"title":{},"content":{"104":{"position":[[2009,10]]},"132":{"position":[[53,9]]}},"keywords":{}}],["interact",{"_index":3863,"title":{},"content":{"120":{"position":[[891,8]]},"152":{"position":[[225,9]]},"160":{"position":[[134,8],[2113,11]]},"172":{"position":[[746,11],[952,9]]},"173":{"position":[[121,9]]},"188":{"position":[[467,9]]},"190":{"position":[[282,11]]}},"keywords":{}}],["interest",{"_index":499,"title":{"33":{"position":[[0,11]]},"40":{"position":[[12,11]]}},"content":{"10":{"position":[[388,8]]},"24":{"position":[[2904,12]]},"25":{"position":[[2725,11]]},"28":{"position":[[107,10],[427,10],[526,11]]},"30":{"position":[[695,10],[7910,11]]},"32":{"position":[[144,11]]},"33":{"position":[[71,11]]},"40":{"position":[[892,12],[1200,11],[2104,11],[3083,11],[3210,11]]},"41":{"position":[[226,10],[590,11]]},"44":{"position":[[1900,10]]},"45":{"position":[[3286,11]]},"54":{"position":[[38,11],[123,10]]},"57":{"position":[[244,10]]},"58":{"position":[[887,11]]},"59":{"position":[[200,10]]},"69":{"position":[[98,11]]},"72":{"position":[[255,11]]},"74":{"position":[[306,11]]},"89":{"position":[[1005,11]]},"93":{"position":[[948,11]]},"95":{"position":[[275,11]]},"102":{"position":[[422,10]]},"103":{"position":[[2264,11]]},"104":{"position":[[593,11],[1587,11],[2029,11]]},"106":{"position":[[959,11]]},"117":{"position":[[78,10]]},"124":{"position":[[382,11]]},"125":{"position":[[2126,11],[9713,10]]},"129":{"position":[[296,11],[456,11],[1202,11]]},"148":{"position":[[548,10]]},"156":{"position":[[1019,11]]},"159":{"position":[[23,11]]},"163":{"position":[[2163,12],[2343,10]]},"176":{"position":[[238,10]]},"178":{"position":[[237,11]]},"199":{"position":[[468,11]]}},"keywords":{}}],["interestingli",{"_index":3875,"title":{},"content":{"121":{"position":[[168,14]]},"195":{"position":[[99,13]]}},"keywords":{}}],["interfac",{"_index":4146,"title":{},"content":{"125":{"position":[[7297,9]]},"163":{"position":[[1167,9]]},"174":{"position":[[997,11]]}},"keywords":{}}],["interface_id",{"_index":4785,"title":{},"content":{"163":{"position":[[1870,13]]}},"keywords":{}}],["interior",{"_index":5076,"title":{"186":{"position":[[0,8]]}},"content":{"179":{"position":[[797,8]]},"186":{"position":[[132,8],[432,8],[532,8]]}},"keywords":{}}],["intermedi",{"_index":5281,"title":{},"content":{"193":{"position":[[1177,12]]}},"keywords":{}}],["internet",{"_index":2386,"title":{},"content":{"61":{"position":[[2062,10]]},"97":{"position":[[2841,9]]}},"keywords":{}}],["interpol",{"_index":495,"title":{},"content":{"10":{"position":[[320,13]]}},"keywords":{}}],["interpolation)μ\\mu",{"_index":330,"title":{},"content":{"6":{"position":[[419,19]]}},"keywords":{}}],["interpret",{"_index":3127,"title":{},"content":{"91":{"position":[[2548,14]]},"92":{"position":[[360,14]]},"188":{"position":[[671,11]]}},"keywords":{}}],["interrupt",{"_index":4940,"title":{},"content":{"173":{"position":[[155,10],[873,11],[1603,11],[1622,10],[1814,10],[1867,10]]}},"keywords":{}}],["interv",{"_index":3022,"title":{},"content":{"90":{"position":[[3303,8]]}},"keywords":{}}],["interview",{"_index":4501,"title":{},"content":{"150":{"position":[[718,12]]}},"keywords":{}}],["interweb",{"_index":3303,"title":{},"content":{"95":{"position":[[113,10]]}},"keywords":{}}],["intimid",{"_index":3788,"title":{},"content":{"115":{"position":[[2576,13]]}},"keywords":{}}],["intowhil",{"_index":4091,"title":{},"content":{"125":{"position":[[4126,9]]}},"keywords":{}}],["intraday",{"_index":2398,"title":{},"content":{"62":{"position":[[237,8]]}},"keywords":{}}],["intraday']['dataset",{"_index":2420,"title":{},"content":{"62":{"position":[[1005,22]]}},"keywords":{}}],["introduc",{"_index":628,"title":{},"content":{"14":{"position":[[122,9]]},"90":{"position":[[42,9]]},"198":{"position":[[479,9]]}},"keywords":{}}],["introduct",{"_index":3462,"title":{"101":{"position":[[8,12]]}},"content":{},"keywords":{}}],["intuit",{"_index":1127,"title":{},"content":{"24":{"position":[[3142,11]]},"32":{"position":[[1045,9]]},"40":{"position":[[2299,12]]},"83":{"position":[[354,6]]}},"keywords":{}}],["invalid",{"_index":3109,"title":{},"content":{"91":{"position":[[1991,7]]},"93":{"position":[[4404,7]]},"115":{"position":[[560,10],[2947,7]]},"129":{"position":[[2532,7]]}},"keywords":{}}],["invalid_ev",{"_index":3145,"title":{},"content":{"91":{"position":[[3404,14]]}},"keywords":{}}],["invalid_events.append((tick",{"_index":3152,"title":{},"content":{"91":{"position":[[4060,30]]}},"keywords":{}}],["invalid_tick",{"_index":3277,"title":{},"content":{"93":{"position":[[4671,15]]}},"keywords":{}}],["invalid_tickers.append(tick",{"_index":3290,"title":{},"content":{"93":{"position":[[5033,30],[5448,30]]}},"keywords":{}}],["invent",{"_index":2295,"title":{},"content":{"55":{"position":[[27,8]]}},"keywords":{}}],["invers",{"_index":1128,"title":{},"content":{"24":{"position":[[3171,7]]},"136":{"position":[[974,9]]}},"keywords":{}}],["invest",{"_index":1518,"title":{"37":{"position":[[24,10]]}},"content":{"32":{"position":[[382,6],[619,6],[778,10],[1198,9],[1312,6],[2099,6],[2191,6]]},"33":{"position":[[278,6],[690,6],[826,7],[861,10],[1063,6],[1117,6],[1176,10]]},"34":{"position":[[31,10],[103,10],[230,6],[323,6],[494,6],[1800,8],[1918,9],[1994,9],[2167,9],[2195,8],[2206,10],[2394,9],[2470,9],[2675,10],[2927,9],[3081,6],[3168,6],[3290,12],[3452,9],[3516,6],[3681,12],[3843,9]]},"35":{"position":[[18,10],[67,6],[253,9]]},"36":{"position":[[126,10]]},"38":{"position":[[150,7],[231,10],[363,10],[546,8],[590,9],[850,8],[940,8],[990,9],[1067,8]]},"39":{"position":[[1053,8],[1135,9],[1208,9],[1378,9],[1406,8],[1498,9],[1616,9],[1689,9],[1736,9],[1963,9],[2125,9]]},"40":{"position":[[3569,11]]}},"keywords":{}}],["invested.sum",{"_index":1738,"title":{},"content":{"39":{"position":[[1546,14]]}},"keywords":{}}],["investig",{"_index":1516,"title":{},"content":{"32":{"position":[[168,12]]}},"keywords":{}}],["investments[1",{"_index":1649,"title":{},"content":{"34":{"position":[[2842,14]]}},"keywords":{}}],["investor",{"_index":3193,"title":{},"content":{"93":{"position":[[732,9]]}},"keywords":{}}],["invoc",{"_index":4447,"title":{},"content":{"144":{"position":[[60,11]]}},"keywords":{}}],["invok",{"_index":3699,"title":{},"content":{"111":{"position":[[183,6]]},"139":{"position":[[972,6]]},"140":{"position":[[264,8]]},"143":{"position":[[568,6]]},"197":{"position":[[1115,8],[1306,8]]}},"keywords":{}}],["involv",{"_index":2092,"title":{},"content":{"51":{"position":[[859,9]]},"155":{"position":[[836,7]]},"174":{"position":[[1040,9]]},"179":{"position":[[780,8]]},"198":{"position":[[848,9]]}},"keywords":{}}],["involvingcomput",{"_index":3852,"title":{},"content":{"120":{"position":[[478,18]]}},"keywords":{}}],["io/isomorph",{"_index":4074,"title":{},"content":{"125":{"position":[[3085,13]]}},"keywords":{}}],["ipython.display",{"_index":705,"title":{},"content":{"17":{"position":[[58,15]]},"103":{"position":[[447,15]]}},"keywords":{}}],["iresult<&[u8",{"_index":4781,"title":{},"content":{"163":{"position":[[1790,21]]}},"keywords":{}}],["iron",{"_index":3300,"title":{},"content":{"95":{"position":[[20,4]]},"97":{"position":[[792,4],[2269,4],[3200,4],[5906,4]]}},"keywords":{}}],["iron'",{"_index":3426,"title":{},"content":{"97":{"position":[[5570,6]]}},"keywords":{}}],["iron::ironerror>",{"_index":3387,"title":{},"content":{"97":{"position":[[1987,19]]}},"keywords":{}}],["iron::request<'r",{"_index":3385,"title":{},"content":{"97":{"position":[[1913,20]]}},"keywords":{}}],["ironresult<response>",{"_index":3330,"title":{},"content":{"96":{"position":[[697,26],[1116,26],[1646,26],[2192,26]]},"97":{"position":[[1527,26],[3683,26]]}},"keywords":{}}],["irrelevant.it'",{"_index":1577,"title":{},"content":{"33":{"position":[[541,15]]}},"keywords":{}}],["irwin",{"_index":2574,"title":{},"content":{"68":{"position":[[972,5]]}},"keywords":{}}],["is_portfolio",{"_index":830,"title":{},"content":{"20":{"position":[[1784,12],[2053,12]]}},"keywords":{}}],["is_profit",{"_index":1619,"title":{},"content":{"34":{"position":[[1408,13]]}},"keywords":{}}],["is_profitable(close_vals[day",{"_index":1631,"title":{},"content":{"34":{"position":[[1887,30],[2363,30]]},"39":{"position":[[1102,28],[1583,28],[1930,28]]}},"keywords":{}}],["is_profitable(current_pric",{"_index":1725,"title":{},"content":{"39":{"position":[[606,28]]}},"keywords":{}}],["is_profitable(open_vals[day",{"_index":1732,"title":{},"content":{"39":{"position":[[1178,29],[1659,29]]}},"keywords":{}}],["is_profitable(open_vals[day+1",{"_index":1633,"title":{},"content":{"34":{"position":[[1962,31],[2438,31]]}},"keywords":{}}],["isaiah26",{"_index":2227,"title":{},"content":{"53":{"position":[[730,9]]}},"keywords":{}}],["isdead",{"_index":4408,"title":{},"content":{"137":{"position":[[197,7]]}},"keywords":{}}],["isessenti",{"_index":4846,"title":{},"content":{"166":{"position":[[630,13]]}},"keywords":{}}],["ishar",{"_index":3248,"title":{},"content":{"93":{"position":[[3065,8]]}},"keywords":{}}],["isn't",{"_index":229,"title":{},"content":{"4":{"position":[[154,5]]},"24":{"position":[[3419,5]]},"25":{"position":[[2766,5]]},"30":{"position":[[7273,5]]},"43":{"position":[[903,5]]},"96":{"position":[[577,5]]},"97":{"position":[[797,5]]},"112":{"position":[[744,5]]},"125":{"position":[[271,5],[4550,5]]},"148":{"position":[[281,5]]},"153":{"position":[[15,5]]},"163":{"position":[[246,5],[2153,5]]},"170":{"position":[[113,5]]},"184":{"position":[[948,5]]},"193":{"position":[[1036,5]]},"199":{"position":[[603,5]]}},"keywords":{}}],["iso_str",{"_index":3122,"title":{},"content":{"91":{"position":[[2345,7]]}},"keywords":{}}],["isol",{"_index":4949,"title":{},"content":{"173":{"position":[[764,8]]}},"keywords":{}}],["isolcpuskernel",{"_index":4946,"title":{},"content":{"173":{"position":[[618,15]]}},"keywords":{}}],["isomorph",{"_index":4001,"title":{"125":{"position":[[0,10]]}},"content":{},"keywords":{}}],["isomorphic_rust/perci",{"_index":4076,"title":{},"content":{"125":{"position":[[3111,21]]}},"keywords":{}}],["isp",{"_index":5005,"title":{},"content":{"175":{"position":[[342,3]]}},"keywords":{}}],["issu",{"_index":100,"title":{"96":{"position":[[0,5]]},"97":{"position":[[0,5]]}},"content":{"2":{"position":[[375,6]]},"15":{"position":[[294,6]]},"22":{"position":[[2990,5]]},"28":{"position":[[1558,5],[1623,6],[2381,7],[2766,7],[3344,5],[3409,6],[4011,5],[4091,6]]},"30":{"position":[[2512,6]]},"34":{"position":[[164,6]]},"38":{"position":[[442,7],[807,5]]},"40":{"position":[[1325,6]]},"44":{"position":[[1085,6]]},"46":{"position":[[82,5],[232,6]]},"53":{"position":[[1794,6]]},"63":{"position":[[15,5]]},"76":{"position":[[1415,6]]},"88":{"position":[[633,6]]},"90":{"position":[[3453,6]]},"91":{"position":[[3277,6],[3813,7],[3867,6]]},"92":{"position":[[1089,6]]},"93":{"position":[[4048,6]]},"97":{"position":[[2474,6]]},"106":{"position":[[537,5]]},"121":{"position":[[1876,6]]},"122":{"position":[[142,6]]},"123":{"position":[[407,5]]},"125":{"position":[[1391,6],[1867,6],[3508,6],[3654,5],[4563,6],[7197,5],[8406,6],[9227,6],[10033,5]]},"158":{"position":[[497,7]]},"160":{"position":[[2023,5]]},"164":{"position":[[792,7],[1532,6]]},"165":{"position":[[497,7]]},"173":{"position":[[1424,6],[1595,6]]},"174":{"position":[[768,6]]},"188":{"position":[[4059,5]]},"199":{"position":[[759,5]]}},"keywords":{}}],["issue/pr",{"_index":3987,"title":{},"content":{"123":{"position":[[1077,8]]}},"keywords":{}}],["issue:what",{"_index":4381,"title":{},"content":{"135":{"position":[[625,10]]}},"keywords":{}}],["issuei",{"_index":4090,"title":{},"content":{"125":{"position":[[4115,6]]}},"keywords":{}}],["issues/pr",{"_index":3970,"title":{},"content":{"123":{"position":[[149,10],[274,10]]}},"keywords":{}}],["it"",{"_index":926,"title":{},"content":{"22":{"position":[[1184,8]]}},"keywords":{}}],["it'",{"_index":624,"title":{},"content":{"14":{"position":[[51,4]]},"24":{"position":[[511,4]]},"25":{"position":[[236,4]]},"29":{"position":[[302,4]]},"30":{"position":[[425,4],[4062,4]]},"32":{"position":[[413,4]]},"33":{"position":[[92,4],[717,4]]},"39":{"position":[[276,4]]},"41":{"position":[[281,4]]},"51":{"position":[[1494,4]]},"62":{"position":[[65,4]]},"63":{"position":[[42,4]]},"66":{"position":[[402,4],[629,4]]},"74":{"position":[[1164,4]]},"83":{"position":[[224,4]]},"89":{"position":[[454,4]]},"90":{"position":[[5336,4]]},"91":{"position":[[360,4]]},"95":{"position":[[426,4]]},"96":{"position":[[835,4]]},"97":{"position":[[576,4],[601,4],[3351,4]]},"98":{"position":[[742,4],[1177,4],[1194,4]]},"101":{"position":[[255,4],[938,4]]},"102":{"position":[[1445,4]]},"103":{"position":[[761,4]]},"104":{"position":[[943,4],[954,4],[1226,4],[1294,4],[1363,4],[1888,4]]},"106":{"position":[[145,4],[324,4],[983,4]]},"109":{"position":[[35,4]]},"111":{"position":[[5,4]]},"112":{"position":[[275,4]]},"113":{"position":[[90,4],[197,4],[1508,4]]},"120":{"position":[[1120,4]]},"121":{"position":[[242,4],[556,4],[1805,4]]},"122":{"position":[[338,4]]},"125":{"position":[[506,4],[3267,4],[8005,4],[9956,4]]},"127":{"position":[[1209,4]]},"129":{"position":[[5,4],[2673,4],[2773,4]]},"134":{"position":[[174,4]]},"135":{"position":[[80,4],[552,4]]},"139":{"position":[[356,4],[683,4],[842,4]]},"142":{"position":[[212,4]]},"145":{"position":[[336,4]]},"147":{"position":[[1,4]]},"148":{"position":[[102,4],[217,4]]},"150":{"position":[[949,4]]},"155":{"position":[[264,4],[1085,4]]},"156":{"position":[[146,4]]},"157":{"position":[[84,4]]},"158":{"position":[[142,4],[397,4]]},"159":{"position":[[67,4]]},"160":{"position":[[1437,4],[1689,4],[3181,4]]},"163":{"position":[[629,4],[2381,4]]},"164":{"position":[[5,4]]},"166":{"position":[[745,4]]},"172":{"position":[[1874,4]]},"173":{"position":[[399,4],[1587,4]]},"175":{"position":[[399,4]]},"178":{"position":[[172,4],[582,4]]},"179":{"position":[[152,4],[1765,4]]},"181":{"position":[[4,4],[572,4]]},"184":{"position":[[1184,4]]},"188":{"position":[[144,4]]},"189":{"position":[[1840,4]]},"190":{"position":[[19,4]]},"193":{"position":[[730,4]]},"195":{"position":[[947,4]]},"196":{"position":[[600,4]]},"197":{"position":[[1440,4]]},"198":{"position":[[452,4],[550,4],[662,4]]},"199":{"position":[[1595,4]]}},"keywords":{}}],["it'sthi",{"_index":4006,"title":{},"content":{"125":{"position":[[87,8]]}},"keywords":{}}],["item",{"_index":4459,"title":{},"content":{"145":{"position":[[293,5]]}},"keywords":{}}],["itemprop",{"_index":938,"title":{},"content":{"22":{"position":[[1423,12]]}},"keywords":{}}],["iter",{"_index":2400,"title":{"199":{"position":[[0,10]]}},"content":{"62":{"position":[[315,7]]},"75":{"position":[[356,9],[1091,10]]},"76":{"position":[[2368,11]]},"78":{"position":[[881,10]]},"82":{"position":[[256,10],[326,10],[396,10],[466,10],[536,10],[606,10],[676,10],[746,10],[816,10],[886,10]]},"96":{"position":[[1060,10]]},"159":{"position":[[184,8],[658,10]]},"172":{"position":[[1074,10]]},"199":{"position":[[366,9],[625,9],[812,9],[865,7],[923,8],[939,6],[1009,7],[1296,9],[1446,9],[1642,8]]}},"keywords":{}}],["iter(actual_word",{"_index":2103,"title":{},"content":{"51":{"position":[[1292,19]]}},"keywords":{}}],["iter_count",{"_index":2722,"title":{},"content":{"76":{"position":[[1956,10],[2422,10],[2448,10],[2467,10],[2570,11]]}},"keywords":{}}],["iteration.given",{"_index":2667,"title":{},"content":{"75":{"position":[[782,15]]}},"keywords":{}}],["itself",{"_index":1685,"title":{},"content":{"38":{"position":[[13,6]]},"68":{"position":[[943,6]]},"88":{"position":[[3806,6]]},"93":{"position":[[392,6]]},"108":{"position":[[18,6]]},"116":{"position":[[2990,6]]},"117":{"position":[[267,6]]},"136":{"position":[[561,7]]},"160":{"position":[[364,6],[1874,6]]},"161":{"position":[[1556,6]]},"165":{"position":[[789,6]]},"199":{"position":[[932,6]]}},"keywords":{}}],["iwv",{"_index":3245,"title":{},"content":{"93":{"position":[[2968,4]]}},"keywords":{}}],["i}d(0,t)=d(0,t−1)⋅fi−1,i",{"_index":468,"title":{},"content":{"9":{"position":[[455,25]]}},"keywords":{}}],["i}fi−1,i",{"_index":470,"title":{},"content":{"9":{"position":[[502,9]]}},"keywords":{}}],["j",{"_index":2104,"title":{},"content":{"51":{"position":[[1332,1],[1361,1]]},"85":{"position":[[284,1]]}},"keywords":{}}],["jan_92_jan_16",{"_index":2473,"title":{},"content":{"64":{"position":[[962,13],[1055,13],[1668,14]]}},"keywords":{}}],["januari",{"_index":1851,"title":{},"content":{"41":{"position":[[271,7]]},"62":{"position":[[134,7],[1739,7]]},"64":{"position":[[227,7],[400,7],[417,7],[1095,7],[1112,7],[1355,7],[2036,7]]},"65":{"position":[[2165,7]]}},"keywords":{}}],["java",{"_index":3447,"title":{"127":{"position":[[20,7]]}},"content":{"98":{"position":[[593,6]]},"121":{"position":[[48,4]]},"127":{"position":[[75,4],[116,5],[140,5],[320,5],[436,4],[543,4]]},"128":{"position":[[1776,4]]},"129":{"position":[[1050,6]]},"160":{"position":[[1029,6]]},"172":{"position":[[492,4],[506,4],[1089,4],[1591,4],[1809,5],[2203,6]]}},"keywords":{}}],["java'",{"_index":4235,"title":{},"content":{"127":{"position":[[837,6]]}},"keywords":{}}],["java,lambda",{"_index":5325,"title":{},"content":{"196":{"position":[[95,11]]}},"keywords":{}}],["javascript",{"_index":47,"title":{},"content":{"1":{"position":[[540,12]]},"3":{"position":[[112,10]]},"125":{"position":[[15,10],[313,10],[1194,10],[1707,10],[3784,11],[6148,10],[6603,10],[6694,10],[7268,10],[10629,11]]},"196":{"position":[[359,10]]}},"keywords":{}}],["javascript,i",{"_index":4012,"title":{},"content":{"125":{"position":[[295,12]]}},"keywords":{}}],["jemalloc,tcmalloc",{"_index":4916,"title":{},"content":{"172":{"position":[[1233,19]]}},"keywords":{}}],["jerri",{"_index":2266,"title":{},"content":{"53":{"position":[[1353,5]]}},"keywords":{}}],["jit",{"_index":4930,"title":{},"content":{"172":{"position":[[2161,3],[2298,3],[2318,3],[2468,3]]},"189":{"position":[[224,4],[484,4],[3033,3]]}},"keywords":{}}],["jit(nogil=tru",{"_index":5255,"title":{},"content":{"189":{"position":[[2968,16]]}},"keywords":{}}],["jit(nopython=tru",{"_index":5235,"title":{},"content":{"189":{"position":[[1045,19],[1329,19],[3037,19]]}},"keywords":{}}],["jitclass",{"_index":5261,"title":{},"content":{"190":{"position":[[397,9]]}},"keywords":{}}],["jnj",{"_index":313,"title":{},"content":{"6":{"position":[[210,3]]}},"keywords":{}}],["job",{"_index":3563,"title":{},"content":{"104":{"position":[[964,3]]},"121":{"position":[[217,3]]},"125":{"position":[[876,3]]},"150":{"position":[[968,4]]},"193":{"position":[[750,3],[849,4]]},"198":{"position":[[172,4]]}},"keywords":{}}],["join((first",{"_index":2178,"title":{},"content":{"52":{"position":[[399,14]]}},"keywords":{}}],["join((tweet",{"_index":2192,"title":{},"content":{"52":{"position":[[1148,14]]}},"keywords":{}}],["join(results[result",{"_index":2153,"title":{},"content":{"51":{"position":[[3724,22]]}},"keywords":{}}],["joke",{"_index":1680,"title":{},"content":{"36":{"position":[[99,4]]}},"keywords":{}}],["jona",{"_index":2252,"title":{},"content":{"53":{"position":[[1168,5],[2111,5]]}},"keywords":{}}],["jone",{"_index":994,"title":{},"content":{"23":{"position":[[115,5]]}},"keywords":{}}],["joy",{"_index":35,"title":{},"content":{"1":{"position":[[390,4]]}},"keywords":{}}],["js",{"_index":4188,"title":{},"content":{"125":{"position":[[9591,2]]}},"keywords":{}}],["jsx",{"_index":44,"title":{},"content":{"1":{"position":[[518,3]]}},"keywords":{}}],["judg",{"_index":3578,"title":{},"content":{"105":{"position":[[328,6]]}},"keywords":{}}],["judgment",{"_index":1575,"title":{},"content":{"33":{"position":[[456,8]]}},"keywords":{}}],["juli",{"_index":1259,"title":{},"content":{"28":{"position":[[1890,8],[4077,4]]},"30":{"position":[[1407,8],[7480,4]]}},"keywords":{}}],["julia",{"_index":1714,"title":{},"content":{"39":{"position":[[338,5]]}},"keywords":{}}],["july'",{"_index":1280,"title":{},"content":{"28":{"position":[[2389,6]]}},"keywords":{}}],["jump",{"_index":2232,"title":{},"content":{"53":{"position":[[875,4]]}},"keywords":{}}],["justconcurr",{"_index":5265,"title":{},"content":{"190":{"position":[[1005,16]]}},"keywords":{}}],["justif",{"_index":1684,"title":{"38":{"position":[[12,14]]},"84":{"position":[[0,13]]}},"content":{"73":{"position":[[391,14]]}},"keywords":{}}],["jvm",{"_index":4908,"title":{},"content":{"172":{"position":[[525,3]]}},"keywords":{}}],["kaput",{"_index":2531,"title":{},"content":{"65":{"position":[[2391,5],[2438,5]]}},"keywords":{}}],["keep",{"_index":16,"title":{},"content":{"1":{"position":[[155,7]]},"35":{"position":[[470,7]]},"76":{"position":[[2099,4]]},"97":{"position":[[1399,4],[5235,4]]},"115":{"position":[[2621,5]]},"116":{"position":[[2465,5]]},"118":{"position":[[22,4],[341,4]]},"121":{"position":[[1969,4]]},"122":{"position":[[1448,7]]},"123":{"position":[[117,4],[269,4],[793,7],[867,7]]},"125":{"position":[[3906,4],[10263,4]]},"150":{"position":[[662,4]]},"158":{"position":[[301,4]]},"160":{"position":[[633,8],[4026,4]]},"161":{"position":[[1018,5]]},"172":{"position":[[612,4]]},"173":{"position":[[1263,4]]},"188":{"position":[[2829,4]]},"193":{"position":[[980,4]]},"196":{"position":[[1304,5]]}},"keywords":{}}],["kept",{"_index":2838,"title":{},"content":{"88":{"position":[[55,4]]},"125":{"position":[[8046,4]]}},"keywords":{}}],["kernel",{"_index":4938,"title":{"173":{"position":[[0,7]]}},"content":{"173":{"position":[[335,6],[1166,7],[1182,6],[2052,6]]},"174":{"position":[[708,6],[1182,6],[1224,6]]},"195":{"position":[[476,6]]}},"keywords":{}}],["kernelnetwork",{"_index":4994,"title":{},"content":{"174":{"position":[[1090,13]]}},"keywords":{}}],["kernelperf",{"_index":4924,"title":{},"content":{"172":{"position":[[1635,10]]}},"keywords":{}}],["key",{"_index":1054,"title":{},"content":{"24":{"position":[[1142,3]]},"25":{"position":[[862,3]]},"30":{"position":[[8746,3]]},"93":{"position":[[4550,4]]}},"keywords":{}}],["key.to_datetim",{"_index":1052,"title":{},"content":{"24":{"position":[[1106,19]]},"25":{"position":[[826,19]]}},"keywords":{}}],["keyerror",{"_index":3138,"title":{},"content":{"91":{"position":[[3114,9]]},"92":{"position":[[926,9]]}},"keywords":{}}],["keys=list(results.key",{"_index":1780,"title":{},"content":{"39":{"position":[[3309,26]]}},"keywords":{}}],["keyword",{"_index":3421,"title":{},"content":{"97":{"position":[[4775,7]]}},"keywords":{}}],["kick",{"_index":528,"title":{},"content":{"12":{"position":[[319,4]]},"172":{"position":[[2481,6]]}},"keywords":{}}],["kid",{"_index":3979,"title":{},"content":{"123":{"position":[[656,3]]},"165":{"position":[[17,3]]}},"keywords":{}}],["kilobyt",{"_index":5320,"title":{},"content":{"195":{"position":[[251,9],[327,9]]}},"keywords":{}}],["kind",{"_index":126,"title":{},"content":{"2":{"position":[[778,4]]},"51":{"position":[[1892,4]]},"66":{"position":[[14,4]]},"153":{"position":[[377,4]]}},"keywords":{}}],["kinda",{"_index":3848,"title":{},"content":{"120":{"position":[[167,5]]},"125":{"position":[[4075,5]]}},"keywords":{}}],["kindli",{"_index":3975,"title":{},"content":{"123":{"position":[[335,8]]}},"keywords":{}}],["knew",{"_index":2330,"title":{"88":{"position":[[16,5]]}},"content":{"58":{"position":[[277,4]]},"64":{"position":[[1534,5]]},"136":{"position":[[8,4]]},"160":{"position":[[170,4]]}},"keywords":{}}],["knife",{"_index":2234,"title":{},"content":{"53":{"position":[[900,5]]}},"keywords":{}}],["know",{"_index":726,"title":{},"content":{"18":{"position":[[18,4]]},"28":{"position":[[648,5]]},"30":{"position":[[709,4]]},"32":{"position":[[1237,4]]},"33":{"position":[[809,4]]},"34":{"position":[[404,4],[470,4]]},"35":{"position":[[82,4]]},"39":{"position":[[1828,4]]},"40":{"position":[[1080,4]]},"45":{"position":[[1,7],[528,4]]},"53":{"position":[[378,4],[1398,4]]},"54":{"position":[[137,4]]},"61":{"position":[[25,4],[46,4],[170,4],[1001,4],[1157,4]]},"65":{"position":[[29,4],[392,5],[1393,4]]},"66":{"position":[[39,5],[558,4]]},"74":{"position":[[47,5],[983,4]]},"93":{"position":[[543,5],[747,4],[1006,7]]},"96":{"position":[[1881,4],[2025,4]]},"97":{"position":[[4030,5],[5815,4]]},"108":{"position":[[201,4],[789,4]]},"112":{"position":[[1645,4]]},"113":{"position":[[2072,4]]},"117":{"position":[[664,4]]},"122":{"position":[[1353,4]]},"124":{"position":[[302,4],[732,5]]},"125":{"position":[[1503,7],[2157,4],[10332,7],[10771,6]]},"130":{"position":[[561,4]]},"132":{"position":[[150,5]]},"139":{"position":[[158,4]]},"140":{"position":[[68,5]]},"148":{"position":[[570,4]]},"159":{"position":[[234,4]]},"160":{"position":[[2729,4],[4322,4]]},"163":{"position":[[613,4]]},"173":{"position":[[1021,7]]},"174":{"position":[[290,5]]},"175":{"position":[[1562,4]]},"176":{"position":[[618,4]]},"193":{"position":[[1609,5]]}},"keywords":{}}],["knowledg",{"_index":1318,"title":{},"content":{"29":{"position":[[426,10]]},"150":{"position":[[308,9]]},"160":{"position":[[3006,9]]}},"keywords":{}}],["known",{"_index":2629,"title":{},"content":{"73":{"position":[[887,5]]},"115":{"position":[[3115,5]]},"125":{"position":[[10050,5]]}},"keywords":{}}],["kwarg",{"_index":934,"title":{},"content":{"22":{"position":[[1303,10],[1338,9]]},"93":{"position":[[1571,10],[1606,9]]}},"keywords":{}}],["l",{"_index":789,"title":{},"content":{"20":{"position":[[748,3]]},"199":{"position":[[386,1],[405,2]]}},"keywords":{}}],["l(x",{"_index":2647,"title":{},"content":{"74":{"position":[[1119,4]]}},"keywords":{}}],["l(x)={p2x=2p3x=3…p11x=11p12x=12\\begin{align",{"_index":2634,"title":{},"content":{"74":{"position":[[509,45]]}},"keywords":{}}],["l(x)=∏i=1nl(x)\\begin{align",{"_index":2644,"title":{},"content":{"74":{"position":[[1045,28]]}},"keywords":{}}],["l(x)l(x)l(x",{"_index":2652,"title":{},"content":{"74":{"position":[[1390,12]]}},"keywords":{}}],["l__unnamed_1",{"_index":5096,"title":{},"content":{"180":{"position":[[479,15]]},"197":{"position":[[371,12]]}},"keywords":{}}],["l__unnamed_2",{"_index":5344,"title":{},"content":{"197":{"position":[[517,12]]}},"keywords":{}}],["label",{"_index":1908,"title":{},"content":{"44":{"position":[[377,6],[516,6]]}},"keywords":{}}],["label="$\\pm",{"_index":3000,"title":{},"content":{"90":{"position":[[1609,17],[1758,17],[2902,17]]}},"keywords":{}}],["label="gaussian",{"_index":2006,"title":{},"content":{"45":{"position":[[2262,20],[3042,20]]}},"keywords":{}}],["label="invers",{"_index":2013,"title":{},"content":{"45":{"position":[[2394,19],[3174,19]]}},"keywords":{}}],["label="na",{"_index":2010,"title":{},"content":{"45":{"position":[[2327,17],[3107,17]]}},"keywords":{}}],["label='earn",{"_index":2883,"title":{},"content":{"88":{"position":[[1605,15],[1932,15],[3062,15],[3447,15]]},"91":{"position":[[823,15],[1293,15]]}},"keywords":{}}],["label='max",{"_index":3008,"title":{},"content":{"90":{"position":[[1959,10],[3098,10]]}},"keywords":{}}],["label='midpoint",{"_index":3084,"title":{},"content":{"91":{"position":[[700,17],[1164,17]]}},"keywords":{}}],["label=fals",{"_index":441,"title":{},"content":{"7":{"position":[[1283,13]]}},"keywords":{}}],["lack",{"_index":3370,"title":{},"content":{"97":{"position":[[1042,4],[2805,4]]},"100":{"position":[[211,4]]},"160":{"position":[[3020,4]]}},"keywords":{}}],["lackadais",{"_index":4345,"title":{},"content":{"132":{"position":[[317,13]]}},"keywords":{}}],["lambda",{"_index":748,"title":{},"content":{"19":{"position":[[288,6]]},"20":{"position":[[242,6],[1462,6],[1799,6],[1886,6]]},"39":{"position":[[564,6]]},"62":{"position":[[1057,6]]},"90":{"position":[[677,6]]}},"keywords":{}}],["land",{"_index":4127,"title":{},"content":{"125":{"position":[[5707,6],[11116,6]]},"175":{"position":[[108,4]]}},"keywords":{}}],["lang.org/std/sync/struct.once.html#method.call_onc",{"_index":5140,"title":{},"content":{"186":{"position":[[249,51]]}},"keywords":{}}],["lang/rust",{"_index":3745,"title":{},"content":{"113":{"position":[[1209,9]]}},"keywords":{}}],["languag",{"_index":3309,"title":{"122":{"position":[[14,9]]},"172":{"position":[[0,8]]}},"content":{"95":{"position":[[368,8]]},"98":{"position":[[352,9]]},"125":{"position":[[691,8],[730,8]]},"128":{"position":[[147,8]]},"130":{"position":[[240,8]]},"152":{"position":[[361,9]]},"160":{"position":[[355,8],[1019,9]]},"172":{"position":[[714,8],[943,8],[1461,9],[1757,9],[2098,9],[2322,10]]},"176":{"position":[[528,8]]},"188":{"position":[[37,8]]},"189":{"position":[[100,8]]},"193":{"position":[[615,9]]},"196":{"position":[[73,8]]},"198":{"position":[[567,8]]},"199":{"position":[[19,9]]}},"keywords":{}}],["larg",{"_index":525,"title":{},"content":{"12":{"position":[[137,7]]},"40":{"position":[[2331,5]]},"82":{"position":[[34,5]]},"89":{"position":[[788,5]]},"92":{"position":[[1483,5]]},"93":{"position":[[673,5],[1055,7]]},"105":{"position":[[46,5]]},"194":{"position":[[91,5]]}},"keywords":{}}],["large(u64",{"_index":5313,"title":{},"content":{"194":{"position":[[244,10]]}},"keywords":{}}],["largegoogle.com'",{"_index":4699,"title":{},"content":{"160":{"position":[[2913,17]]}},"keywords":{}}],["larger",{"_index":3649,"title":{},"content":{"105":{"position":[[3368,6]]},"111":{"position":[[811,6]]},"150":{"position":[[494,6]]}},"keywords":{}}],["largest",{"_index":765,"title":{},"content":{"20":{"position":[[208,7]]},"194":{"position":[[502,7]]}},"keywords":{}}],["last",{"_index":1372,"title":{},"content":{"30":{"position":[[2435,4]]},"33":{"position":[[529,4]]},"39":{"position":[[204,4]]},"45":{"position":[[2747,4]]},"50":{"position":[[213,4]]},"83":{"position":[[575,5]]},"96":{"position":[[2323,5]]},"97":{"position":[[6288,5]]},"125":{"position":[[4059,4]]},"135":{"position":[[65,4]]},"160":{"position":[[1154,4]]}},"keywords":{}}],["last_coupon",{"_index":678,"title":{},"content":{"15":{"position":[[942,11],[1341,12],[1363,11]]}},"keywords":{}}],["late",{"_index":1833,"title":{},"content":{"40":{"position":[[3171,4]]},"125":{"position":[[140,4]]},"130":{"position":[[319,4]]}},"keywords":{}}],["later",{"_index":58,"title":{},"content":{"1":{"position":[[651,5]]},"8":{"position":[[158,5]]},"30":{"position":[[7977,6]]},"41":{"position":[[252,5]]},"45":{"position":[[1514,6]]},"97":{"position":[[1452,6],[3766,5]]},"110":{"position":[[83,6]]},"113":{"position":[[895,5],[1054,6]]},"184":{"position":[[267,5]]}},"keywords":{}}],["launch",{"_index":4823,"title":{},"content":{"165":{"position":[[102,9]]}},"keywords":{}}],["law",{"_index":4407,"title":{},"content":{"137":{"position":[[193,3]]}},"keywords":{}}],["lay",{"_index":310,"title":{},"content":{"6":{"position":[[142,4]]}},"keywords":{}}],["layout",{"_index":4335,"title":{},"content":{"130":{"position":[[224,7]]},"152":{"position":[[402,7],[1340,7],[1348,7],[1521,7],[1529,7],[1644,8]]},"156":{"position":[[852,7],[1423,7],[1431,7],[1604,7],[1612,7],[1727,8]]},"172":{"position":[[1316,7],[1722,7]]},"193":{"position":[[3094,7]]}},"keywords":{}}],["lbyte_str.u",{"_index":4286,"title":{},"content":{"129":{"position":[[568,13]]}},"keywords":{}}],["lda",{"_index":1956,"title":{"45":{"position":[[33,4]]}},"content":{"45":{"position":[[683,3],[861,3]]}},"keywords":{}}],["lda/qda/svm",{"_index":1984,"title":{},"content":{"45":{"position":[[1496,11]]}},"keywords":{}}],["ldot",{"_index":2638,"title":{},"content":{"74":{"position":[[634,6]]},"85":{"position":[[295,7]]}},"keywords":{}}],["le",{"_index":786,"title":{},"content":{"20":{"position":[[710,3],[744,3]]}},"keywords":{}}],["le_u32",{"_index":4792,"title":{},"content":{"163":{"position":[[1978,7],[1986,7],[1994,7],[2002,7],[2010,7],[2018,7]]}},"keywords":{}}],["lea",{"_index":4284,"title":{},"content":{"129":{"position":[[552,3]]}},"keywords":{}}],["lead",{"_index":2273,"title":{},"content":{"53":{"position":[[1465,5]]},"72":{"position":[[534,5]]},"90":{"position":[[4278,7]]},"102":{"position":[[353,4]]},"106":{"position":[[1102,4]]},"125":{"position":[[7430,5]]},"130":{"position":[[120,5]]},"185":{"position":[[7,5]]},"189":{"position":[[2626,5]]}},"keywords":{}}],["leak",{"_index":3454,"title":{},"content":{"98":{"position":[[1050,7]]}},"keywords":{}}],["leap",{"_index":2454,"title":{},"content":{"64":{"position":[[351,4],[460,4],[687,4],[750,4]]},"65":{"position":[[369,4],[564,4],[615,4],[1420,4],[1637,4]]}},"keywords":{}}],["leap_day",{"_index":2472,"title":{},"content":{"64":{"position":[[948,9],[1044,10]]}},"keywords":{}}],["leap_day_count",{"_index":2467,"title":{},"content":{"64":{"position":[[821,14],[1011,14]]},"65":{"position":[[672,14],[1613,14]]}},"keywords":{}}],["learn",{"_index":217,"title":{"4":{"position":[[0,8]]},"119":{"position":[[7,7]]},"153":{"position":[[20,7]]}},"content":{"4":{"position":[[211,8],[1404,8]]},"73":{"position":[[201,8]]},"98":{"position":[[303,7]]},"102":{"position":[[98,9]]},"103":{"position":[[139,5]]},"125":{"position":[[10242,5]]},"132":{"position":[[785,7]]},"139":{"position":[[830,5]]},"160":{"position":[[799,5]]},"161":{"position":[[531,7],[1257,7]]}},"keywords":{}}],["leav",{"_index":297,"title":{},"content":{"4":{"position":[[1485,5]]},"38":{"position":[[776,5]]},"128":{"position":[[736,5]]},"161":{"position":[[1493,6]]},"198":{"position":[[151,5]]}},"keywords":{}}],["leave"",{"_index":4725,"title":{},"content":{"161":{"position":[[43,11]]}},"keywords":{}}],["led",{"_index":4008,"title":{},"content":{"125":{"position":[[111,3]]}},"keywords":{}}],["left",{"_index":2318,"title":{},"content":{"57":{"position":[[718,5]]},"64":{"position":[[2083,5]]},"65":{"position":[[804,5],[1229,5],[1326,5],[1525,4],[1574,5],[1918,4],[2060,4]]},"66":{"position":[[585,4],[791,5]]},"70":{"position":[[281,7],[455,7]]},"71":{"position":[[381,7],[555,7]]},"74":{"position":[[572,7]]},"90":{"position":[[4989,4]]},"91":{"position":[[3883,4]]},"117":{"position":[[1899,4]]},"134":{"position":[[109,4]]},"150":{"position":[[405,4]]}},"keywords":{}}],["left|\\omega\\right",{"_index":788,"title":{},"content":{"20":{"position":[[724,19]]}},"keywords":{}}],["legal",{"_index":3795,"title":{},"content":{"115":{"position":[[3091,6]]}},"keywords":{}}],["legend=c",{"_index":1277,"title":{},"content":{"28":{"position":[[2274,12],[3947,12]]}},"keywords":{}}],["legend=months_str[x",{"_index":1367,"title":{},"content":{"30":{"position":[[2212,21],[3697,21],[3920,21],[5476,21],[6777,21],[7000,21]]}},"keywords":{}}],["legitim",{"_index":2239,"title":{},"content":{"53":{"position":[[950,12],[1590,10]]},"76":{"position":[[1022,10]]}},"keywords":{}}],["len",{"_index":4773,"title":{},"content":{"163":{"position":[[1441,3],[1525,3]]}},"keywords":{}}],["len(b_class",{"_index":1906,"title":{},"content":{"44":{"position":[[296,12],[686,14]]}},"keywords":{}}],["len(component_byt",{"_index":3588,"title":{},"content":{"105":{"position":[[863,21]]}},"keywords":{}}],["len(compress",{"_index":3595,"title":{},"content":{"105":{"position":[[1122,15]]}},"keywords":{}}],["len(dist",{"_index":2167,"title":{},"content":{"51":{"position":[[4183,9]]}},"keywords":{}}],["len(elem",{"_index":3136,"title":{},"content":{"91":{"position":[[3056,10]]},"92":{"position":[[868,10]]}},"keywords":{}}],["len(elems.dropna()[elem",{"_index":3137,"title":{},"content":{"91":{"position":[[3072,24]]},"92":{"position":[[884,24]]}},"keywords":{}}],["len(first",{"_index":2189,"title":{},"content":{"52":{"position":[[885,10]]}},"keywords":{}}],["len(first_words_alpha",{"_index":2090,"title":{},"content":{"51":{"position":[[672,22]]}},"keywords":{}}],["len(fram",{"_index":1030,"title":{},"content":{"24":{"position":[[578,12]]},"25":{"position":[[303,12]]}},"keywords":{}}],["len(hashtag",{"_index":2124,"title":{},"content":{"51":{"position":[[2319,13]]},"52":{"position":[[898,13],[982,13]]}},"keywords":{}}],["len(hashtag_dist",{"_index":2131,"title":{},"content":{"51":{"position":[[2530,17]]}},"keywords":{}}],["len(list(filter(lambda",{"_index":1248,"title":{},"content":{"28":{"position":[[1483,22],[3274,22]]},"30":{"position":[[1844,22],[3193,22],[5108,22],[6262,22]]}},"keywords":{}}],["len(matches_dict[index][futur",{"_index":1084,"title":{},"content":{"24":{"position":[[2155,32]]},"25":{"position":[[1879,32]]}},"keywords":{}}],["len(month",{"_index":1365,"title":{},"content":{"30":{"position":[[2161,13],[3647,13],[3866,13],[5420,13],[6720,13],[6945,13]]}},"keywords":{}}],["len(recon.tobyt",{"_index":3607,"title":{},"content":{"105":{"position":[[1576,20]]}},"keywords":{}}],["len(sign",{"_index":3524,"title":{},"content":{"103":{"position":[[1009,11]]}},"keywords":{}}],["len(signal_byt",{"_index":3587,"title":{},"content":{"105":{"position":[[842,18]]}},"keywords":{}}],["len(tick",{"_index":835,"title":{},"content":{"20":{"position":[[1974,12]]}},"keywords":{}}],["len(tweet",{"_index":2190,"title":{},"content":{"52":{"position":[[969,10]]}},"keywords":{}}],["len(x.column",{"_index":1876,"title":{},"content":{"43":{"position":[[650,14]]}},"keywords":{}}],["len(x[0",{"_index":1768,"title":{},"content":{"39":{"position":[[2837,10],[2943,11]]}},"keywords":{}}],["len(x[c].uniqu",{"_index":1904,"title":{},"content":{"44":{"position":[[253,18]]}},"keywords":{}}],["length",{"_index":4771,"title":{},"content":{"163":{"position":[[1088,6]]},"166":{"position":[[392,6],[508,6]]}},"keywords":{}}],["length(investments))"",{"_index":1653,"title":{},"content":{"34":{"position":[[2937,29]]}},"keywords":{}}],["length(motion[1",{"_index":407,"title":{},"content":{"7":{"position":[[615,19]]}},"keywords":{}}],["length(motion[:,1",{"_index":408,"title":{},"content":{"7":{"position":[[639,19]]}},"keywords":{}}],["length(s0",{"_index":391,"title":{},"content":{"7":{"position":[[330,10]]}},"keywords":{}}],["length(term",{"_index":475,"title":{},"content":{"9":{"position":[[732,12]]}},"keywords":{}}],["length(year_pric",{"_index":568,"title":{},"content":{"13":{"position":[[736,19]]},"14":{"position":[[1593,19]]},"15":{"position":[[980,19]]}},"keywords":{}}],["less",{"_index":1409,"title":{},"content":{"30":{"position":[[5611,4]]},"45":{"position":[[975,4]]},"66":{"position":[[865,4]]},"76":{"position":[[1175,4]]},"165":{"position":[[1451,4]]},"173":{"position":[[1403,4]]},"189":{"position":[[1888,4]]}},"keywords":{}}],["lesson",{"_index":231,"title":{},"content":{"4":{"position":[[203,7]]},"161":{"position":[[564,8],[1275,7]]}},"keywords":{}}],["let",{"_index":2397,"title":{},"content":{"62":{"position":[[223,4]]},"93":{"position":[[368,7]]},"117":{"position":[[628,4]]},"160":{"position":[[3456,4]]}},"keywords":{}}],["let'",{"_index":307,"title":{},"content":{"6":{"position":[[86,5]]},"8":{"position":[[1,5]]},"9":{"position":[[45,5]]},"10":{"position":[[40,5]]},"11":{"position":[[95,5]]},"13":{"position":[[51,5]]},"14":{"position":[[1,5]]},"15":{"position":[[553,5]]},"23":{"position":[[163,5]]},"24":{"position":[[195,5]]},"25":{"position":[[123,5]]},"28":{"position":[[2802,5]]},"34":{"position":[[987,5],[1362,5],[3016,5],[3605,5]]},"38":{"position":[[395,5]]},"39":{"position":[[102,5]]},"40":{"position":[[1,5],[82,5],[558,5],[2573,5]]},"44":{"position":[[384,5]]},"45":{"position":[[1021,5],[2733,5]]},"51":{"position":[[77,5],[327,5],[1532,5],[1994,5],[2207,5],[3265,5]]},"52":{"position":[[87,5],[504,5]]},"57":{"position":[[628,5]]},"62":{"position":[[1771,5]]},"65":{"position":[[1332,5]]},"68":{"position":[[212,5]]},"69":{"position":[[76,5]]},"77":{"position":[[1,5]]},"88":{"position":[[2134,5],[2400,5]]},"91":{"position":[[4942,5]]},"96":{"position":[[229,5],[594,5],[1040,5],[1581,5]]},"97":{"position":[[3178,5],[4814,5]]},"103":{"position":[[368,5],[1542,5],[1906,5]]},"105":{"position":[[2652,5],[2838,5]]},"113":{"position":[[1558,5],[1751,5]]},"116":{"position":[[2347,5]]},"121":{"position":[[2748,5]]},"125":{"position":[[10906,5]]},"128":{"position":[[112,5],[1045,5]]},"129":{"position":[[363,5]]},"160":{"position":[[793,5],[3337,5]]},"184":{"position":[[7,5]]},"188":{"position":[[1464,5]]},"189":{"position":[[895,5]]}},"keywords":{}}],["level",{"_index":156,"title":{"128":{"position":[[4,5]]}},"content":{"3":{"position":[[456,6]]},"14":{"position":[[669,5]]},"20":{"position":[[895,6],[919,6]]},"34":{"position":[[542,5]]},"110":{"position":[[218,5]]},"121":{"position":[[1951,6]]},"127":{"position":[[1598,5]]},"128":{"position":[[374,5],[927,5]]},"176":{"position":[[1626,6]]}},"keywords":{}}],["level=1).hist",{"_index":1791,"title":{},"content":{"40":{"position":[[260,15],[1794,15],[2737,15]]}},"keywords":{}}],["level=1).plot",{"_index":1797,"title":{},"content":{"40":{"position":[[429,15],[1965,15],[2909,15]]}},"keywords":{}}],["leverag",{"_index":796,"title":{},"content":{"20":{"position":[[930,8],[1097,8],[1851,8]]},"34":{"position":[[2742,9],[2875,9],[3419,9],[3810,9],[3929,9]]},"38":{"position":[[110,8],[528,8],[832,8],[909,8],[964,10],[1179,9]]},"40":{"position":[[3350,9]]}},"keywords":{}}],["levien",{"_index":4643,"title":{},"content":{"159":{"position":[[1259,6]]}},"keywords":{}}],["lexic",{"_index":3743,"title":{},"content":{"113":{"position":[[1163,7]]}},"keywords":{}}],["lib.r",{"_index":4367,"title":{},"content":{"133":{"position":[[232,6]]}},"keywords":{}}],["liber",{"_index":3921,"title":{},"content":{"121":{"position":[[2369,10]]}},"keywords":{}}],["librari",{"_index":2068,"title":{},"content":{"51":{"position":[[24,7]]},"53":{"position":[[485,7]]},"95":{"position":[[25,7]]},"108":{"position":[[144,10]]},"109":{"position":[[555,7]]},"112":{"position":[[1250,7]]},"120":{"position":[[88,7],[129,7]]},"121":{"position":[[445,7]]},"122":{"position":[[366,8],[511,7],[570,7],[988,7],[1176,7]]},"124":{"position":[[154,7]]},"125":{"position":[[11146,9]]},"132":{"position":[[122,8]]},"155":{"position":[[596,7]]},"156":{"position":[[1776,7]]},"157":{"position":[[350,7]]},"159":{"position":[[1156,7]]},"163":{"position":[[431,7]]},"188":{"position":[[197,10]]}},"keywords":{}}],["library"",{"_index":3937,"title":{},"content":{"122":{"position":[[216,13],[1067,13]]}},"keywords":{}}],["libui",{"_index":4042,"title":{},"content":{"125":{"position":[[1315,6]]}},"keywords":{}}],["life",{"_index":2336,"title":{},"content":{"58":{"position":[[562,4],[582,4],[702,4]]},"63":{"position":[[124,5]]},"66":{"position":[[279,5]]},"123":{"position":[[762,5]]},"127":{"position":[[67,4]]},"150":{"position":[[169,4]]},"160":{"position":[[1198,4]]},"182":{"position":[[141,4]]}},"keywords":{}}],["lifetim",{"_index":2316,"title":{},"content":{"57":{"position":[[660,8]]},"58":{"position":[[782,8]]},"98":{"position":[[715,8]]},"113":{"position":[[1171,10]]},"117":{"position":[[1542,10]]},"152":{"position":[[60,8]]},"182":{"position":[[213,10]]}},"keywords":{}}],["lifetimeand",{"_index":3394,"title":{},"content":{"97":{"position":[[2543,11]]}},"keywords":{}}],["lift",{"_index":2070,"title":{},"content":{"51":{"position":[[61,8]]}},"keywords":{}}],["light",{"_index":2904,"title":{},"content":{"88":{"position":[[2388,6]]}},"keywords":{}}],["lighter",{"_index":4734,"title":{},"content":{"161":{"position":[[502,7]]}},"keywords":{}}],["lightli",{"_index":4253,"title":{},"content":{"128":{"position":[[425,7],[1250,7]]}},"keywords":{}}],["likebranch",{"_index":4977,"title":{},"content":{"174":{"position":[[155,10]]}},"keywords":{}}],["likecompil",{"_index":4711,"title":{},"content":{"160":{"position":[[3875,11]]}},"keywords":{}}],["likecriterion",{"_index":5050,"title":{},"content":{"176":{"position":[[1194,13]]}},"keywords":{}}],["likejailhous",{"_index":4991,"title":{},"content":{"174":{"position":[[870,13]]}},"keywords":{}}],["likejava",{"_index":5370,"title":{},"content":{"199":{"position":[[29,11]]}},"keywords":{}}],["likelihood",{"_index":2630,"title":{"74":{"position":[[13,10]]}},"content":{"73":{"position":[[900,10]]},"74":{"position":[[15,10],[992,10]]},"75":{"position":[[36,10]]},"86":{"position":[[814,10]]}},"keywords":{}}],["liketelecom",{"_index":4998,"title":{},"content":{"174":{"position":[[1317,11]]}},"keywords":{}}],["likethi",{"_index":4775,"title":{},"content":{"163":{"position":[[1667,9]]}},"keywords":{}}],["liketim",{"_index":3861,"title":{},"content":{"120":{"position":[[755,9]]}},"keywords":{}}],["likewis",{"_index":4343,"title":{},"content":{"132":{"position":[[234,8]]}},"keywords":{}}],["limit",{"_index":1985,"title":{},"content":{"45":{"position":[[1705,5]]},"93":{"position":[[4611,6]]},"97":{"position":[[982,7]]},"160":{"position":[[1830,7],[2563,7]]},"173":{"position":[[513,5]]}},"keywords":{}}],["line",{"_index":680,"title":{},"content":{"15":{"position":[[1313,5]]},"30":{"position":[[7355,4]]},"33":{"position":[[400,5]]},"44":{"position":[[1148,4]]},"90":{"position":[[4754,4],[4977,4]]},"91":{"position":[[1999,5]]},"93":{"position":[[4412,5]]},"97":{"position":[[6388,4]]},"121":{"position":[[1558,4],[2206,5],[2324,5]]},"129":{"position":[[2498,4]]},"152":{"position":[[678,4]]},"155":{"position":[[1377,4],[1439,4],[1501,4],[1564,4]]},"156":{"position":[[661,4]]},"173":{"position":[[642,4]]},"175":{"position":[[133,4]]},"179":{"position":[[994,4],[1099,4]]},"181":{"position":[[154,4],[276,5]]},"188":{"position":[[3864,4],[3929,4],[4008,4]]},"192":{"position":[[155,4],[529,4]]},"193":{"position":[[2330,4],[3512,5]]}},"keywords":{}}],["linear",{"_index":329,"title":{},"content":{"6":{"position":[[412,6]]},"10":{"position":[[313,6]]},"86":{"position":[[111,6],[186,6],[564,6]]}},"keywords":{}}],["link",{"_index":4071,"title":{},"content":{"125":{"position":[[2870,4],[6135,4],[6577,4],[7123,7],[7799,6]]},"129":{"position":[[1383,4]]},"155":{"position":[[277,6]]}},"keywords":{}}],["linker",{"_index":4648,"title":{},"content":{"160":{"position":[[182,6]]}},"keywords":{}}],["linking/packag",{"_index":5263,"title":{},"content":{"190":{"position":[[597,17]]}},"keywords":{}}],["links"""",{"_index":886,"title":{},"content":{"22":{"position":[[258,23]]}},"keywords":{}}],["linux",{"_index":3665,"title":{},"content":{"108":{"position":[[342,5]]},"124":{"position":[[203,5]]},"134":{"position":[[74,6]]},"173":{"position":[[241,5]]},"176":{"position":[[363,5]]},"195":{"position":[[525,6]]}},"keywords":{}}],["liquid",{"_index":3192,"title":{},"content":{"93":{"position":[[688,9]]}},"keywords":{}}],["list",{"_index":2052,"title":{},"content":{"49":{"position":[[16,4]]},"91":{"position":[[2151,4]]},"93":{"position":[[2982,4]]},"121":{"position":[[2409,4]]}},"keywords":{}}],["list(earnings_data.key",{"_index":3275,"title":{},"content":{"93":{"position":[[4628,26]]}},"keywords":{}}],["list(filter(lambda",{"_index":897,"title":{},"content":{"22":{"position":[[517,18],[1477,18]]}},"keywords":{}}],["list(map(lambda",{"_index":1245,"title":{},"content":{"28":{"position":[[1386,15],[3181,15]]},"30":{"position":[[1752,15],[3101,15],[5020,15],[6169,15]]},"93":{"position":[[2886,15]]}},"keywords":{}}],["list(set([x",{"_index":2126,"title":{},"content":{"51":{"position":[[2351,11]]}},"keywords":{}}],["list(set(global_articl",{"_index":982,"title":{},"content":{"22":{"position":[[2881,26]]}},"keywords":{}}],["list_1.iterrow",{"_index":1056,"title":{},"content":{"24":{"position":[[1188,18]]},"25":{"position":[[908,18]]}},"keywords":{}}],["list_2",{"_index":1047,"title":{},"content":{"24":{"position":[[955,8],[1322,7]]},"25":{"position":[[675,8],[1042,7]]}},"keywords":{}}],["list_2.key",{"_index":1055,"title":{},"content":{"24":{"position":[[1149,14]]},"25":{"position":[[869,14]]}},"keywords":{}}],["list_2[index_dt",{"_index":1066,"title":{},"content":{"24":{"position":[[1344,16]]},"25":{"position":[[1064,16]]}},"keywords":{}}],["list_2[key",{"_index":1053,"title":{},"content":{"24":{"position":[[1126,11]]},"25":{"position":[[846,11]]}},"keywords":{}}],["liter",{"_index":3348,"title":{},"content":{"96":{"position":[[1798,7]]},"132":{"position":[[900,9]]}},"keywords":{}}],["littl",{"_index":279,"title":{},"content":{"4":{"position":[[1091,6]]},"30":{"position":[[9485,6]]},"98":{"position":[[627,6]]},"116":{"position":[[2358,6]]},"122":{"position":[[1369,6]]},"161":{"position":[[421,6]]}},"keywords":{}}],["live",{"_index":1314,"title":{},"content":{"29":{"position":[[244,4]]},"66":{"position":[[201,4]]},"112":{"position":[[479,5]]},"174":{"position":[[467,4]]}},"keywords":{}}],["llvm",{"_index":4508,"title":{},"content":{"152":{"position":[[35,4],[160,4],[309,4],[835,4]]},"153":{"position":[[35,4],[84,4],[414,4]]},"172":{"position":[[2229,4]]}},"keywords":{}}],["lmt",{"_index":1656,"title":{},"content":{"34":{"position":[[3103,4]]}},"keywords":{}}],["load",{"_index":110,"title":{},"content":{"2":{"position":[[551,4]]},"30":{"position":[[319,7]]},"43":{"position":[[22,4]]},"68":{"position":[[389,6]]},"69":{"position":[[337,6]]},"71":{"position":[[17,6],[40,6],[115,6]]},"72":{"position":[[322,6]]},"73":{"position":[[106,7]]},"77":{"position":[[94,6]]},"103":{"position":[[84,7],[387,4]]},"125":{"position":[[3996,4],[4469,4]]},"134":{"position":[[319,4]]},"178":{"position":[[334,6]]},"180":{"position":[[52,6]]},"182":{"position":[[507,6]]}},"keywords":{}}],["loader",{"_index":171,"title":{},"content":{"3":{"position":[[754,8]]}},"keywords":{}}],["loav",{"_index":4743,"title":{},"content":{"161":{"position":[[927,6]]}},"keywords":{}}],["loc",{"_index":1484,"title":{},"content":{"30":{"position":[[9665,3]]}},"keywords":{}}],["local",{"_index":2346,"title":{},"content":{"60":{"position":[[185,5]]},"85":{"position":[[530,5]]},"86":{"position":[[267,5]]},"134":{"position":[[244,5]]},"172":{"position":[[1398,8]]},"196":{"position":[[173,5],[214,5]]}},"keywords":{}}],["locat",{"_index":979,"title":{},"content":{"22":{"position":[[2811,9]]},"113":{"position":[[529,8]]},"127":{"position":[[1473,6]]},"128":{"position":[[583,8],[823,8],[1331,8]]},"129":{"position":[[1003,8]]},"155":{"position":[[991,8]]},"181":{"position":[[983,9]]},"182":{"position":[[454,9]]},"183":{"position":[[767,8]]},"192":{"position":[[274,8]]},"193":{"position":[[437,7]]}},"keywords":{}}],["lock",{"_index":5197,"title":{},"content":{"188":{"position":[[2934,6],[3341,6]]},"189":{"position":[[831,5],[857,6],[1289,6],[2003,6],[2606,6]]}},"keywords":{}}],["log(\\mathcal{l",{"_index":2659,"title":{},"content":{"74":{"position":[[1681,17]]}},"keywords":{}}],["log(l",{"_index":2660,"title":{},"content":{"74":{"position":[[1719,7]]}},"keywords":{}}],["logic",{"_index":3028,"title":{},"content":{"90":{"position":[[3639,5]]},"121":{"position":[[789,6],[1890,6]]}},"keywords":{}}],["loglevel",{"_index":3506,"title":{},"content":{"103":{"position":[[260,8]]}},"keywords":{}}],["log⁡(d)\\log(d)log(d",{"_index":1694,"title":{},"content":{"38":{"position":[[643,21]]}},"keywords":{}}],["log⁡(l)=∑i=1nlog⁡(l)\\begin{align",{"_index":2658,"title":{},"content":{"74":{"position":[[1646,34]]}},"keywords":{}}],["log⁡(l)\\log(\\mathcal{l})log(l",{"_index":2649,"title":{},"content":{"74":{"position":[[1208,30]]},"75":{"position":[[570,30]]}},"keywords":{}}],["london",{"_index":1214,"title":{},"content":{"28":{"position":[[495,6]]}},"keywords":{}}],["long",{"_index":1466,"title":{},"content":{"30":{"position":[[8772,5],[8921,5],[9018,5]]},"32":{"position":[[228,4]]},"33":{"position":[[583,4]]},"43":{"position":[[370,4]]},"44":{"position":[[1252,4]]},"45":{"position":[[1344,4],[1399,5]]},"61":{"position":[[377,5]]},"83":{"position":[[570,4]]},"89":{"position":[[839,5]]},"93":{"position":[[300,4]]},"96":{"position":[[2318,4]]},"97":{"position":[[92,4],[6167,4],[6283,4]]},"98":{"position":[[14,4]]},"112":{"position":[[526,4]]},"113":{"position":[[228,4]]},"121":{"position":[[762,4]]},"125":{"position":[[9886,4]]},"127":{"position":[[230,4]]},"160":{"position":[[1136,4]]},"164":{"position":[[112,4],[1575,4]]},"168":{"position":[[48,4]]},"169":{"position":[[48,4]]},"173":{"position":[[1033,4]]},"188":{"position":[[984,4],[1008,4],[1060,4],[1175,4],[1309,4],[1479,4]]},"189":{"position":[[1582,4],[1700,4],[2066,4]]},"199":{"position":[[153,4],[317,4],[380,5]]}},"keywords":{}}],["long/short",{"_index":800,"title":{},"content":{"20":{"position":[[979,10]]}},"keywords":{}}],["longer",{"_index":2499,"title":{"65":{"position":[[20,8]]}},"content":{"66":{"position":[[206,7]]},"82":{"position":[[1075,6]]},"97":{"position":[[5518,6]]},"98":{"position":[[1227,6]]},"113":{"position":[[1258,6]]},"121":{"position":[[1797,7],[2306,6]]},"146":{"position":[[476,6]]},"156":{"position":[[154,6]]},"183":{"position":[[850,6]]},"194":{"position":[[162,7]]}},"keywords":{}}],["look",{"_index":190,"title":{},"content":{"3":{"position":[[1095,6]]},"4":{"position":[[1289,7]]},"28":{"position":[[2350,5],[2842,7]]},"30":{"position":[[7416,6]]},"32":{"position":[[921,4],[1422,5]]},"38":{"position":[[1033,4]]},"39":{"position":[[152,7]]},"40":{"position":[[13,7],[101,5],[826,7],[3720,5]]},"44":{"position":[[916,5]]},"51":{"position":[[1857,5]]},"53":{"position":[[1964,7]]},"57":{"position":[[614,4]]},"64":{"position":[[488,7]]},"68":{"position":[[262,5]]},"72":{"position":[[638,7]]},"88":{"position":[[161,4],[2140,4]]},"91":{"position":[[5327,7],[5718,4]]},"92":{"position":[[93,7]]},"93":{"position":[[61,7],[469,4],[608,4]]},"96":{"position":[[806,4],[950,4],[1562,5]]},"97":{"position":[[731,5],[3336,4],[3538,5],[6039,4]]},"106":{"position":[[1133,4]]},"111":{"position":[[719,4]]},"112":{"position":[[354,5],[775,4],[930,4],[967,5]]},"115":{"position":[[87,4]]},"116":{"position":[[181,5]]},"121":{"position":[[808,7]]},"122":{"position":[[1000,4]]},"124":{"position":[[822,7]]},"125":{"position":[[7737,5]]},"128":{"position":[[1058,4],[1292,4]]},"155":{"position":[[547,4],[799,4],[1262,7]]},"159":{"position":[[193,5]]},"160":{"position":[[446,4],[2798,4]]},"161":{"position":[[868,4],[1645,7]]},"163":{"position":[[1661,5]]},"172":{"position":[[1200,4]]},"176":{"position":[[687,4]]},"182":{"position":[[407,4]]},"188":{"position":[[51,5]]},"193":{"position":[[2176,4]]},"196":{"position":[[1022,5]]}},"keywords":{}}],["lookback",{"_index":717,"title":{},"content":{"17":{"position":[[222,8],[303,10]]},"19":{"position":[[80,8]]},"20":{"position":[[62,8]]},"90":{"position":[[820,11],[887,8],[1089,8],[1355,8],[2048,8],[2093,8],[2205,11],[2272,8],[2474,8],[2710,8],[3150,8]]}},"keywords":{}}],["lookback+1",{"_index":3012,"title":{},"content":{"90":{"position":[[2060,12],[2105,12],[3162,12]]}},"keywords":{}}],["lookforward",{"_index":2984,"title":{},"content":{"90":{"position":[[1050,11],[1376,11],[1542,13],[1574,13],[1691,13],[1723,13],[2435,11],[2731,11],[2835,13],[2867,13]]}},"keywords":{}}],["lookforward+1",{"_index":3004,"title":{},"content":{"90":{"position":[[1815,15],[1848,15],[1917,16],[2959,15],[2992,15],[3056,16]]}},"keywords":{}}],["lookforward_data",{"_index":2987,"title":{},"content":{"90":{"position":[[1133,16],[2518,16]]}},"keywords":{}}],["lookforward_data.max(axis=0",{"_index":2992,"title":{},"content":{"90":{"position":[[1245,28],[2630,28]]}},"keywords":{}}],["lookforward_data.min(axis=0",{"_index":2993,"title":{},"content":{"90":{"position":[[1281,28],[2666,28]]}},"keywords":{}}],["lookforward_data.std(axis=0",{"_index":2991,"title":{},"content":{"90":{"position":[[1206,30],[2591,30]]}},"keywords":{}}],["lookimposs",{"_index":4540,"title":{},"content":{"153":{"position":[[244,14]]}},"keywords":{}}],["lookup",{"_index":5091,"title":{},"content":{"180":{"position":[[249,6]]}},"keywords":{}}],["loop",{"_index":1026,"title":{},"content":{"24":{"position":[[499,5]]},"25":{"position":[[224,5]]},"30":{"position":[[9523,5]]},"199":{"position":[[182,4],[354,4]]}},"keywords":{}}],["loos",{"_index":3448,"title":{},"content":{"98":{"position":[[643,5]]}},"keywords":{}}],["lose",{"_index":1580,"title":{},"content":{"33":{"position":[[962,4]]},"102":{"position":[[1353,6]]}},"keywords":{}}],["lossi",{"_index":3475,"title":{},"content":{"101":{"position":[[544,5],[805,5]]},"102":{"position":[[208,5]]},"175":{"position":[[760,6]]}},"keywords":{}}],["lossless",{"_index":3470,"title":{},"content":{"101":{"position":[[337,8]]},"105":{"position":[[916,8]]}},"keywords":{}}],["lost",{"_index":3867,"title":{"121":{"position":[[0,4]]}},"content":{},"keywords":{}}],["lot",{"_index":1333,"title":{},"content":{"30":{"position":[[387,3]]},"33":{"position":[[699,3]]},"40":{"position":[[637,3],[674,3],[3076,3]]},"41":{"position":[[67,3]]},"51":{"position":[[44,3],[3204,3]]},"53":{"position":[[1650,3]]},"55":{"position":[[91,3]]},"68":{"position":[[58,3]]},"74":{"position":[[205,3]]},"90":{"position":[[108,3]]},"98":{"position":[[1223,3]]},"102":{"position":[[320,3]]},"104":{"position":[[1751,3],[1813,3]]},"106":{"position":[[296,3]]},"120":{"position":[[195,3]]},"121":{"position":[[2228,3]]},"122":{"position":[[807,3]]},"124":{"position":[[432,3]]},"125":{"position":[[3491,3],[7382,3],[9910,3],[10393,3],[10735,3]]},"130":{"position":[[261,3]]},"148":{"position":[[17,3]]},"153":{"position":[[168,3]]},"159":{"position":[[16,3]]},"161":{"position":[[1610,3]]},"174":{"position":[[298,3]]},"176":{"position":[[196,3]]},"188":{"position":[[59,3]]},"199":{"position":[[1112,3]]}},"keywords":{}}],["love",{"_index":2269,"title":{"153":{"position":[[31,4]]}},"content":{"53":{"position":[[1384,4]]},"124":{"position":[[139,4]]},"129":{"position":[[1408,4]]}},"keywords":{}}],["loveyoual",{"_index":2231,"title":{},"content":{"53":{"position":[[841,11]]}},"keywords":{}}],["low",{"_index":337,"title":{"128":{"position":[[0,3]]}},"content":{"6":{"position":[[513,3]]},"70":{"position":[[37,4],[1232,4]]},"71":{"position":[[24,4],[127,3]]},"78":{"position":[[51,4]]},"104":{"position":[[1256,3],[1512,3]]},"105":{"position":[[167,3]]},"127":{"position":[[1594,3]]},"128":{"position":[[923,3]]},"163":{"position":[[1353,5]]}},"keywords":{}}],["lower",{"_index":1371,"title":{},"content":{"30":{"position":[[2417,5],[4395,5]]}},"keywords":{}}],["lowest/highest",{"_index":4763,"title":{},"content":{"163":{"position":[[206,14]]}},"keywords":{}}],["lt",{"_index":822,"title":{},"content":{"20":{"position":[[1564,4]]},"24":{"position":[[1422,4],[1445,4]]},"25":{"position":[[1142,4],[1165,4]]},"76":{"position":[[2402,4],[2433,4],[3104,4]]},"91":{"position":[[3097,5]]},"93":{"position":[[2851,4]]},"96":{"position":[[179,4]]},"188":{"position":[[1028,5],[3567,5]]},"189":{"position":[[1117,5],[1387,5],[3111,5]]},"199":{"position":[[205,4]]}},"keywords":{}}],["lt;bspeice@kcg.com>"",{"_index":3689,"title":{},"content":{"109":{"position":[[346,30]]}},"keywords":{}}],["lt;matplotlib.axes._subplots.axessubplot",{"_index":2114,"title":{},"content":{"51":{"position":[[1785,41]]}},"keywords":{}}],["lt;t",{"_index":4288,"title":{},"content":{"129":{"position":[[624,5]]}},"keywords":{}}],["lt;url>",{"_index":3323,"title":{},"content":{"96":{"position":[[378,12]]}},"keywords":{}}],["luajit",{"_index":4926,"title":{},"content":{"172":{"position":[[1796,8]]}},"keywords":{}}],["luck",{"_index":4500,"title":{},"content":{"150":{"position":[[702,5]]}},"keywords":{}}],["lume",{"_index":207,"title":{},"content":{"3":{"position":[[1338,5]]}},"keywords":{}}],["lunch",{"_index":4494,"title":{},"content":{"150":{"position":[[414,6]]}},"keywords":{}}],["luxuri",{"_index":4498,"title":{},"content":{"150":{"position":[[570,6]]}},"keywords":{}}],["m",{"_index":370,"title":{},"content":{"6":{"position":[[1034,1]]},"7":{"position":[[326,1],[635,1],[675,2]]},"12":{"position":[[251,2],[566,2]]},"13":{"position":[[1347,2]]},"14":{"position":[[2419,2]]},"15":{"position":[[2091,2]]},"30":{"position":[[2039,1],[3445,1],[3533,1],[5289,1],[6519,1],[6607,1]]},"39":{"position":[[577,2],[592,2]]},"62":{"position":[[563,2],[1109,2]]},"64":{"position":[[567,2]]},"65":{"position":[[463,2]]},"88":{"position":[[759,2]]},"93":{"position":[[4174,2]]},"129":{"position":[[1976,1]]}},"keywords":{}}],["m)[0",{"_index":1361,"title":{},"content":{"30":{"position":[[2013,5],[3419,5],[5263,5],[6493,5]]}},"keywords":{}}],["m)[1",{"_index":1388,"title":{},"content":{"30":{"position":[[3507,5],[6581,5]]}},"keywords":{}}],["m.my_funct",{"_index":4307,"title":{},"content":{"129":{"position":[[1990,15]]}},"keywords":{}}],["m4a",{"_index":3479,"title":{},"content":{"101":{"position":[[595,6]]}},"keywords":{}}],["mac",{"_index":4372,"title":{},"content":{"134":{"position":[[50,4]]}},"keywords":{}}],["machin",{"_index":2622,"title":{},"content":{"73":{"position":[[193,7]]},"102":{"position":[[90,7]]},"189":{"position":[[162,7],[290,7],[367,7]]}},"keywords":{}}],["macro",{"_index":3346,"title":{"144":{"position":[[19,6]]},"145":{"position":[[16,6]]}},"content":{"96":{"position":[[1551,5],[1861,5]]},"121":{"position":[[1997,6],[2068,5],[2299,6],[2650,6]]},"147":{"position":[[596,5]]}},"keywords":{}}],["made",{"_index":49,"title":{},"content":{"1":{"position":[[562,4]]},"26":{"position":[[325,4]]},"34":{"position":[[1852,4],[3274,4]]},"36":{"position":[[12,4]]},"66":{"position":[[341,4]]},"71":{"position":[[1463,4]]},"76":{"position":[[1441,4]]},"172":{"position":[[1171,4]]}},"keywords":{}}],["magic",{"_index":5040,"title":{},"content":{"176":{"position":[[59,8]]}},"keywords":{}}],["magical."",{"_index":71,"title":{},"content":{"1":{"position":[[789,14]]}},"keywords":{}}],["magnitud",{"_index":4419,"title":{},"content":{"139":{"position":[[451,9]]}},"keywords":{}}],["main",{"_index":84,"title":{},"content":{"2":{"position":[[145,4]]},"76":{"position":[[1814,4]]},"111":{"position":[[327,6]]},"113":{"position":[[729,6]]},"115":{"position":[[112,6]]},"116":{"position":[[212,6]]},"117":{"position":[[1004,6]]},"127":{"position":[[587,4],[1237,4]]},"128":{"position":[[263,6],[441,5],[1135,6]]},"129":{"position":[[421,6],[1533,6]]},"135":{"position":[[373,4]]},"136":{"position":[[225,4]]},"144":{"position":[[283,6]]},"145":{"position":[[141,6]]},"146":{"position":[[169,6]]},"147":{"position":[[317,6]]},"152":{"position":[[1057,5],[1109,6]]},"153":{"position":[[750,6]]},"156":{"position":[[919,6],[1154,4]]},"160":{"position":[[261,7]]},"164":{"position":[[1216,4]]},"179":{"position":[[568,6],[976,6],[1284,6]]},"180":{"position":[[237,4]]},"184":{"position":[[314,6],[654,6]]},"186":{"position":[[337,6]]},"195":{"position":[[638,6]]}},"keywords":{}}],["main(str",{"_index":4231,"title":{},"content":{"127":{"position":[[613,13],[1263,13]]}},"keywords":{}}],["main.java:5",{"_index":4233,"title":{},"content":{"127":{"position":[[730,12]]}},"keywords":{}}],["main.r",{"_index":4368,"title":{},"content":{"133":{"position":[[242,8]]}},"keywords":{}}],["maintain",{"_index":809,"title":{},"content":{"20":{"position":[[1149,8]]},"122":{"position":[[1338,8]]},"123":{"position":[[168,10]]},"125":{"position":[[10278,8]]},"164":{"position":[[163,11]]}},"keywords":{}}],["maintained.chrono",{"_index":3953,"title":{},"content":{"122":{"position":[[1132,17]]}},"keywords":{}}],["mainten",{"_index":3965,"title":{"123":{"position":[[6,11]]}},"content":{},"keywords":{}}],["make",{"_index":216,"title":{"113":{"position":[[8,6]]},"161":{"position":[[0,6]]}},"content":{"3":{"position":[[1532,4]]},"7":{"position":[[4,4]]},"9":{"position":[[57,6]]},"23":{"position":[[199,4]]},"25":{"position":[[2791,4]]},"26":{"position":[[143,5]]},"32":{"position":[[323,4],[742,4],[962,4],[1029,4],[1345,4],[2167,4],[2344,4]]},"33":{"position":[[111,4],[451,4],[569,4],[740,4],[887,4]]},"34":{"position":[[95,4],[883,4],[961,4],[3576,4]]},"35":{"position":[[171,4]]},"36":{"position":[[68,6]]},"38":{"position":[[66,6],[343,4],[1041,6]]},"39":{"position":[[306,4],[1784,4]]},"43":{"position":[[157,4],[1044,4],[1185,4]]},"53":{"position":[[549,4],[2033,4],[2129,4]]},"61":{"position":[[495,4],[1257,4]]},"63":{"position":[[91,4]]},"66":{"position":[[187,6]]},"68":{"position":[[84,4],[681,5],[717,4],[782,4]]},"69":{"position":[[240,4]]},"75":{"position":[[1145,4]]},"76":{"position":[[899,4],[1367,4]]},"81":{"position":[[42,4]]},"85":{"position":[[493,5]]},"90":{"position":[[484,4]]},"91":{"position":[[2185,4],[3215,4]]},"92":{"position":[[1027,4]]},"96":{"position":[[83,4]]},"97":{"position":[[325,5],[709,6],[5975,6]]},"101":{"position":[[628,4]]},"104":{"position":[[583,5],[1009,4],[1413,4]]},"106":{"position":[[910,4]]},"108":{"position":[[223,4],[701,4]]},"110":{"position":[[115,4]]},"111":{"position":[[55,4]]},"113":{"position":[[1245,4],[2309,4]]},"116":{"position":[[2768,6],[2868,4],[3107,4]]},"120":{"position":[[222,6],[684,4],[779,5],[1042,4]]},"121":{"position":[[577,4],[1252,4],[1897,4]]},"122":{"position":[[72,4]]},"123":{"position":[[231,4]]},"125":{"position":[[6207,4],[10370,4],[11185,4]]},"128":{"position":[[564,6]]},"129":{"position":[[2051,4]]},"132":{"position":[[393,6],[1021,4]]},"133":{"position":[[168,4]]},"135":{"position":[[4,4]]},"150":{"position":[[442,4]]},"153":{"position":[[223,4]]},"155":{"position":[[189,4]]},"156":{"position":[[1816,4]]},"158":{"position":[[410,4],[448,4]]},"160":{"position":[[1246,4]]},"161":{"position":[[635,5],[1726,6]]},"163":{"position":[[341,4]]},"164":{"position":[[1470,4]]},"165":{"position":[[1464,4]]},"166":{"position":[[299,4]]},"167":{"position":[[266,4]]},"170":{"position":[[61,6]]},"172":{"position":[[1614,5],[2525,4]]},"173":{"position":[[1825,4],[1973,6]]},"175":{"position":[[464,6],[706,4],[941,4]]},"176":{"position":[[403,4]]},"188":{"position":[[2886,5]]},"190":{"position":[[492,4]]},"192":{"position":[[335,5]]},"194":{"position":[[81,4]]},"196":{"position":[[1693,4]]}},"keywords":{}}],["make_lin",{"_index":5267,"title":{},"content":{"192":{"position":[[191,11]]}},"keywords":{}}],["maker",{"_index":1507,"title":{"31":{"position":[[17,5]]}},"content":{},"keywords":{}}],["malloc",{"_index":3364,"title":{},"content":{"97":{"position":[[269,8]]},"160":{"position":[[3504,8]]}},"keywords":{}}],["man",{"_index":2549,"title":{},"content":{"66":{"position":[[604,3]]},"121":{"position":[[2380,4]]}},"keywords":{}}],["manag",{"_index":1534,"title":{},"content":{"32":{"position":[[952,6]]},"97":{"position":[[200,10]]},"108":{"position":[[405,7]]},"121":{"position":[[919,7]]},"125":{"position":[[1962,6],[7039,6],[8138,7],[8298,7],[10085,7]]},"134":{"position":[[63,7]]},"148":{"position":[[64,8]]},"155":{"position":[[442,8],[640,6]]},"156":{"position":[[762,7]]},"160":{"position":[[729,11],[1004,7],[1960,6]]},"188":{"position":[[293,8],[4343,6]]},"190":{"position":[[937,6]]},"199":{"position":[[4,7]]}},"keywords":{}}],["managerexplicitli",{"_index":5155,"title":{},"content":{"188":{"position":[[530,17]]}},"keywords":{}}],["mani",{"_index":188,"title":{"64":{"position":[[4,4]]},"65":{"position":[[4,4]]}},"content":{"3":{"position":[[1058,4]]},"4":{"position":[[756,4]]},"30":{"position":[[1060,4],[2814,4],[4203,4],[4569,4]]},"44":{"position":[[1095,4]]},"51":{"position":[[1548,4],[2177,4]]},"58":{"position":[[294,4]]},"64":{"position":[[36,4],[282,4],[1253,4]]},"65":{"position":[[38,4],[81,4],[281,4],[1368,4],[1548,4],[2240,4]]},"66":{"position":[[346,4]]},"68":{"position":[[704,4]]},"74":{"position":[[1341,4]]},"89":{"position":[[278,4]]},"97":{"position":[[349,4],[2196,4],[2464,4]]},"102":{"position":[[1033,4]]},"156":{"position":[[293,4]]},"164":{"position":[[1527,4]]},"172":{"position":[[2093,4]]},"173":{"position":[[90,4]]},"175":{"position":[[1083,4]]}},"keywords":{}}],["manipul",{"_index":5269,"title":{},"content":{"192":{"position":[[651,12]]}},"keywords":{}}],["manner",{"_index":2095,"title":{},"content":{"51":{"position":[[984,6]]},"116":{"position":[[2943,7]]}},"keywords":{}}],["mannerth",{"_index":5153,"title":{},"content":{"188":{"position":[[502,9]]}},"keywords":{}}],["manual",{"_index":3362,"title":{},"content":{"97":{"position":[[186,6]]},"121":{"position":[[685,6]]},"125":{"position":[[9387,8]]}},"keywords":{}}],["map",{"_index":808,"title":{},"content":{"20":{"position":[[1122,3]]},"113":{"position":[[2130,3]]}},"keywords":{}}],["map(lambda",{"_index":3240,"title":{},"content":{"93":{"position":[[2765,10]]}},"keywords":{}}],["march",{"_index":2394,"title":{},"content":{"62":{"position":[[158,5],[1759,5]]}},"keywords":{}}],["margin",{"_index":1842,"title":{},"content":{"40":{"position":[[3630,7]]}},"keywords":{}}],["mark",{"_index":4441,"title":{},"content":{"143":{"position":[[97,6]]},"152":{"position":[[785,4],[882,6]]},"159":{"position":[[879,6]]},"184":{"position":[[875,6]]}},"keywords":{}}],["marker",{"_index":5114,"title":{"185":{"position":[[9,7]]}},"content":{"182":{"position":[[614,6]]},"185":{"position":[[82,7]]},"198":{"position":[[669,6]]}},"keywords":{}}],["market",{"_index":723,"title":{"88":{"position":[[4,6]]}},"content":{"17":{"position":[[335,6]]},"19":{"position":[[107,6]]},"24":{"position":[[408,7],[3003,6],[3186,7],[3324,6]]},"25":{"position":[[72,6],[2674,6]]},"26":{"position":[[355,6],[488,6],[697,6],[787,6]]},"32":{"position":[[217,7]]},"38":{"position":[[1124,6]]},"40":{"position":[[1280,7],[1582,7],[2545,8]]},"88":{"position":[[2095,6],[2229,6],[2308,6],[3583,6],[3789,6]]},"89":{"position":[[163,6],[416,6],[848,7]]},"91":{"position":[[1707,6],[4703,6],[4884,6],[5105,6],[5469,6]]},"93":{"position":[[83,7],[380,6],[488,7],[525,6],[638,6],[818,6]]},"163":{"position":[[75,6],[396,6],[2207,6],[2421,6]]}},"keywords":{}}],["market.pct_chang",{"_index":747,"title":{},"content":{"19":{"position":[[259,19]]}},"keywords":{}}],["market_return",{"_index":746,"title":{},"content":{"19":{"position":[[242,14]]}},"keywords":{}}],["market_returns[d_col].mean",{"_index":751,"title":{},"content":{"19":{"position":[[314,29]]}},"keywords":{}}],["market_tick",{"_index":715,"title":{},"content":{"17":{"position":[[190,13]]}},"keywords":{}}],["markov",{"_index":2298,"title":{},"content":{"55":{"position":[[105,6]]}},"keywords":{}}],["marri",{"_index":2277,"title":{},"content":{"53":{"position":[[1528,7]]}},"keywords":{}}],["martingal",{"_index":1508,"title":{"32":{"position":[[13,10]]}},"content":{"34":{"position":[[811,10]]}},"keywords":{}}],["marvel",{"_index":3842,"title":{},"content":{"118":{"position":[[147,6]]}},"keywords":{}}],["match",{"_index":282,"title":{},"content":{"4":{"position":[[1117,5]]},"7":{"position":[[181,5]]},"9":{"position":[[337,5]]},"24":{"position":[[1017,5],[1084,5],[1164,7],[1497,7],[1518,7],[1588,7]]},"25":{"position":[[737,5],[804,5],[884,7],[1217,7],[1238,7],[1308,7]]},"72":{"position":[[334,7]]},"75":{"position":[[329,7]]},"93":{"position":[[1764,5],[1806,6]]},"113":{"position":[[2324,5]]},"125":{"position":[[4303,5],[7995,6]]}},"keywords":{}}],["matches_dict",{"_index":1069,"title":{},"content":{"24":{"position":[[1617,12]]},"25":{"position":[[1316,12]]}},"keywords":{}}],["matches_dict[index",{"_index":1080,"title":{},"content":{"24":{"position":[[2011,19]]},"25":{"position":[[1735,19]]}},"keywords":{}}],["materi",{"_index":4735,"title":{},"content":{"161":{"position":[[510,9]]},"178":{"position":[[653,12]]}},"keywords":{}}],["math",{"_index":1519,"title":{},"content":{"32":{"position":[[431,5]]},"193":{"position":[[1403,4]]}},"keywords":{}}],["mathbb{e}[d_1",{"_index":2587,"title":{},"content":{"70":{"position":[[620,15],[684,14]]},"71":{"position":[[720,15],[784,14]]}},"keywords":{}}],["mathbb{e}[d_2",{"_index":2588,"title":{},"content":{"70":{"position":[[648,15]]},"71":{"position":[[748,15]]}},"keywords":{}}],["mathbb{e}[d_{fair",{"_index":2590,"title":{},"content":{"70":{"position":[[712,19]]},"71":{"position":[[812,19]]}},"keywords":{}}],["mathcal{l(\\mathbf{x",{"_index":2645,"title":{},"content":{"74":{"position":[[1074,23]]}},"keywords":{}}],["mathcal{l(x",{"_index":2635,"title":{},"content":{"74":{"position":[[555,14]]}},"keywords":{}}],["mathematician",{"_index":2816,"title":{},"content":{"83":{"position":[[585,14]]}},"keywords":{}}],["matplotlib",{"_index":1720,"title":{},"content":{"39":{"position":[[516,11]]},"43":{"position":[[338,11]]},"51":{"position":[[1657,11]]},"68":{"position":[[473,11]]},"88":{"position":[[544,11]]}},"keywords":{}}],["matplotlib.d",{"_index":2843,"title":{},"content":{"88":{"position":[[319,16],[405,16]]}},"keywords":{}}],["matplotlib.fin",{"_index":2845,"title":{},"content":{"88":{"position":[[357,18]]}},"keywords":{}}],["matplotlib.pyplot",{"_index":1717,"title":{},"content":{"39":{"position":[[460,17]]},"43":{"position":[[313,17]]},"51":{"position":[[1632,17]]},"68":{"position":[[448,17]]},"88":{"position":[[289,17]]}},"keywords":{}}],["matrix",{"_index":405,"title":{},"content":{"7":{"position":[[575,6]]},"43":{"position":[[1059,6]]},"106":{"position":[[237,6],[615,6],[722,7],[806,7],[842,6],[881,7]]}},"keywords":{}}],["matter",{"_index":2030,"title":{},"content":{"46":{"position":[[258,6]]},"74":{"position":[[1503,6]]},"139":{"position":[[592,7]]},"175":{"position":[[542,8],[1686,6]]},"176":{"position":[[1445,6]]},"194":{"position":[[583,6]]}},"keywords":{}}],["matters;data",{"_index":4918,"title":{},"content":{"172":{"position":[[1360,12]]}},"keywords":{}}],["matur",{"_index":573,"title":{},"content":{"13":{"position":[[913,9]]},"14":{"position":[[1325,9],[1931,9]]},"15":{"position":[[1599,9]]}},"keywords":{}}],["max",{"_index":701,"title":{},"content":{"17":{"position":[[7,3]]},"20":{"position":[[533,3],[583,4],[2678,3],[3004,3]]},"30":{"position":[[7137,3]]},"34":{"position":[[3415,3],[3806,3]]},"44":{"position":[[897,3]]},"90":{"position":[[1237,5],[1800,5],[2622,5],[2944,5]]}},"keywords":{}}],["max(close_vals[day",{"_index":1642,"title":{},"content":{"34":{"position":[[2584,20]]}},"keywords":{}}],["max(ev",{"_index":3033,"title":{},"content":{"90":{"position":[[3761,11]]}},"keywords":{}}],["max(events)+td",{"_index":3288,"title":{},"content":{"93":{"position":[[4988,15],[5403,15]]}},"keywords":{}}],["max(x[0",{"_index":1766,"title":{},"content":{"39":{"position":[[2772,10],[2932,10]]}},"keywords":{}}],["max_d1",{"_index":2730,"title":{},"content":{"76":{"position":[[2184,6],[2726,6],[3326,7]]},"78":{"position":[[253,7]]}},"keywords":{}}],["max_d2",{"_index":2731,"title":{},"content":{"76":{"position":[[2200,6],[2742,6],[3334,7]]},"78":{"position":[[261,7],[710,8]]}},"keywords":{}}],["max_err",{"_index":3003,"title":{},"content":{"90":{"position":[[1790,7],[1949,9],[2934,7],[3088,9]]}},"keywords":{}}],["max_it",{"_index":2734,"title":{},"content":{"76":{"position":[[2438,9],[2480,9]]}},"keywords":{}}],["max_iter=1e4",{"_index":2720,"title":{},"content":{"76":{"position":[[1921,14]]}},"keywords":{}}],["max_leverag",{"_index":1647,"title":{},"content":{"34":{"position":[[2806,12]]}},"keywords":{}}],["max_leverage)"",{"_index":1651,"title":{},"content":{"34":{"position":[[2885,22]]}},"keywords":{}}],["max_profit",{"_index":1641,"title":{},"content":{"34":{"position":[[2571,10],[2641,10]]}},"keywords":{}}],["max_scor",{"_index":2729,"title":{},"content":{"76":{"position":[[2162,9],[2693,10],[2704,9]]}},"keywords":{}}],["max_value=r3000_equities.index.max",{"_index":3267,"title":{},"content":{"93":{"position":[[3546,37]]}},"keywords":{}}],["maxim",{"_index":792,"title":{},"content":{"20":{"position":[[811,8]]}},"keywords":{}}],["maximum",{"_index":702,"title":{},"content":{"17":{"position":[[24,7]]},"20":{"position":[[32,7],[162,7]]},"30":{"position":[[7223,7]]},"76":{"position":[[2350,7]]},"86":{"position":[[273,8]]},"90":{"position":[[5256,7]]}},"keywords":{}}],["maximum(leverag",{"_index":1648,"title":{},"content":{"34":{"position":[[2821,18]]}},"keywords":{}}],["mayb",{"_index":209,"title":{},"content":{"3":{"position":[[1391,6]]},"29":{"position":[[179,5]]},"30":{"position":[[7936,5]]},"43":{"position":[[884,5]]},"97":{"position":[[4239,5],[4362,5]]},"124":{"position":[[530,5]]},"142":{"position":[[51,6]]},"161":{"position":[[295,5]]}},"keywords":{}}],["mb",{"_index":4402,"title":{},"content":{"136":{"position":[[961,2]]}},"keywords":{}}],["mean",{"_index":605,"title":{"149":{"position":[[28,5]]}},"content":{"13":{"position":[[1921,4],[1977,4],[2033,4],[2089,4],[2145,4],[2201,4]]},"14":{"position":[[2993,4],[3049,4],[3105,4],[3161,4],[3217,4],[3273,4]]},"15":{"position":[[2664,4],[2720,4],[2776,4],[2832,4],[2888,4],[2944,4]]},"26":{"position":[[295,5]]},"38":{"position":[[1137,5]]},"40":{"position":[[655,5]]},"44":{"position":[[818,4]]},"51":{"position":[[2634,5]]},"54":{"position":[[236,6]]},"75":{"position":[[5,5]]},"76":{"position":[[1149,5]]},"90":{"position":[[1098,5],[1433,6],[1485,6],[1535,6],[1567,6],[1684,6],[1716,6],[1808,6],[1841,6],[1910,6],[2483,5],[2783,6],[2828,6],[2860,6],[2952,6],[2985,6],[3049,6],[3423,5],[4774,4],[5082,4]]},"96":{"position":[[2073,6]]},"104":{"position":[[736,5],[830,5]]},"105":{"position":[[587,7],[720,5]]},"108":{"position":[[187,6]]},"121":{"position":[[730,5]]},"122":{"position":[[38,5],[727,5]]},"124":{"position":[[807,4]]},"161":{"position":[[857,5],[1699,4]]},"172":{"position":[[1099,8]]},"175":{"position":[[173,5],[1619,5]]},"198":{"position":[[595,5]]}},"keywords":{}}],["mean(mean_payoff",{"_index":594,"title":{},"content":{"13":{"position":[[1671,18]]},"14":{"position":[[2754,18]]},"15":{"position":[[2428,18]]}},"keywords":{}}],["mean(mean_payoffs))"",{"_index":597,"title":{},"content":{"13":{"position":[[1744,28]]},"14":{"position":[[2827,28]]},"15":{"position":[[2501,28]]}},"keywords":{}}],["mean(payoff",{"_index":585,"title":{},"content":{"13":{"position":[[1425,13]]},"14":{"position":[[2497,13]]},"15":{"position":[[2169,13]]}},"keywords":{}}],["mean_payoff",{"_index":586,"title":{},"content":{"13":{"position":[[1443,12]]},"14":{"position":[[2515,12]]},"15":{"position":[[2187,12]]}},"keywords":{}}],["mean_payoffs[i",{"_index":589,"title":{},"content":{"13":{"position":[[1511,15],[1631,16]]},"14":{"position":[[2583,15],[2714,16]]},"15":{"position":[[2255,15],[2388,16]]}},"keywords":{}}],["meant",{"_index":2837,"title":{},"content":{"86":{"position":[[1147,5]]},"91":{"position":[[188,5]]}},"keywords":{}}],["meanwhile,chrono",{"_index":3958,"title":{},"content":{"122":{"position":[[1244,16]]}},"keywords":{}}],["measur",{"_index":4618,"title":{},"content":{"158":{"position":[[68,9]]},"168":{"position":[[11,9]]},"169":{"position":[[11,9]]},"176":{"position":[[1025,10],[1572,7]]}},"keywords":{}}],["meati",{"_index":4801,"title":{},"content":{"164":{"position":[[31,5]]}},"keywords":{}}],["median",{"_index":4856,"title":{},"content":{"168":{"position":[[160,6]]},"169":{"position":[[274,6]]},"170":{"position":[[233,6]]}},"keywords":{}}],["medic",{"_index":2339,"title":{},"content":{"58":{"position":[[855,7]]},"66":{"position":[[112,7]]}},"keywords":{}}],["meet",{"_index":1596,"title":{},"content":{"34":{"position":[[580,4]]}},"keywords":{}}],["meets_dd",{"_index":841,"title":{},"content":{"20":{"position":[[2184,8]]}},"keywords":{}}],["meets_dd(x",{"_index":821,"title":{},"content":{"20":{"position":[[1514,12]]}},"keywords":{}}],["meets_sharp",{"_index":818,"title":{},"content":{"20":{"position":[[1447,12],[2143,12]]}},"keywords":{}}],["megabyt",{"_index":3466,"title":{},"content":{"101":{"position":[[77,9]]},"105":{"position":[[825,9]]},"195":{"position":[[402,9],[768,9]]}},"keywords":{}}],["melodi",{"_index":3557,"title":{},"content":{"104":{"position":[[547,9]]}},"keywords":{}}],["memori",{"_index":623,"title":{"14":{"position":[[16,6]]},"15":{"position":[[13,6]]},"154":{"position":[[29,6]]},"177":{"position":[[28,6]]},"183":{"position":[[0,6]]},"191":{"position":[[27,6]]}},"content":{"14":{"position":[[43,7],[2959,6],[3350,6]]},"15":{"position":[[18,6],[687,6],[1293,6],[2630,6],[3018,6]]},"22":{"position":[[2804,6]]},"97":{"position":[[193,6]]},"98":{"position":[[795,6],[1058,7]]},"127":{"position":[[1084,7]]},"128":{"position":[[221,7],[936,7],[1407,6],[1764,7]]},"130":{"position":[[217,6]]},"132":{"position":[[193,6],[343,6],[750,6],[1038,6]]},"135":{"position":[[22,6],[255,6]]},"136":{"position":[[738,6],[967,6]]},"137":{"position":[[77,7]]},"140":{"position":[[130,6]]},"153":{"position":[[63,6]]},"155":{"position":[[976,6],[1114,6],[1252,6]]},"156":{"position":[[27,6],[99,6],[134,6],[451,7]]},"159":{"position":[[378,6],[1219,7]]},"160":{"position":[[478,6],[722,6],[817,6],[983,6],[1012,6],[1429,7],[1730,7],[1838,7],[2234,6],[2780,6],[2863,6],[3050,6],[3149,6],[4521,6]]},"164":{"position":[[370,6]]},"172":{"position":[[780,7],[864,6],[1063,6],[1353,6],[1566,6],[1715,6]]},"173":{"position":[[2096,6],[2184,6]]},"174":{"position":[[432,6],[586,6],[632,6],[911,6]]},"178":{"position":[[573,6]]},"180":{"position":[[64,6],[242,6]]},"183":{"position":[[760,6]]},"192":{"position":[[83,6],[252,6],[365,6],[512,6],[644,6]]},"193":{"position":[[275,6],[456,6],[1677,6],[2043,7],[3147,6]]},"194":{"position":[[565,6]]},"195":{"position":[[690,6],[787,6],[916,6],[1016,6]]},"196":{"position":[[878,6],[1339,6]]},"198":{"position":[[184,6]]},"199":{"position":[[12,6],[907,7],[1663,6]]}},"keywords":{}}],["memory"",{"_index":4683,"title":{},"content":{"160":{"position":[[1985,12]]}},"keywords":{}}],["memory."th",{"_index":5063,"title":{},"content":{"179":{"position":[[52,16]]}},"keywords":{}}],["memory.al",{"_index":5112,"title":{},"content":{"182":{"position":[[563,10]]}},"keywords":{}}],["memory.collect",{"_index":4639,"title":{},"content":{"159":{"position":[[1033,18]]}},"keywords":{}}],["memory.lik",{"_index":5111,"title":{},"content":{"182":{"position":[[467,11]]}},"keywords":{}}],["memory.som",{"_index":4641,"title":{},"content":{"159":{"position":[[1113,11]]}},"keywords":{}}],["memory?"",{"_index":4349,"title":{},"content":{"132":{"position":[[493,13]]}},"keywords":{}}],["memory_coupon",{"_index":681,"title":{},"content":{"15":{"position":[[1319,14],[1441,14]]}},"keywords":{}}],["memoryand",{"_index":4676,"title":{},"content":{"160":{"position":[[1357,9]]}},"keywords":{}}],["mention",{"_index":1221,"title":{},"content":{"28":{"position":[[744,10]]},"51":{"position":[[213,10]]},"97":{"position":[[3219,8]]},"104":{"position":[[1045,9]]},"125":{"position":[[483,10],[1996,7],[9580,10]]},"163":{"position":[[2392,10]]},"166":{"position":[[565,9]]},"180":{"position":[[19,7]]}},"keywords":{}}],["messag",{"_index":3375,"title":{},"content":{"97":{"position":[[1616,10],[3586,8],[3838,8],[4656,8]]},"112":{"position":[[1187,7],[1419,8]]},"113":{"position":[[139,9],[779,7],[863,7],[1313,7],[1435,7],[1539,7],[1992,7]]},"115":{"position":[[194,7]]},"116":{"position":[[294,7],[2644,8],[3253,7]]},"117":{"position":[[419,8],[701,7],[1086,7],[1513,7],[2107,9]]},"163":{"position":[[111,7]]},"164":{"position":[[290,9],[401,7],[506,8],[757,8],[820,7],[945,9],[986,7],[1065,7],[1161,7]]},"165":{"position":[[212,10],[413,8],[630,7],[763,8],[781,7],[874,7],[1160,8],[1254,7],[1328,7]]},"166":{"position":[[358,7],[454,8]]},"168":{"position":[[29,7],[83,7]]},"169":{"position":[[29,7],[96,7]]},"170":{"position":[[403,7]]}},"keywords":{}}],["message;phantomdata",{"_index":3825,"title":{},"content":{"117":{"position":[[793,19]]}},"keywords":{}}],["messages:[messag",{"_index":4829,"title":{},"content":{"165":{"position":[[679,19]]}},"keywords":{}}],["met",{"_index":4489,"title":{},"content":{"150":{"position":[[138,3]]}},"keywords":{}}],["method",{"_index":2826,"title":{},"content":{"86":{"position":[[131,8],[1197,6]]},"97":{"position":[[3329,6],[3494,6],[3991,6],[4114,6],[6520,7]]},"106":{"position":[[488,6]]},"112":{"position":[[1552,8],[1625,8],[1682,7]]},"127":{"position":[[493,8],[965,7]]},"129":{"position":[[2100,10],[2739,7]]},"144":{"position":[[13,7]]},"179":{"position":[[501,6]]}},"keywords":{}}],["method='nearest",{"_index":2435,"title":{},"content":{"62":{"position":[[1461,17]]}},"keywords":{}}],["methodolog",{"_index":3102,"title":{},"content":{"91":{"position":[[1598,11]]}},"keywords":{}}],["metobserv",{"_index":557,"title":{},"content":{"13":{"position":[[499,11]]},"14":{"position":[[552,11]]}},"keywords":{}}],["metric",{"_index":1379,"title":{},"content":{"30":{"position":[[2777,6]]},"40":{"position":[[1069,7]]},"91":{"position":[[258,7]]}},"keywords":{}}],["metropoli",{"_index":2626,"title":{},"content":{"73":{"position":[[554,10]]}},"keywords":{}}],["mi",{"_index":4978,"title":{},"content":{"174":{"position":[[193,3]]}},"keywords":{}}],["micro",{"_index":4421,"title":{},"content":{"139":{"position":[[569,5]]}},"keywords":{}}],["microsecond",{"_index":4623,"title":{},"content":{"158":{"position":[[204,11]]}},"keywords":{}}],["microsoft",{"_index":4409,"title":{},"content":{"137":{"position":[[252,9]]}},"keywords":{}}],["microwav",{"_index":4739,"title":{},"content":{"161":{"position":[[780,9]]}},"keywords":{}}],["mid",{"_index":1834,"title":{},"content":{"40":{"position":[[3188,3]]}},"keywords":{}}],["middl",{"_index":5292,"title":{},"content":{"193":{"position":[[1802,6],[2757,6]]}},"keywords":{}}],["midnight",{"_index":1476,"title":{},"content":{"30":{"position":[[9172,8],[9282,9]]},"93":{"position":[[1923,8]]}},"keywords":{}}],["midpoint",{"_index":2333,"title":{},"content":{"58":{"position":[[428,8]]},"91":{"position":[[270,8],[597,8],[690,9],[893,8],[1053,8],[1154,9],[1369,8],[2863,9],[3018,9]]},"92":{"position":[[675,9],[830,9]]}},"keywords":{}}],["midpoints.shift(1",{"_index":3135,"title":{},"content":{"91":{"position":[[3030,18]]},"92":{"position":[[842,18]]}},"keywords":{}}],["midrang",{"_index":3549,"title":{},"content":{"103":{"position":[[2383,8]]}},"keywords":{}}],["might'v",{"_index":3940,"title":{},"content":{"122":{"position":[[383,8]]}},"keywords":{}}],["migrat",{"_index":5044,"title":{},"content":{"176":{"position":[[426,8]]}},"keywords":{}}],["million",{"_index":2477,"title":{},"content":{"64":{"position":[[1149,7]]},"65":{"position":[[1306,7]]}},"keywords":{}}],["mime",{"_index":4094,"title":{},"content":{"125":{"position":[[4330,4],[4498,4],[4592,4],[4714,4]]}},"keywords":{}}],["mimick",{"_index":3876,"title":{},"content":{"121":{"position":[[224,9]]}},"keywords":{}}],["min",{"_index":1925,"title":{},"content":{"44":{"position":[[845,3]]},"90":{"position":[[1274,4],[1866,4],[1976,5],[2659,4],[3010,4],[3115,5]]}},"keywords":{}}],["min(ev",{"_index":3032,"title":{},"content":{"90":{"position":[[3728,11]]},"93":{"position":[[4972,11],[5387,11]]}},"keywords":{}}],["min/max",{"_index":3166,"title":{},"content":{"91":{"position":[[4826,7]]},"92":{"position":[[1489,7]]}},"keywords":{}}],["min_err",{"_index":3005,"title":{},"content":{"90":{"position":[[1831,7],[2975,7]]}},"keywords":{}}],["mind",{"_index":17,"title":{},"content":{"1":{"position":[[171,5]]},"95":{"position":[[421,4]]},"97":{"position":[[5248,5]]},"123":{"position":[[788,4]]},"125":{"position":[[11613,4]]},"129":{"position":[[1747,4]]},"160":{"position":[[2103,5]]},"188":{"position":[[2837,4]]}},"keywords":{}}],["mindblown",{"_index":2243,"title":{},"content":{"53":{"position":[[1022,10]]}},"keywords":{}}],["mindshar",{"_index":3440,"title":{},"content":{"98":{"position":[[402,9]]}},"keywords":{}}],["minim",{"_index":804,"title":{},"content":{"20":{"position":[[1048,8],[1360,10],[1936,10],[2462,10]]},"125":{"position":[[9288,7]]}},"keywords":{}}],["minimize(object",{"_index":842,"title":{},"content":{"20":{"position":[[2207,19]]}},"keywords":{}}],["minimum",{"_index":2824,"title":{},"content":{"85":{"position":[[536,8]]},"90":{"position":[[5244,7]]},"172":{"position":[[649,7]]},"173":{"position":[[1278,7]]}},"keywords":{}}],["minor",{"_index":2543,"title":{},"content":{"66":{"position":[[351,5]]},"130":{"position":[[90,5]]}},"keywords":{}}],["minu",{"_index":740,"title":{},"content":{"19":{"position":[[97,5]]}},"keywords":{}}],["minut",{"_index":292,"title":{},"content":{"4":{"position":[[1356,8]]},"62":{"position":[[1267,7]]},"64":{"position":[[1280,7],[1323,7]]},"65":{"position":[[2206,6],[2245,7]]},"93":{"position":[[5088,7]]},"101":{"position":[[91,6]]},"121":{"position":[[2098,7]]}},"keywords":{}}],["minute_mean",{"_index":2483,"title":{},"content":{"64":{"position":[[1472,11],[1606,11]]},"65":{"position":[[2379,11]]}},"keywords":{}}],["minutes_left",{"_index":2530,"title":{},"content":{"65":{"position":[[2346,12]]}},"keywords":{}}],["mirror",{"_index":4340,"title":{},"content":{"132":{"position":[[70,6]]}},"keywords":{}}],["miss",{"_index":96,"title":{},"content":{"2":{"position":[[339,8]]},"28":{"position":[[2441,7],[4054,7]]},"30":{"position":[[2721,7]]},"62":{"position":[[1280,7]]},"91":{"position":[[3955,7]]},"97":{"position":[[4266,8]]},"121":{"position":[[2404,4]]},"125":{"position":[[6462,7]]}},"keywords":{}}],["mistak",{"_index":75,"title":{},"content":{"2":{"position":[[21,8]]},"3":{"position":[[22,8]]},"66":{"position":[[357,9]]},"98":{"position":[[835,7]]},"127":{"position":[[413,8]]},"136":{"position":[[211,8]]},"158":{"position":[[415,9]]}},"keywords":{}}],["mitig",{"_index":5055,"title":{},"content":{"176":{"position":[[1584,8]]}},"keywords":{}}],["mix",{"_index":281,"title":{},"content":{"4":{"position":[[1109,3]]},"66":{"position":[[415,3]]},"121":{"position":[[1019,5]]},"125":{"position":[[10685,6]]},"147":{"position":[[88,6]]}},"keywords":{}}],["mkdir",{"_index":3680,"title":{},"content":{"109":{"position":[[128,5]]},"110":{"position":[[348,5]]}},"keywords":{}}],["mle",{"_index":2120,"title":{},"content":{"51":{"position":[[2087,3],[2109,3]]}},"keywords":{}}],["mod",{"_index":3732,"title":{},"content":{"113":{"position":[[444,3]]}},"keywords":{}}],["mode",{"_index":4444,"title":{},"content":{"143":{"position":[[437,4]]},"160":{"position":[[3663,4]]},"189":{"position":[[531,4],[802,4],[1234,4]]}},"keywords":{}}],["mode=develop",{"_index":4118,"title":{},"content":{"125":{"position":[[5403,16],[5528,16]]}},"keywords":{}}],["mode=product",{"_index":4129,"title":{},"content":{"125":{"position":[[5990,15]]}},"keywords":{}}],["model",{"_index":458,"title":{},"content":{"9":{"position":[[104,6]]},"43":{"position":[[112,5]]},"45":{"position":[[687,5],[865,5],[1253,5],[1295,5],[1508,5],[1674,6],[1865,5]]},"46":{"position":[[270,5]]},"53":{"position":[[1853,7]]},"73":{"position":[[447,5]]},"82":{"position":[[1298,5]]},"86":{"position":[[801,8]]},"160":{"position":[[4528,6]]}},"keywords":{}}],["modern",{"_index":267,"title":{},"content":{"4":{"position":[[885,6]]},"174":{"position":[[54,6],[1135,6]]},"176":{"position":[[356,6]]}},"keywords":{}}],["modif",{"_index":2694,"title":{},"content":{"76":{"position":[[911,14]]}},"keywords":{}}],["modifi",{"_index":2664,"title":{},"content":{"75":{"position":[[486,6]]},"125":{"position":[[2318,8]]},"179":{"position":[[268,6],[521,6]]},"186":{"position":[[553,8]]}},"keywords":{}}],["modify.valu",{"_index":5060,"title":{},"content":{"178":{"position":[[601,13]]}},"keywords":{}}],["modul",{"_index":210,"title":{},"content":{"3":{"position":[[1409,6]]},"4":{"position":[[798,7],[1233,8]]},"113":{"position":[[369,6]]},"125":{"position":[[8513,6],[8981,6],[11237,6]]}},"keywords":{}}],["modules"",{"_index":4165,"title":{},"content":{"125":{"position":[[8432,13]]}},"keywords":{}}],["moistur",{"_index":4751,"title":{},"content":{"161":{"position":[[1194,8]]}},"keywords":{}}],["moment",{"_index":1316,"title":{},"content":{"29":{"position":[[294,7]]},"51":{"position":[[1052,7]]},"64":{"position":[[2016,6]]},"97":{"position":[[1008,7]]},"125":{"position":[[3590,7],[7362,7],[10717,7],[10863,7]]},"150":{"position":[[901,8]]},"175":{"position":[[329,6]]}},"keywords":{}}],["monday",{"_index":2850,"title":{},"content":{"88":{"position":[[473,6],[1189,7]]},"90":{"position":[[3623,6]]}},"keywords":{}}],["money",{"_index":1165,"title":{"31":{"position":[[11,5]]}},"content":{"25":{"position":[[2796,5]]},"26":{"position":[[313,5],[684,5]]},"32":{"position":[[328,5],[602,5],[751,6],[1034,6],[1188,5],[1302,5],[1350,6],[1400,5],[2181,5],[2349,6]]},"33":{"position":[[116,5],[264,5],[574,5],[892,5],[1070,5]]},"34":{"position":[[888,6],[966,5]]},"35":{"position":[[176,6],[247,5]]},"36":{"position":[[75,5]]},"38":{"position":[[348,5]]}},"keywords":{}}],["money"",{"_index":1513,"title":{},"content":{"32":{"position":[[82,11]]}},"keywords":{}}],["money.it'",{"_index":1581,"title":{},"content":{"33":{"position":[[967,10]]}},"keywords":{}}],["monkey'",{"_index":3473,"title":{},"content":{"101":{"position":[[389,8]]}},"keywords":{}}],["monomorph",{"_index":5337,"title":{},"content":{"197":{"position":[[57,18],[706,17]]}},"keywords":{}}],["monorepo",{"_index":146,"title":{},"content":{"3":{"position":[[286,8]]}},"keywords":{}}],["mont",{"_index":2300,"title":{},"content":{"55":{"position":[[118,5]]}},"keywords":{}}],["month",{"_index":415,"title":{},"content":{"7":{"position":[[755,6]]},"28":{"position":[[1235,7],[1289,6],[1323,5],[1808,7],[1856,6],[1879,6],[1976,6],[1995,7],[2459,6],[2567,6],[2735,6],[3035,7],[3089,6],[3123,5],[3560,7],[3604,6],[3631,6],[3650,7],[4205,6]]},"30":{"position":[[556,6],[1372,6],[1601,7],[1655,6],[1689,5],[2044,7],[2950,7],[3004,6],[3038,5],[3450,7],[3538,7],[4554,6],[4588,5],[4874,7],[4928,6],[4962,5],[5294,7],[5597,5],[5654,6],[5720,6],[6018,7],[6072,6],[6106,5],[6524,7],[6612,7],[7322,7],[7470,6]]},"57":{"position":[[571,7]]},"58":{"position":[[728,6]]},"63":{"position":[[73,6]]},"64":{"position":[[289,5]]},"66":{"position":[[242,7]]},"123":{"position":[[463,6]]},"124":{"position":[[671,5]]},"125":{"position":[[2241,7],[10835,6]]}},"keywords":{}}],["month_averag",{"_index":1268,"title":{},"content":{"28":{"position":[[2003,14],[3658,14]]}},"keywords":{}}],["month_averages[c",{"_index":1276,"title":{},"content":{"28":{"position":[[2251,22],[3924,22]]}},"keywords":{}}],["month_id",{"_index":1267,"title":{},"content":{"28":{"position":[[1983,8],[2045,9],[3638,8],[3700,9]]}},"keywords":{}}],["monthli",{"_index":1370,"title":{},"content":{"30":{"position":[[2313,7],[2905,7]]}},"keywords":{}}],["monthly_avg_cloudcover(c",{"_index":1239,"title":{},"content":{"28":{"position":[[1200,28],[1823,29]]}},"keywords":{}}],["monthly_avg_cloudcover(i",{"_index":1360,"title":{},"content":{"30":{"position":[[1985,27]]}},"keywords":{}}],["monthly_avg_cloudcover(year",{"_index":1357,"title":{},"content":{"30":{"position":[[1572,28]]}},"keywords":{}}],["monthly_avg_precip(c",{"_index":1298,"title":{},"content":{"28":{"position":[[3004,24],[3575,25]]}},"keywords":{}}],["monthly_avg_precip(i",{"_index":1407,"title":{},"content":{"30":{"position":[[5239,23]]}},"keywords":{}}],["monthly_avg_precip(year",{"_index":1404,"title":{},"content":{"30":{"position":[[4849,24]]}},"keywords":{}}],["monthly_avg_precip_v",{"_index":1406,"title":{},"content":{"30":{"position":[[5213,23]]}},"keywords":{}}],["monthly_avg_precip_vals[x",{"_index":1408,"title":{},"content":{"30":{"position":[[5448,27]]}},"keywords":{}}],["monthly_cloudy_days(i",{"_index":1386,"title":{},"content":{"30":{"position":[[3394,24],[3482,24]]}},"keywords":{}}],["monthly_cloudy_days(year",{"_index":1382,"title":{},"content":{"30":{"position":[[2924,25]]}},"keywords":{}}],["monthly_cover_sampl",{"_index":1387,"title":{},"content":{"30":{"position":[[3458,21]]}},"keywords":{}}],["monthly_cover_samples[x",{"_index":1391,"title":{},"content":{"30":{"position":[[3894,25]]}},"keywords":{}}],["monthly_cover_v",{"_index":1359,"title":{},"content":{"30":{"position":[[1964,18]]}},"keywords":{}}],["monthly_cover_vals[x",{"_index":1366,"title":{},"content":{"30":{"position":[[2189,22]]}},"keywords":{}}],["monthly_days_v",{"_index":1385,"title":{},"content":{"30":{"position":[[3374,17]]}},"keywords":{}}],["monthly_days_vals[x",{"_index":1389,"title":{},"content":{"30":{"position":[[3675,21]]}},"keywords":{}}],["monthly_precip_days_v",{"_index":1423,"title":{},"content":{"30":{"position":[[6442,24]]}},"keywords":{}}],["monthly_precip_days_vals[x",{"_index":1426,"title":{},"content":{"30":{"position":[[6748,28]]}},"keywords":{}}],["monthly_precip_sampl",{"_index":1425,"title":{},"content":{"30":{"position":[[6532,22]]}},"keywords":{}}],["monthly_precip_samples[x",{"_index":1427,"title":{},"content":{"30":{"position":[[6973,26]]}},"keywords":{}}],["monthly_rainy_days(i",{"_index":1424,"title":{},"content":{"30":{"position":[[6469,23],[6557,23]]}},"keywords":{}}],["monthly_rainy_days(year",{"_index":1417,"title":{},"content":{"30":{"position":[[5993,24]]}},"keywords":{}}],["months_str",{"_index":1356,"title":{},"content":{"30":{"position":[[1394,10]]}},"keywords":{}}],["moore'",{"_index":4406,"title":{},"content":{"137":{"position":[[185,7]]}},"keywords":{}}],["morbid",{"_index":2315,"title":{},"content":{"57":{"position":[[413,8]]}},"keywords":{}}],["more",{"_index":239,"title":{"105":{"position":[[2,4]]},"149":{"position":[[0,4]]}},"content":{"4":{"position":[[411,4],[600,4]]},"9":{"position":[[77,4]]},"12":{"position":[[175,4]]},"24":{"position":[[331,4]]},"26":{"position":[[81,4],[913,4]]},"28":{"position":[[2624,4]]},"29":{"position":[[220,4]]},"30":{"position":[[576,4],[2772,4],[4085,4],[5603,4],[5734,4],[7581,4],[7734,5],[9195,4]]},"33":{"position":[[6,4]]},"34":{"position":[[330,4]]},"35":{"position":[[299,4]]},"40":{"position":[[887,4],[932,4],[2099,4],[3498,4]]},"43":{"position":[[828,4]]},"44":{"position":[[1975,4]]},"45":{"position":[[1477,4]]},"46":{"position":[[568,4]]},"51":{"position":[[854,4],[969,4]]},"53":{"position":[[321,4],[1654,4]]},"55":{"position":[[203,4]]},"57":{"position":[[389,4]]},"61":{"position":[[1593,4]]},"68":{"position":[[181,4]]},"70":{"position":[[1380,5]]},"71":{"position":[[1492,4]]},"72":{"position":[[431,4]]},"73":{"position":[[136,4]]},"74":{"position":[[244,4]]},"86":{"position":[[538,4]]},"91":{"position":[[5122,4]]},"93":{"position":[[888,4],[943,4],[1143,4]]},"95":{"position":[[303,4]]},"97":{"position":[[1210,4],[2469,4],[4065,4]]},"98":{"position":[[1163,5]]},"101":{"position":[[610,4],[686,4]]},"104":{"position":[[32,4],[1303,4]]},"105":{"position":[[2871,4]]},"106":{"position":[[1149,4]]},"108":{"position":[[557,4]]},"121":{"position":[[803,4],[2758,4]]},"122":{"position":[[102,4]]},"124":{"position":[[850,5]]},"125":{"position":[[415,4],[2096,4],[3621,4],[6960,4]]},"129":{"position":[[765,4]]},"139":{"position":[[461,4]]},"141":{"position":[[303,4]]},"145":{"position":[[25,4]]},"148":{"position":[[21,4],[426,4]]},"155":{"position":[[668,4],[885,4]]},"156":{"position":[[94,4]]},"161":{"position":[[86,4],[1614,4]]},"163":{"position":[[2176,4]]},"170":{"position":[[442,4]]},"172":{"position":[[553,4]]},"174":{"position":[[627,4],[949,4],[1014,4],[1150,4]]},"182":{"position":[[314,4]]},"185":{"position":[[338,4]]},"188":{"position":[[266,5],[4314,4]]},"190":{"position":[[109,4]]},"195":{"position":[[513,5]]},"199":{"position":[[1433,4]]}},"keywords":{}}],["morn",{"_index":2198,"title":{},"content":{"53":{"position":[[206,8]]}},"keywords":{}}],["mostli",{"_index":1373,"title":{},"content":{"30":{"position":[[2467,6],[7345,6]]},"41":{"position":[[164,6]]},"57":{"position":[[223,6]]},"91":{"position":[[3192,6]]},"92":{"position":[[1004,6]]},"97":{"position":[[2644,8]]},"124":{"position":[[592,6]]},"125":{"position":[[2849,6],[3272,6]]},"155":{"position":[[552,6]]}},"keywords":{}}],["moststruct",{"_index":5134,"title":{},"content":{"185":{"position":[[203,10]]}},"keywords":{}}],["motion",{"_index":392,"title":{},"content":{"7":{"position":[[351,6],[519,6],[604,6]]},"8":{"position":[[164,6]]},"9":{"position":[[30,6]]},"12":{"position":[[48,6]]},"13":{"position":[[1312,6]]},"14":{"position":[[2384,6]]},"15":{"position":[[2056,6]]}},"keywords":{}}],["motion[:,1",{"_index":394,"title":{},"content":{"7":{"position":[[372,11]]}},"keywords":{}}],["motion[:,i",{"_index":397,"title":{},"content":{"7":{"position":[[442,11]]}},"keywords":{}}],["motion[:,i+1",{"_index":396,"title":{},"content":{"7":{"position":[[426,13]]}},"keywords":{}}],["mov",{"_index":4257,"title":{},"content":{"128":{"position":[[456,3],[519,3],[627,3],[654,3],[725,3],[768,3],[866,3],[980,3],[1414,3],[1584,3]]},"129":{"position":[[539,3],[582,3],[676,3]]},"181":{"position":[[169,4],[296,4],[428,3]]},"193":{"position":[[3490,5]]}},"keywords":{}}],["move",{"_index":108,"title":{"54":{"position":[[0,6]]},"115":{"position":[[11,4]]}},"content":{"2":{"position":[[474,6]]},"3":{"position":[[212,6]]},"14":{"position":[[7,4]]},"24":{"position":[[3166,4]]},"28":{"position":[[2812,4]]},"33":{"position":[[999,4]]},"63":{"position":[[163,4]]},"65":{"position":[[1241,4]]},"90":{"position":[[5367,5]]},"91":{"position":[[4606,4],[5455,5],[5813,4]]},"97":{"position":[[1556,4],[4768,6],[4870,4],[4999,4],[5121,4]]},"115":{"position":[[53,4],[537,4]]},"116":{"position":[[668,4]]},"117":{"position":[[978,4],[1942,6]]},"123":{"position":[[129,6],[314,7],[882,6]]},"125":{"position":[[2484,6]]},"152":{"position":[[170,4]]},"173":{"position":[[2059,5]]},"175":{"position":[[1285,4]]},"192":{"position":[[438,4]]},"193":{"position":[[3027,6],[3213,6]]},"195":{"position":[[994,4]]},"196":{"position":[[1124,4]]},"198":{"position":[[15,4],[363,5],[880,4]]}},"keywords":{}}],["mozilla/5.0",{"_index":3222,"title":{},"content":{"93":{"position":[[2357,12]]}},"keywords":{}}],["mp3",{"_index":3476,"title":{},"content":{"101":{"position":[[577,4]]},"102":{"position":[[712,4]]},"104":{"position":[[1719,4]]}},"keywords":{}}],["mpsc",{"_index":3837,"title":{},"content":{"117":{"position":[[2017,4]]}},"keywords":{}}],["ms",{"_index":5173,"title":{},"content":{"188":{"position":[[1594,3],[1620,2],[1638,2],[1692,3],[1718,2],[1736,2],[2261,3],[2275,3],[2290,2],[2308,2],[2578,3],[2606,2],[2624,2],[3116,3],[3142,2],[3160,2]]},"189":{"position":[[1782,3],[1810,2],[1828,2],[2237,3],[2251,3],[2266,2],[2284,2],[2520,3],[2534,3],[2549,2],[2567,2],[2809,3],[2835,2],[2853,2]]}},"keywords":{}}],["mu",{"_index":779,"title":{},"content":{"20":{"position":[[596,3]]}},"keywords":{}}],["much",{"_index":382,"title":{},"content":{"7":{"position":[[124,4]]},"18":{"position":[[27,4]]},"32":{"position":[[366,4],[931,5],[1395,4]]},"33":{"position":[[818,4]]},"34":{"position":[[222,4],[797,4],[937,4]]},"35":{"position":[[59,4]]},"40":{"position":[[2178,4]]},"43":{"position":[[1204,4]]},"44":{"position":[[977,4]]},"57":{"position":[[698,4]]},"66":{"position":[[567,4],[860,4]]},"74":{"position":[[1179,4]]},"82":{"position":[[1070,4]]},"83":{"position":[[401,4]]},"86":{"position":[[1064,4]]},"88":{"position":[[958,4],[3813,4]]},"90":{"position":[[18,4],[5331,4]]},"93":{"position":[[1138,4]]},"95":{"position":[[298,4],[540,4]]},"97":{"position":[[2321,4]]},"101":{"position":[[277,4]]},"105":{"position":[[404,4]]},"111":{"position":[[806,4],[909,4]]},"120":{"position":[[1098,4]]},"125":{"position":[[252,4],[818,4],[5738,4],[7241,4],[10608,4]]},"127":{"position":[[56,4]]},"132":{"position":[[261,4]]},"135":{"position":[[161,4],[250,4]]},"153":{"position":[[24,4]]},"160":{"position":[[2720,4],[3144,4],[3392,4]]},"182":{"position":[[309,4]]},"188":{"position":[[2718,5]]},"194":{"position":[[560,4]]}},"keywords":{}}],["mul",{"_index":5117,"title":{},"content":{"183":{"position":[[382,4],[528,4]]}},"keywords":{}}],["multi",{"_index":1716,"title":{},"content":{"39":{"position":[[376,5]]},"173":{"position":[[1980,5]]}},"keywords":{}}],["multicast",{"_index":5022,"title":{},"content":{"175":{"position":[[926,10]]}},"keywords":{}}],["multimessag",{"_index":4828,"title":{},"content":{"165":{"position":[[664,12],[723,12],[930,13]]}},"keywords":{}}],["multinom_sim(1",{"_index":2161,"title":{},"content":{"51":{"position":[[4015,15],[4200,15]]}},"keywords":{}}],["multinom_sim(n",{"_index":2149,"title":{},"content":{"51":{"position":[[3610,15],[3870,15]]}},"keywords":{}}],["multinomi",{"_index":2142,"title":{},"content":{"51":{"position":[[3170,11]]}},"keywords":{}}],["multipl",{"_index":1839,"title":{},"content":{"40":{"position":[[3518,8]]},"43":{"position":[[866,8]]},"86":{"position":[[301,8]]},"121":{"position":[[1532,8]]},"193":{"position":[[606,8]]}},"keywords":{}}],["multipli",{"_index":851,"title":{},"content":{"20":{"position":[[2416,8]]},"64":{"position":[[1292,8]]},"74":{"position":[[1329,8]]},"183":{"position":[[694,11]]}},"keywords":{}}],["multiply(valu",{"_index":5095,"title":{},"content":{"180":{"position":[[425,15]]},"181":{"position":[[105,15]]},"183":{"position":[[330,15]]}},"keywords":{}}],["multiply_twic",{"_index":5102,"title":{},"content":{"181":{"position":[[478,14]]}},"keywords":{}}],["multiply_twice(valu",{"_index":5099,"title":{},"content":{"181":{"position":[[221,21]]},"183":{"position":[[470,21]]}},"keywords":{}}],["music",{"_index":2263,"title":{},"content":{"53":{"position":[[1285,5],[2000,5]]},"100":{"position":[[189,6]]},"104":{"position":[[1672,5]]}},"keywords":{}}],["mustcontext",{"_index":4960,"title":{},"content":{"173":{"position":[[1140,11]]}},"keywords":{}}],["mut",{"_index":3384,"title":{},"content":{"97":{"position":[[1909,3]]},"112":{"position":[[1362,3],[1375,3],[1398,3]]},"113":{"position":[[944,3],[1348,3],[1594,3]]},"152":{"position":[[1362,4],[1512,4]]},"156":{"position":[[1445,4],[1595,4]]},"179":{"position":[[117,3]]},"186":{"position":[[23,3]]},"199":{"position":[[1276,3],[1419,3],[1577,3]]}},"keywords":{}}],["mut.refcel",{"_index":5067,"title":{},"content":{"179":{"position":[[303,11]]}},"keywords":{}}],["mutabl",{"_index":3740,"title":{"186":{"position":[[9,11]]}},"content":{"113":{"position":[[1019,7],[1119,7]]},"136":{"position":[[540,7]]},"179":{"position":[[254,10],[806,10]]},"182":{"position":[[636,10]]},"186":{"position":[[141,10]]}},"keywords":{}}],["mutat",{"_index":5137,"title":{},"content":{"186":{"position":[[50,8],[421,6]]}},"keywords":{}}],["mutex",{"_index":4638,"title":{},"content":{"159":{"position":[[988,6]]}},"keywords":{}}],["my_appl",{"_index":4374,"title":{},"content":{"134":{"position":[[157,14]]}},"keywords":{}}],["my_arc",{"_index":4584,"title":{},"content":{"155":{"position":[[1470,8]]}},"keywords":{}}],["my_box",{"_index":4578,"title":{},"content":{"155":{"position":[[1346,8]]}},"keywords":{}}],["my_cow",{"_index":4587,"title":{},"content":{"155":{"position":[[1533,8]]}},"keywords":{}}],["my_func",{"_index":5332,"title":{},"content":{"196":{"position":[[940,9],[1162,12],[1175,12],[1559,10],[1578,10],[1761,10],[1780,10]]}},"keywords":{}}],["my_funct",{"_index":4263,"title":{},"content":{"128":{"position":[[594,13],[674,13],[713,11],[746,12],[1344,13],[1432,13]]},"140":{"position":[[4,13]]},"141":{"position":[[4,13]]}},"keywords":{}}],["my_function(int",{"_index":4249,"title":{},"content":{"128":{"position":[[235,15]]}},"keywords":{}}],["my_function(self",{"_index":4305,"title":{},"content":{"129":{"position":[[1943,18]]}},"keywords":{}}],["my_function(v",{"_index":4439,"title":{},"content":{"142":{"position":[[4,14]]}},"keywords":{}}],["my_function(x",{"_index":4251,"title":{},"content":{"128":{"position":[[283,15],[1109,14],[1155,14]]}},"keywords":{}}],["my_lock",{"_index":5131,"title":{},"content":{"184":{"position":[[1117,8]]}},"keywords":{}}],["my_mutator(&cel",{"_index":5075,"title":{},"content":{"179":{"position":[[663,22],[1066,22]]}},"keywords":{}}],["my_mutator(cel",{"_index":5069,"title":{},"content":{"179":{"position":[[390,16],[910,16]]}},"keywords":{}}],["my_rc",{"_index":4581,"title":{},"content":{"155":{"position":[[1409,7]]}},"keywords":{}}],["my_struct",{"_index":5122,"title":{},"content":{"184":{"position":[[182,10],[367,11],[612,10],[716,11]]},"185":{"position":[[798,10]]}},"keywords":{}}],["my_val",{"_index":4299,"title":{},"content":{"129":{"position":[[1546,6]]},"184":{"position":[[276,6],[293,7]]}},"keywords":{}}],["my_val.to_str",{"_index":4300,"title":{},"content":{"129":{"position":[[1593,19]]}},"keywords":{}}],["my_vec",{"_index":4598,"title":{},"content":{"156":{"position":[[630,8]]}},"keywords":{}}],["myclass",{"_index":4304,"title":{},"content":{"129":{"position":[[1921,10],[1980,9]]}},"keywords":{}}],["myclass.my_function(m",{"_index":4308,"title":{},"content":{"129":{"position":[[2006,22]]}},"keywords":{}}],["myenum",{"_index":5311,"title":{},"content":{"194":{"position":[[224,6],[278,7],[289,7]]}},"keywords":{}}],["myenum::large(0",{"_index":5316,"title":{},"content":{"194":{"position":[[357,17]]}},"keywords":{}}],["myenum::small(0",{"_index":5315,"title":{},"content":{"194":{"position":[[331,17]]}},"keywords":{}}],["myself",{"_index":232,"title":{},"content":{"4":{"position":[[225,7]]},"35":{"position":[[485,8]]},"45":{"position":[[1813,8]]},"121":{"position":[[936,6]]},"125":{"position":[[192,6],[8163,6]]}},"keywords":{}}],["mystruct",{"_index":5121,"title":{},"content":{"184":{"position":[[155,8],[193,8],[204,8],[345,9],[514,8],[539,8],[571,8],[582,8],[623,8],[694,9]]},"185":{"position":[[477,8],[660,8],[809,8],[820,8]]},"194":{"position":[[264,8],[383,8]]}},"keywords":{}}],["mystruct::new",{"_index":5125,"title":{},"content":{"184":{"position":[[634,16]]}},"keywords":{}}],["myval",{"_index":4296,"title":{},"content":{"129":{"position":[[1434,5],[1456,5],[1555,5]]}},"keywords":{}}],["myval::to_string(&my_v",{"_index":4301,"title":{},"content":{"129":{"position":[[1613,30]]}},"keywords":{}}],["n",{"_index":367,"title":{"91":{"position":[[42,1]]},"92":{"position":[[30,1]]}},"content":{"6":{"position":[[1003,1]]},"7":{"position":[[299,2],[349,1],[369,2],[611,1],[940,1]]},"11":{"position":[[497,2]]},"12":{"position":[[248,2],[456,2],[563,2]]},"13":{"position":[[1344,2]]},"14":{"position":[[2416,2]]},"15":{"position":[[2088,2]]},"64":{"position":[[549,1],[564,2]]},"65":{"position":[[443,1],[458,2]]},"70":{"position":[[957,3],[998,2]]},"78":{"position":[[189,2],[222,2]]},"89":{"position":[[598,1]]},"91":{"position":[[351,1]]},"105":{"position":[[1731,2],[1742,2]]},"188":{"position":[[1013,2],[1026,1],[1044,1],[1114,3],[1180,3],[1314,3],[3552,2],[3565,1]]},"189":{"position":[[1115,1],[1133,1],[1176,3],[1385,1],[1403,1],[1446,3],[3109,1]]}},"keywords":{}}],["n*i",{"_index":581,"title":{},"content":{"13":{"position":[[1296,4]]},"14":{"position":[[2368,4]]},"15":{"position":[[2040,4]]}},"keywords":{}}],["n=10000",{"_index":2749,"title":{},"content":{"78":{"position":[[149,9]]}},"keywords":{}}],["n=250",{"_index":2789,"title":{},"content":{"82":{"position":[[246,6]]}},"keywords":{}}],["n_compon",{"_index":3521,"title":{},"content":{"103":{"position":[[896,13],[1597,12]]},"105":{"position":[[1360,13],[1439,13]]}},"keywords":{}}],["n_hash",{"_index":2186,"title":{},"content":{"52":{"position":[[791,6]]}},"keywords":{}}],["n_hashtag",{"_index":2123,"title":{},"content":{"51":{"position":[[2306,10],[2491,10]]}},"keywords":{}}],["naiv",{"_index":1947,"title":{},"content":{"44":{"position":[[1624,5],[1697,5]]},"45":{"position":[[18,5],[173,5],[998,5],[1241,5],[1662,5],[1887,5],[2414,5],[2600,5],[3194,5]]}},"keywords":{}}],["naive_guess",{"_index":1940,"title":{},"content":{"44":{"position":[[1456,11]]},"45":{"position":[[2381,12],[3161,12]]}},"keywords":{}}],["name",{"_index":664,"title":{},"content":{"15":{"position":[[78,4]]},"93":{"position":[[4769,4],[5184,4]]},"109":{"position":[[250,4]]},"112":{"position":[[689,4]]},"120":{"position":[[750,4]]},"121":{"position":[[508,6]]},"127":{"position":[[26,4],[164,4]]},"134":{"position":[[267,4]]},"183":{"position":[[754,5]]},"196":{"position":[[525,5]]}},"keywords":{}}],["nan",{"_index":1250,"title":{},"content":{"28":{"position":[[1588,3],[3374,3]]}},"keywords":{}}],["nanmean",{"_index":1249,"title":{},"content":{"28":{"position":[[1569,7],[3355,7]]}},"keywords":{}}],["nano",{"_index":4422,"title":{},"content":{"139":{"position":[[579,4]]}},"keywords":{}}],["nasdaq",{"_index":997,"title":{},"content":{"23":{"position":[[151,6],[566,6]]},"24":{"position":[[2506,6],[2585,6],[2658,6],[2797,6],[2946,6],[3454,6]]},"25":{"position":[[2229,6],[2308,6],[2381,6],[2520,6],[2688,6],[2706,6]]},"26":{"position":[[515,6]]},"93":{"position":[[3228,9]]}},"keywords":{}}],["nasdaq_close_ret",{"_index":1146,"title":{},"content":{"25":{"position":[[602,16],[1505,17]]}},"keywords":{}}],["nasdaq_open_ret",{"_index":1044,"title":{},"content":{"24":{"position":[[883,15],[1782,16]]}},"keywords":{}}],["nasti",{"_index":1206,"title":{},"content":{"28":{"position":[[268,5]]},"112":{"position":[[980,6]]},"125":{"position":[[7721,5]]}},"keywords":{}}],["nativ",{"_index":4041,"title":{},"content":{"125":{"position":[[1298,6]]},"172":{"position":[[2067,6]]}},"keywords":{}}],["natur",{"_index":4715,"title":{},"content":{"160":{"position":[[3957,6]]}},"keywords":{}}],["navig",{"_index":3934,"title":{},"content":{"122":{"position":[[149,10]]}},"keywords":{}}],["nb",{"_index":2007,"title":{},"content":{"45":{"position":[[2283,2],[3063,2]]}},"keywords":{}}],["ncseattl",{"_index":1210,"title":{},"content":{"28":{"position":[[388,10]]}},"keywords":{}}],["near",{"_index":1884,"title":{},"content":{"43":{"position":[[940,4]]}},"keywords":{}}],["nearli",{"_index":2314,"title":{},"content":{"57":{"position":[[403,6]]},"92":{"position":[[1368,6]]},"104":{"position":[[1858,6]]},"105":{"position":[[2584,6]]},"124":{"position":[[97,6]]},"175":{"position":[[791,6]]}},"keywords":{}}],["neat",{"_index":1852,"title":{},"content":{"41":{"position":[[348,4]]}},"keywords":{}}],["necessari",{"_index":3498,"title":{},"content":{"102":{"position":[[1070,11]]},"113":{"position":[[1265,9]]},"123":{"position":[[912,9]]},"125":{"position":[[3738,9],[11074,9]]},"152":{"position":[[133,10]]},"156":{"position":[[161,10]]},"157":{"position":[[598,9]]},"174":{"position":[[730,9]]},"189":{"position":[[756,9]]},"196":{"position":[[1940,10]]}},"keywords":{}}],["necessarili",{"_index":5054,"title":{},"content":{"176":{"position":[[1471,11]]}},"keywords":{}}],["need",{"_index":23,"title":{},"content":{"1":{"position":[[250,4]]},"6":{"position":[[46,4]]},"9":{"position":[[289,4]]},"22":{"position":[[822,4]]},"30":{"position":[[2546,4],[4130,4]]},"34":{"position":[[53,4],[174,4],[315,4],[3508,4]]},"35":{"position":[[202,5]]},"39":{"position":[[1902,4]]},"43":{"position":[[14,4],[149,4],[1436,4]]},"44":{"position":[[468,4]]},"49":{"position":[[158,4],[408,4]]},"51":{"position":[[706,4],[2750,4],[3504,4]]},"52":{"position":[[35,4]]},"54":{"position":[[252,5]]},"55":{"position":[[220,7]]},"61":{"position":[[303,4],[349,4],[398,4],[823,4],[990,7],[1438,4],[1588,4],[2278,4]]},"62":{"position":[[1300,4]]},"64":{"position":[[1176,4]]},"74":{"position":[[237,4],[850,4]]},"76":{"position":[[558,4],[837,4]]},"86":{"position":[[974,6],[1115,6]]},"89":{"position":[[211,4]]},"91":{"position":[[156,4],[1976,4],[2270,4]]},"93":{"position":[[3764,6],[4389,4]]},"95":{"position":[[86,4]]},"96":{"position":[[891,4],[2083,4]]},"97":{"position":[[3008,4],[3419,4],[6008,4]]},"98":{"position":[[174,4]]},"101":{"position":[[200,5]]},"102":{"position":[[1047,6]]},"103":{"position":[[190,4]]},"104":{"position":[[274,4],[423,4],[571,5]]},"105":{"position":[[418,4]]},"106":{"position":[[244,6]]},"108":{"position":[[28,6],[215,4],[666,4]]},"109":{"position":[[626,4]]},"112":{"position":[[378,4]]},"113":{"position":[[179,4],[1012,4]]},"121":{"position":[[2358,4]]},"122":{"position":[[270,4]]},"123":{"position":[[160,7],[285,7],[932,5],[1048,4]]},"124":{"position":[[724,4]]},"125":{"position":[[6970,5],[7287,6],[9451,4],[10975,4],[11050,5],[11177,4],[11265,4]]},"128":{"position":[[10,4]]},"137":{"position":[[23,4]]},"141":{"position":[[321,6]]},"145":{"position":[[20,4]]},"152":{"position":[[777,4]]},"156":{"position":[[111,7]]},"157":{"position":[[217,4],[544,4],[709,5]]},"159":{"position":[[226,4],[1209,4]]},"160":{"position":[[1561,4],[3169,5]]},"163":{"position":[[300,4]]},"164":{"position":[[958,4]]},"166":{"position":[[680,4]]},"170":{"position":[[182,6],[426,4]]},"175":{"position":[[995,6],[1275,6]]},"178":{"position":[[489,4]]},"180":{"position":[[611,5]]},"183":{"position":[[808,5]]},"190":{"position":[[193,4],[433,5]]},"193":{"position":[[408,6],[1151,6]]},"194":{"position":[[681,4]]},"196":{"position":[[885,6],[1320,5]]},"199":{"position":[[672,4],[954,4],[1327,4]]}},"keywords":{}}],["needless",{"_index":4755,"title":{},"content":{"161":{"position":[[1365,8]]}},"keywords":{}}],["neg",{"_index":334,"title":{},"content":{"6":{"position":[[479,8]]},"19":{"position":[[215,8]]},"76":{"position":[[1619,9]]}},"keywords":{}}],["nervous",{"_index":4156,"title":{},"content":{"125":{"position":[[8178,11]]}},"keywords":{}}],["nest",{"_index":3907,"title":{},"content":{"121":{"position":[[1655,6]]},"165":{"position":[[557,6]]}},"keywords":{}}],["netflix",{"_index":1804,"title":{},"content":{"40":{"position":[[1027,7],[1115,8],[2449,8]]}},"keywords":{}}],["network",{"_index":4992,"title":{"175":{"position":[[0,9]]}},"content":{"174":{"position":[[989,7]]},"175":{"position":[[571,7],[731,10],[1666,7]]}},"keywords":{}}],["never",{"_index":41,"title":{},"content":{"1":{"position":[[487,5]]},"45":{"position":[[1745,5]]},"55":{"position":[[158,5]]},"76":{"position":[[1646,5]]},"97":{"position":[[247,5]]},"98":{"position":[[935,5]]},"127":{"position":[[445,5]]},"132":{"position":[[807,5]]},"153":{"position":[[891,5]]},"158":{"position":[[169,5]]},"160":{"position":[[1555,5],[1617,5]]},"161":{"position":[[1283,5]]},"176":{"position":[[420,5]]},"178":{"position":[[204,5]]},"179":{"position":[[1441,5]]},"180":{"position":[[605,5]]},"181":{"position":[[534,5]]},"183":{"position":[[873,5]]},"185":{"position":[[445,5]]},"193":{"position":[[2026,5]]},"197":{"position":[[1300,5]]},"199":{"position":[[1040,5]]}},"keywords":{}}],["new",{"_index":21,"title":{"100":{"position":[[10,3]]}},"content":{"1":{"position":[[222,3]]},"2":{"position":[[712,3]]},"3":{"position":[[241,3],[315,3],[750,3]]},"4":{"position":[[488,3],[1413,3]]},"30":{"position":[[7251,3]]},"51":{"position":[[2709,4]]},"53":{"position":[[853,3]]},"75":{"position":[[395,3],[525,3],[742,3],[802,3],[880,3],[1003,3]]},"76":{"position":[[2796,3],[3150,3]]},"93":{"position":[[3262,4]]},"96":{"position":[[2090,3]]},"97":{"position":[[354,3],[1790,3],[3436,3]]},"98":{"position":[[348,3]]},"100":{"position":[[429,3]]},"115":{"position":[[488,3]]},"116":{"position":[[694,3]]},"117":{"position":[[22,3],[1975,3]]},"121":{"position":[[643,3],[2269,3]]},"122":{"position":[[27,4]]},"125":{"position":[[1775,3]]},"156":{"position":[[468,3]]},"164":{"position":[[286,3],[478,3],[1045,3]]},"165":{"position":[[13,3]]},"183":{"position":[[719,3]]},"184":{"position":[[559,5]]},"198":{"position":[[900,3]]}},"keywords":{}}],["new_d1",{"_index":2708,"title":{},"content":{"76":{"position":[[1466,6],[1779,7],[2594,7],[2659,7],[2735,6],[2889,6],[3198,6]]}},"keywords":{}}],["new_d1[d1_index1",{"_index":2712,"title":{},"content":{"76":{"position":[[1660,17]]}},"keywords":{}}],["new_d1[d1_index2",{"_index":2713,"title":{},"content":{"76":{"position":[[1688,17]]}},"keywords":{}}],["new_d2",{"_index":2710,"title":{},"content":{"76":{"position":[[1507,6],[1787,6],[2602,6],[2667,7],[2751,6],[2905,6],[3214,6]]}},"keywords":{}}],["new_d2[d2_index1",{"_index":2714,"title":{},"content":{"76":{"position":[[1716,17]]}},"keywords":{}}],["new_d2[d2_index2",{"_index":2715,"title":{},"content":{"76":{"position":[[1744,17]]}},"keywords":{}}],["new_scor",{"_index":2738,"title":{},"content":{"76":{"position":[[2635,9],[2678,9],[2716,9],[2761,9],[2870,9],[3179,9]]}},"keywords":{}}],["newbi",{"_index":3395,"title":{},"content":{"97":{"position":[[2568,6]]}},"keywords":{}}],["newer",{"_index":4023,"title":{},"content":{"125":{"position":[[669,5]]}},"keywords":{}}],["newparser::default",{"_index":4396,"title":{},"content":{"136":{"position":[[588,18]]}},"keywords":{}}],["next",{"_index":109,"title":{"25":{"position":[[4,4]]},"41":{"position":[[26,4]]}},"content":{"2":{"position":[[490,4]]},"35":{"position":[[271,4]]},"41":{"position":[[408,4]]},"51":{"position":[[697,5],[795,4]]},"61":{"position":[[65,5]]},"66":{"position":[[881,4]]},"75":{"position":[[777,4],[1086,4]]},"91":{"position":[[5157,4]]},"93":{"position":[[1171,4]]},"103":{"position":[[705,5]]},"113":{"position":[[2505,4]]},"116":{"position":[[168,4]]},"175":{"position":[[1234,4],[1463,4]]},"180":{"position":[[5,4]]},"184":{"position":[[1,5]]},"185":{"position":[[25,4]]},"192":{"position":[[348,4],[495,4]]}},"keywords":{}}],["next.j",{"_index":189,"title":{},"content":{"3":{"position":[[1087,7]]},"4":{"position":[[1148,7]]}},"keywords":{}}],["nice",{"_index":1846,"title":{},"content":{"40":{"position":[[3726,4]]},"70":{"position":[[1362,6]]},"96":{"position":[[1575,5]]},"97":{"position":[[4198,4]]},"106":{"position":[[452,4]]},"116":{"position":[[2751,4]]},"120":{"position":[[647,4]]},"121":{"position":[[844,4],[1122,4]]},"124":{"position":[[745,4]]},"125":{"position":[[775,4]]},"150":{"position":[[631,6]]},"165":{"position":[[375,5]]}},"keywords":{}}],["nicer",{"_index":4013,"title":{},"content":{"125":{"position":[[405,5]]}},"keywords":{}}],["nick",{"_index":2251,"title":{},"content":{"53":{"position":[[1163,4],[2106,4]]}},"keywords":{}}],["nigh",{"_index":4835,"title":{},"content":{"165":{"position":[[1361,4]]}},"keywords":{}}],["night",{"_index":2204,"title":{},"content":{"53":{"position":[[326,5]]},"125":{"position":[[145,6]]}},"keywords":{}}],["night,"",{"_index":3981,"title":{},"content":{"123":{"position":[[701,12]]}},"keywords":{}}],["nighter",{"_index":2179,"title":{},"content":{"52":{"position":[[471,7]]}},"keywords":{}}],["nightli",{"_index":4113,"title":{},"content":{"125":{"position":[[5210,8],[5758,8]]}},"keywords":{}}],["nightly.becaus",{"_index":4714,"title":{},"content":{"160":{"position":[[3934,15]]}},"keywords":{}}],["nltk",{"_index":2067,"title":{},"content":{"51":{"position":[[19,4]]}},"keywords":{}}],["nltk.token",{"_index":2080,"title":{},"content":{"51":{"position":[[418,13]]}},"keywords":{}}],["nnn",{"_index":1538,"title":{},"content":{"32":{"position":[[1225,4]]},"75":{"position":[[1163,3]]}},"keywords":{}}],["no_alloc",{"_index":4450,"title":{},"content":{"144":{"position":[[162,11]]},"147":{"position":[[177,11]]}},"keywords":{}}],["nobodi",{"_index":3488,"title":{},"content":{"101":{"position":[[1069,6]]},"130":{"position":[[409,6]]}},"keywords":{}}],["nobody'",{"_index":3973,"title":{},"content":{"123":{"position":[[241,8]]},"124":{"position":[[611,8]]}},"keywords":{}}],["node",{"_index":4970,"title":{},"content":{"173":{"position":[[2082,6],[2157,5]]},"175":{"position":[[1307,5],[1468,5]]}},"keywords":{}}],["nogil",{"_index":5157,"title":{},"content":{"188":{"position":[[626,5],[865,7],[925,6],[1016,6],[1244,6],[3555,6],[3590,6],[4083,5],[4130,5],[4386,5],[4484,5]]},"189":{"position":[[702,5]]}},"keywords":{}}],["nogil=fals",{"_index":5234,"title":{},"content":{"189":{"position":[[867,11],[1303,13]]}},"keywords":{}}],["nogil=tru",{"_index":5231,"title":{},"content":{"189":{"position":[[612,10],[1065,11],[3057,11]]}},"keywords":{}}],["nogilcontext",{"_index":5154,"title":{},"content":{"188":{"position":[[517,12]]}},"keywords":{}}],["nogilfunct",{"_index":5151,"title":{},"content":{"188":{"position":[[348,13]]}},"keywords":{}}],["nois",{"_index":3561,"title":{},"content":{"104":{"position":[[792,5],[1835,5]]}},"keywords":{}}],["noisi",{"_index":3562,"title":{},"content":{"104":{"position":[[919,5]]}},"keywords":{}}],["nom",{"_index":4761,"title":{"163":{"position":[[30,4]]}},"content":{"163":{"position":[[446,4],[624,4],[1652,3],[2273,3]]}},"keywords":{}}],["nomin",{"_index":352,"title":{},"content":{"6":{"position":[[777,7]]},"9":{"position":[[683,7]]},"13":{"position":[[587,7],[820,8],[1007,7],[1909,8]]},"14":{"position":[[1417,7],[1677,8],[2025,7]]},"15":{"position":[[786,7],[1067,8],[1693,7]]}},"keywords":{}}],["nominal*(1",{"_index":577,"title":{},"content":{"13":{"position":[[1070,10]]},"14":{"position":[[2104,10]]},"15":{"position":[[1772,10]]}},"keywords":{}}],["non",{"_index":2825,"title":{},"content":{"86":{"position":[[107,3],[182,3],[560,3]]},"97":{"position":[[1050,3],[2813,3]]},"112":{"position":[[1371,3]]},"113":{"position":[[1159,3]]},"146":{"position":[[213,3]]},"163":{"position":[[553,3]]},"172":{"position":[[2314,3]]},"173":{"position":[[538,3]]},"181":{"position":[[794,3]]},"185":{"position":[[585,3]]},"190":{"position":[[198,3]]},"196":{"position":[[220,3]]}},"keywords":{}}],["none",{"_index":834,"title":{},"content":{"20":{"position":[[1956,7],[1964,7]]},"30":{"position":[[8863,5],[9946,4]]},"51":{"position":[[1236,4]]},"62":{"position":[[904,4]]},"88":{"position":[[1065,5]]},"93":{"position":[[1529,4],[2751,5]]},"123":{"position":[[1110,4]]},"136":{"position":[[409,5],[415,5],[435,5]]}},"keywords":{}}],["nonetheless",{"_index":3492,"title":{},"content":{"102":{"position":[[443,12]]}},"keywords":{}}],["nonsens",{"_index":2280,"title":{},"content":{"53":{"position":[[1659,11]]}},"keywords":{}}],["noon",{"_index":1475,"title":{},"content":{"30":{"position":[[9142,5]]}},"keywords":{}}],["nop",{"_index":4267,"title":{},"content":{"128":{"position":[[893,3]]}},"keywords":{}}],["nopython",{"_index":5230,"title":{},"content":{"189":{"position":[[522,8],[793,8],[1223,10]]}},"keywords":{}}],["nopython=tru",{"_index":5229,"title":{},"content":{"189":{"position":[[445,13]]}},"keywords":{}}],["nopythonar",{"_index":5233,"title":{},"content":{"189":{"position":[[712,11]]}},"keywords":{}}],["norm_factor",{"_index":2980,"title":{},"content":{"90":{"position":[[928,11],[1034,11],[2313,11],[2419,11]]}},"keywords":{}}],["normal",{"_index":4553,"title":{},"content":{"153":{"position":[[762,8]]},"161":{"position":[[957,8]]},"173":{"position":[[345,8]]},"196":{"position":[[311,9]]}},"keywords":{}}],["north",{"_index":1196,"title":{},"content":{"28":{"position":[[54,5]]},"30":{"position":[[78,5],[347,5],[523,5],[1011,5],[7801,5],[8035,5]]}},"keywords":{}}],["notabl",{"_index":1832,"title":{},"content":{"40":{"position":[[3149,7]]}},"keywords":{}}],["notat",{"_index":5119,"title":{},"content":{"184":{"position":[[120,9]]}},"keywords":{}}],["notcopy",{"_index":5369,"title":{},"content":{"198":{"position":[[1130,11]]}},"keywords":{}}],["note",{"_index":333,"title":{"36":{"position":[[5,4]]}},"content":{"6":{"position":[[453,5]]},"13":{"position":[[90,5],[1867,5],[2269,5]]},"14":{"position":[[752,4],[1089,4],[2966,5],[3357,5]]},"15":{"position":[[289,4],[2637,5],[3025,5]]},"30":{"position":[[8202,4]]},"33":{"position":[[19,4]]},"40":{"position":[[1212,4]]},"43":{"position":[[1107,5]]},"45":{"position":[[3301,4]]},"68":{"position":[[834,5]]},"74":{"position":[[347,4]]},"91":{"position":[[2563,5]]},"92":{"position":[[375,5],[1339,6]]},"97":{"position":[[342,5],[595,5]]},"113":{"position":[[290,4]]},"115":{"position":[[2489,5]]},"121":{"position":[[1070,5]]},"123":{"position":[[953,4]]},"125":{"position":[[2510,4]]},"155":{"position":[[20,4]]},"186":{"position":[[349,4]]},"188":{"position":[[2916,4]]},"189":{"position":[[692,4]]},"192":{"position":[[585,4]]},"193":{"position":[[2247,4]]},"195":{"position":[[960,4]]},"196":{"position":[[987,4]]},"197":{"position":[[1169,4]]},"198":{"position":[[700,4]]}},"keywords":{}}],["notebook",{"_index":1864,"title":{},"content":{"43":{"position":[[395,8]]}},"keywords":{}}],["noth",{"_index":637,"title":{},"content":{"14":{"position":[[1017,8]]},"30":{"position":[[7902,7]]},"45":{"position":[[3271,8]]},"53":{"position":[[569,7]]},"93":{"position":[[549,7]]},"109":{"position":[[82,7]]},"123":{"position":[[442,7]]},"127":{"position":[[1053,7]]},"128":{"position":[[997,7]]},"143":{"position":[[201,7]]},"199":{"position":[[451,7]]}},"keywords":{}}],["notic",{"_index":1436,"title":{},"content":{"30":{"position":[[7720,8]]},"68":{"position":[[848,6]]},"103":{"position":[[2314,6]]},"104":{"position":[[1926,9]]},"153":{"position":[[877,7]]},"160":{"position":[[4434,6]]}},"keywords":{}}],["notifi",{"_index":4966,"title":{},"content":{"173":{"position":[[1676,6]]}},"keywords":{}}],["notion",{"_index":603,"title":{},"content":{"13":{"position":[[1881,9],[2283,9]]}},"keywords":{}}],["notstr",{"_index":4595,"title":{},"content":{"156":{"position":[[387,9]]}},"keywords":{}}],["novemb",{"_index":1265,"title":{},"content":{"28":{"position":[[1953,12],[2589,9],[4236,8]]},"30":{"position":[[1042,9],[1450,11],[7120,8],[7487,8]]}},"keywords":{}}],["now",{"_index":73,"title":{"40":{"position":[[4,3]]}},"content":{"2":{"position":[[1,3]]},"3":{"position":[[1,3]]},"8":{"position":[[125,4]]},"9":{"position":[[1,3]]},"10":{"position":[[1,3]]},"11":{"position":[[1,3]]},"12":{"position":[[7,3]]},"13":{"position":[[1,3]]},"23":{"position":[[1,3]]},"28":{"position":[[552,3],[2808,3]]},"30":{"position":[[2708,3]]},"32":{"position":[[409,3]]},"34":{"position":[[4,3],[698,3],[982,4],[3011,4],[3601,3]]},"38":{"position":[[767,3]]},"40":{"position":[[1370,5]]},"43":{"position":[[973,3],[1027,4]]},"44":{"position":[[1207,3],[1264,4],[1963,4]]},"45":{"position":[[361,4],[1522,3]]},"51":{"position":[[302,3],[1450,3],[2160,3],[2725,3],[3493,3]]},"52":{"position":[[6,3]]},"53":{"position":[[5,3],[353,3]]},"61":{"position":[[877,3],[1833,4]]},"62":{"position":[[1,3],[1681,3]]},"64":{"position":[[325,3],[1169,4]]},"65":{"position":[[1,3],[730,4]]},"66":{"position":[[393,4]]},"74":{"position":[[961,4]]},"76":{"position":[[510,3],[1796,3],[3363,3]]},"79":{"position":[[12,3]]},"80":{"position":[[17,3]]},"81":{"position":[[7,3]]},"82":{"position":[[84,3]]},"88":{"position":[[89,3]]},"89":{"position":[[986,3]]},"92":{"position":[[7,3]]},"97":{"position":[[618,3],[4154,4],[5152,4],[6218,3]]},"98":{"position":[[34,3]]},"100":{"position":[[276,3]]},"103":{"position":[[1501,3]]},"109":{"position":[[590,3]]},"110":{"position":[[373,4],[521,3]]},"111":{"position":[[1,3],[933,4]]},"112":{"position":[[945,4],[1638,3]]},"113":{"position":[[85,4],[1284,3],[1513,3],[2272,3],[2431,3]]},"116":{"position":[[596,3]]},"117":{"position":[[1443,3],[1561,3],[2064,3]]},"118":{"position":[[100,4]]},"120":{"position":[[1116,3]]},"122":{"position":[[1,4]]},"124":{"position":[[12,3]]},"125":{"position":[[1278,3],[10847,4]]},"127":{"position":[[86,4]]},"129":{"position":[[1,3],[737,4]]},"130":{"position":[[508,3]]},"135":{"position":[[531,3]]},"136":{"position":[[843,3]]},"160":{"position":[[3333,3]]},"161":{"position":[[941,4]]},"164":{"position":[[1,3]]},"193":{"position":[[1695,3]]}},"keywords":{}}],["nowher",{"_index":1883,"title":{},"content":{"43":{"position":[[932,7]]}},"keywords":{}}],["np",{"_index":802,"title":{},"content":{"20":{"position":[[1018,2]]},"30":{"position":[[233,2]]},"39":{"position":[[430,2]]},"43":{"position":[[303,2]]},"51":{"position":[[3603,2]]},"68":{"position":[[418,2]]},"76":{"position":[[143,2]]},"90":{"position":[[192,2]]},"103":{"position":[[870,2]]}},"keywords":{}}],["np.append(invest",{"_index":1736,"title":{},"content":{"39":{"position":[[1417,19]]}},"keywords":{}}],["np.arange(1",{"_index":2002,"title":{},"content":{"45":{"position":[[2183,12],[2963,12]]}},"keywords":{}}],["np.arange(2",{"_index":2761,"title":{},"content":{"78":{"position":[[431,12]]}},"keywords":{}}],["np.array([init",{"_index":1730,"title":{},"content":{"39":{"position":[[1064,16]]}},"keywords":{}}],["np.array(event_data",{"_index":3040,"title":{},"content":{"90":{"position":[[3967,20]]}},"keywords":{}}],["np.array(list(map(lambda",{"_index":813,"title":{},"content":{"20":{"position":[[1222,24],[1291,24],[1383,24]]}},"keywords":{}}],["np.count_nonzero(cloudy_day",{"_index":1384,"title":{},"content":{"30":{"position":[[3323,30]]}},"keywords":{}}],["np.count_nonzero(precip_day",{"_index":1422,"title":{},"content":{"30":{"position":[[6391,30]]}},"keywords":{}}],["np.exp(new_scor",{"_index":2741,"title":{},"content":{"76":{"position":[[3032,16]]}},"keywords":{}}],["np.float64(first_word_dist.valu",{"_index":2160,"title":{},"content":{"51":{"position":[[3973,34]]}},"keywords":{}}],["np.float64(np.copy(d1_dens",{"_index":2709,"title":{},"content":{"76":{"position":[[1475,31]]}},"keywords":{}}],["np.float64(np.copy(d2_dens",{"_index":2711,"title":{},"content":{"76":{"position":[[1516,31]]}},"keywords":{}}],["np.hstack((0",{"_index":2691,"title":{},"content":{"76":{"position":[[766,13]]}},"keywords":{}}],["np.hstack([0",{"_index":2990,"title":{},"content":{"90":{"position":[[1192,13],[2577,13]]}},"keywords":{}}],["np.lib.pad(sign",{"_index":3527,"title":{},"content":{"103":{"position":[[1081,18]]}},"keywords":{}}],["np.log(coefs[x]).sum",{"_index":2692,"title":{},"content":{"76":{"position":[[798,22]]}},"keywords":{}}],["np.mean(i",{"_index":1941,"title":{},"content":{"44":{"position":[[1470,9]]}},"keywords":{}}],["np.mean(matches_dict[index][futur",{"_index":1086,"title":{},"content":{"24":{"position":[[2245,36]]},"25":{"position":[[1969,36]]}},"keywords":{}}],["np.mean(x_bin[:,i",{"_index":1915,"title":{},"content":{"44":{"position":[[642,19]]}},"keywords":{}}],["np.mod(sampl",{"_index":3526,"title":{},"content":{"103":{"position":[[1044,15]]}},"keywords":{}}],["np.nan",{"_index":950,"title":{},"content":{"22":{"position":[[1718,6]]},"28":{"position":[[1189,6],[1518,7],[2993,6],[3309,7]]},"30":{"position":[[1561,6],[1879,7],[3228,7],[4838,6],[5143,7],[6297,7]]}},"keywords":{}}],["np.nanmean(cloud_cover_v",{"_index":1254,"title":{},"content":{"28":{"position":[[1708,29]]},"30":{"position":[[1914,29]]}},"keywords":{}}],["np.nanmean(precip_v",{"_index":1302,"title":{},"content":{"28":{"position":[[3494,24]]},"30":{"position":[[5173,24]]}},"keywords":{}}],["np.ones(len(dist",{"_index":2166,"title":{},"content":{"51":{"position":[[4162,18]]}},"keywords":{}}],["np.random.multinomial(1",{"_index":2594,"title":{},"content":{"70":{"position":[[965,24]]}},"keywords":{}}],["np.random.multinomial(n",{"_index":2152,"title":{},"content":{"51":{"position":[[3654,24]]}},"keywords":{}}],["np.random.poisson(hashtag_freq",{"_index":2155,"title":{},"content":{"51":{"position":[[3796,31]]}},"keywords":{}}],["np.random.rand",{"_index":2743,"title":{},"content":{"76":{"position":[[3074,16]]}},"keywords":{}}],["np.random.randint(0",{"_index":2703,"title":{},"content":{"76":{"position":[[1283,20],[1333,20]]}},"keywords":{}}],["np.random.randint(1",{"_index":2561,"title":{},"content":{"68":{"position":[[501,20],[541,20]]}},"keywords":{}}],["np.repeat(1/6",{"_index":2724,"title":{},"content":{"76":{"position":[[2012,14],[2039,14]]},"81":{"position":[[135,14]]}},"keywords":{}}],["np.repeat(array[:,lookback].reshap",{"_index":2981,"title":{},"content":{"90":{"position":[[942,36],[2327,36]]}},"keywords":{}}],["np.vstack([five_day_ev",{"_index":3149,"title":{},"content":{"91":{"position":[[3675,27]]}},"keywords":{}}],["np.zeros((1",{"_index":3143,"title":{},"content":{"91":{"position":[[3375,12]]}},"keywords":{}}],["np.zeros(len(i",{"_index":1942,"title":{},"content":{"44":{"position":[[1483,17]]}},"keywords":{}}],["np.zeros(len(tick",{"_index":836,"title":{},"content":{"20":{"position":[[1991,22]]}},"keywords":{}}],["ns",{"_index":5174,"title":{},"content":{"188":{"position":[[1605,3],[1703,3],[3127,3]]},"189":{"position":[[2820,3]]}},"keywords":{}}],["nt",{"_index":3224,"title":{},"content":{"93":{"position":[[2379,2]]}},"keywords":{}}],["nuanc",{"_index":4539,"title":{},"content":{"153":{"position":[[175,6]]}},"keywords":{}}],["null",{"_index":4228,"title":{},"content":{"127":{"position":[[454,5]]},"188":{"position":[[3685,4]]}},"keywords":{}}],["num",{"_index":4250,"title":{},"content":{"128":{"position":[[251,4]]}},"keywords":{}}],["num_dealloc",{"_index":4898,"title":{},"content":{"172":{"position":[[233,11]]}},"keywords":{}}],["num_quart",{"_index":2471,"title":{},"content":{"64":{"position":[[930,12],[996,12],[1028,13]]}},"keywords":{}}],["num_simul",{"_index":372,"title":{},"content":{"6":{"position":[[1053,15]]},"13":{"position":[[1714,16]]},"14":{"position":[[2797,16]]},"15":{"position":[[2471,16]]}},"keywords":{}}],["num_tick",{"_index":419,"title":{},"content":{"7":{"position":[[830,9],[876,9],[944,9]]}},"keywords":{}}],["numa",{"_index":4968,"title":{},"content":{"173":{"position":[[1945,5],[1957,4]]}},"keywords":{}}],["numba",{"_index":5225,"title":{"189":{"position":[[0,6]]}},"content":{"189":{"position":[[14,5],[119,5],[421,5],[945,5],[1038,6],[1871,5],[2881,5],[3020,5]]},"190":{"position":[[380,5],[671,5],[905,5]]}},"keywords":{}}],["numba_gil(n",{"_index":5238,"title":{},"content":{"189":{"position":[[1353,12],[1623,13],[1747,12]]}},"keywords":{}}],["numba_nogil(n",{"_index":5236,"title":{},"content":{"189":{"position":[[1081,14],[1608,14]]}},"keywords":{}}],["numba_recurse(2",{"_index":5258,"title":{},"content":{"189":{"position":[[3157,17]]}},"keywords":{}}],["numba_recurse(n",{"_index":5257,"title":{},"content":{"189":{"position":[[3073,16],[3136,15]]}},"keywords":{}}],["number",{"_index":346,"title":{},"content":{"6":{"position":[[659,6],[693,6],[727,6]]},"30":{"position":[[3986,6],[4169,6],[4247,6],[7073,6]]},"32":{"position":[[1117,6]]},"40":{"position":[[2258,6]]},"43":{"position":[[1455,6]]},"45":{"position":[[797,6],[1195,6]]},"49":{"position":[[609,6]]},"51":{"position":[[1931,6],[2902,6]]},"57":{"position":[[35,6],[101,6],[456,6]]},"58":{"position":[[185,6],[483,7],[535,6],[611,6],[675,6],[827,6]]},"64":{"position":[[178,7],[475,6],[618,6],[663,6],[700,6],[740,6],[1313,6]]},"65":{"position":[[577,6],[605,6],[768,6]]},"66":{"position":[[79,6],[421,6]]},"74":{"position":[[1352,7]]},"76":{"position":[[2358,6]]},"91":{"position":[[3778,6]]},"92":{"position":[[154,6]]},"98":{"position":[[450,6],[507,6]]},"102":{"position":[[502,6],[1175,6],[1323,6]]},"103":{"position":[[1937,6]]},"104":{"position":[[877,7],[1446,6]]},"105":{"position":[[52,6],[136,6]]},"188":{"position":[[1537,7]]}},"keywords":{}}],["numer",{"_index":5150,"title":{},"content":{"188":{"position":[[235,9]]}},"keywords":{}}],["numpi",{"_index":801,"title":{},"content":{"20":{"position":[[1009,5]]},"30":{"position":[[224,5]]},"39":{"position":[[421,5]]},"43":{"position":[[294,5]]},"51":{"position":[[3594,5]]},"68":{"position":[[409,5]]},"76":{"position":[[134,5],[151,5]]},"90":{"position":[[183,5]]},"103":{"position":[[861,5]]}},"keywords":{}}],["ny",{"_index":1203,"title":{},"content":{"28":{"position":[[203,2],[416,2]]}},"keywords":{}}],["nyc",{"_index":1232,"title":{},"content":{"28":{"position":[[1013,6]]},"30":{"position":[[8641,6],[10273,3]]}},"keywords":{}}],["nyc_loc",{"_index":1453,"title":{},"content":{"30":{"position":[[8503,7],[8648,8]]}},"keywords":{}}],["nycari",{"_index":1209,"title":{},"content":{"28":{"position":[[380,7]]}},"keywords":{}}],["o",{"_index":4123,"title":{},"content":{"125":{"position":[[5581,1],[6042,1]]}},"keywords":{}}],["o_n",{"_index":1553,"title":{},"content":{"32":{"position":[[1861,4]]}},"keywords":{}}],["o_n}{o_n",{"_index":1549,"title":{},"content":{"32":{"position":[[1765,10]]}},"keywords":{}}],["oauth",{"_index":2343,"title":{"61":{"position":[[9,5]]}},"content":{"59":{"position":[[144,6]]},"60":{"position":[[153,5]]},"61":{"position":[[35,5],[92,5]]}},"keywords":{}}],["oauth2sess",{"_index":2402,"title":{},"content":{"62":{"position":[[394,13]]}},"keywords":{}}],["oauth2session(token",{"_index":2404,"title":{},"content":{"62":{"position":[[468,21]]}},"keywords":{}}],["object",{"_index":833,"title":{"49":{"position":[[4,10]]}},"content":{"20":{"position":[[1874,9]]},"29":{"position":[[208,11]]},"34":{"position":[[590,10]]},"90":{"position":[[514,6]]},"98":{"position":[[708,6]]},"110":{"position":[[546,6]]},"117":{"position":[[144,6],[161,6],[332,7],[882,6],[1718,6]]},"125":{"position":[[4243,7]]},"127":{"position":[[1428,8]]},"152":{"position":[[75,6]]},"155":{"position":[[409,7],[652,8]]},"156":{"position":[[298,7],[426,7]]},"157":{"position":[[133,7]]},"159":{"position":[[263,6]]},"160":{"position":[[1141,7],[1209,6]]},"164":{"position":[[339,7]]},"172":{"position":[[130,7],[1550,6]]},"190":{"position":[[306,7]]},"192":{"position":[[61,8]]},"196":{"position":[[132,7]]},"197":{"position":[[116,8],[191,7],[275,7],[1523,7]]},"198":{"position":[[389,7]]},"199":{"position":[[508,6],[655,7],[781,7],[854,7]]}},"keywords":{}}],["objectand",{"_index":4236,"title":{},"content":{"127":{"position":[[844,9]]}},"keywords":{}}],["observ",{"_index":548,"title":{},"content":{"13":{"position":[[289,11],[444,12]]},"14":{"position":[[497,12]]},"15":{"position":[[192,11]]},"68":{"position":[[745,8]]}},"keywords":{}}],["observationacceler",{"_index":545,"title":{},"content":{"13":{"position":[[207,22]]}},"keywords":{}}],["observationcoupon",{"_index":631,"title":{},"content":{"14":{"position":[[362,17]]}},"keywords":{}}],["observationprincipl",{"_index":632,"title":{},"content":{"14":{"position":[[432,20]]}},"keywords":{}}],["obsess",{"_index":234,"title":{},"content":{"4":{"position":[[238,8]]}},"keywords":{}}],["obsolet",{"_index":4060,"title":{},"content":{"125":{"position":[[2221,8]]}},"keywords":{}}],["obviou",{"_index":2556,"title":{},"content":{"68":{"position":[[92,7]]},"98":{"position":[[469,7]]},"172":{"position":[[1008,8]]}},"keywords":{}}],["obvious",{"_index":4246,"title":{},"content":{"127":{"position":[[1522,9]]}},"keywords":{}}],["occas",{"_index":3933,"title":{},"content":{"122":{"position":[[116,8]]}},"keywords":{}}],["occur",{"_index":2616,"title":{},"content":{"72":{"position":[[278,5]]},"136":{"position":[[138,8]]},"143":{"position":[[82,6]]},"156":{"position":[[1139,5]]},"161":{"position":[[204,8]]},"193":{"position":[[2431,6]]},"195":{"position":[[934,8]]},"198":{"position":[[927,5]]}},"keywords":{}}],["occurr",{"_index":2151,"title":{},"content":{"51":{"position":[[3640,11],[3696,11]]}},"keywords":{}}],["ocd",{"_index":1843,"title":{},"content":{"40":{"position":[[3658,3]]}},"keywords":{}}],["octob",{"_index":1263,"title":{},"content":{"28":{"position":[[1936,11],[2577,7],[4223,8]]},"30":{"position":[[1439,10]]},"40":{"position":[[3192,8]]}},"keywords":{}}],["of"resourc",{"_index":4559,"title":{},"content":{"155":{"position":[[312,16]]}},"keywords":{}}],["offer",{"_index":3411,"title":{},"content":{"97":{"position":[[4215,6]]}},"keywords":{}}],["offici",{"_index":4822,"title":{},"content":{"165":{"position":[[72,8]]}},"keywords":{}}],["offset",{"_index":5276,"title":{},"content":{"193":{"position":[[463,7]]}},"keywords":{}}],["offsetsto",{"_index":4842,"title":{},"content":{"166":{"position":[[366,9]]}},"keywords":{}}],["ofperform",{"_index":4665,"title":{},"content":{"160":{"position":[[864,14]]}},"keywords":{}}],["ogg",{"_index":3477,"title":{},"content":{"101":{"position":[[582,4]]}},"keywords":{}}],["oh",{"_index":4045,"title":{},"content":{"125":{"position":[[1334,2]]}},"keywords":{}}],["ohlc_dataframe(aapl",{"_index":2877,"title":{},"content":{"88":{"position":[[1489,20],[2779,20]]}},"keywords":{}}],["ohlc_dataframe(aapl[datetime(2016",{"_index":3089,"title":{},"content":{"91":{"position":[[930,34]]}},"keywords":{}}],["ohlc_dataframe(data",{"_index":2860,"title":{},"content":{"88":{"position":[[925,20]]}},"keywords":{}}],["ohlc_dataframe(fb",{"_index":2891,"title":{},"content":{"88":{"position":[[1818,18],[3182,18]]}},"keywords":{}}],["ohlc_dataframe(fb[datetime(2016",{"_index":3077,"title":{},"content":{"91":{"position":[[482,32]]}},"keywords":{}}],["oio_ioi",{"_index":1521,"title":{},"content":{"32":{"position":[[475,8]]}},"keywords":{}}],["oj",{"_index":2249,"title":{},"content":{"53":{"position":[[1146,2],[2090,3]]}},"keywords":{}}],["ok",{"_index":2354,"title":{},"content":{"61":{"position":[[328,3],[461,3],[664,3]]},"96":{"position":[[1333,3]]},"97":{"position":[[239,2]]},"103":{"position":[[1850,3]]},"120":{"position":[[1,3]]},"121":{"position":[[901,2],[1458,2]]},"160":{"position":[[1811,3]]}},"keywords":{}}],["ok((remain",{"_index":4795,"title":{},"content":{"163":{"position":[[2101,14]]}},"keywords":{}}],["ok((res.0",{"_index":4393,"title":{},"content":{"136":{"position":[[473,10]]}},"keywords":{}}],["ok(12).and_then(|",{"_index":4477,"title":{},"content":{"147":{"position":[[265,19]]}},"keywords":{}}],["ok(response::with((status::ok",{"_index":3331,"title":{},"content":{"96":{"position":[[726,30],[1145,30],[1675,30],[2221,30]]},"97":{"position":[[1585,30],[3712,30],[5060,30],[6056,30]]}},"keywords":{}}],["ok(vec::with_capacity(",{"_index":4478,"title":{},"content":{"147":{"position":[[285,26]]}},"keywords":{}}],["okay",{"_index":1878,"title":{},"content":{"43":{"position":[[674,5]]},"118":{"position":[[313,5]]}},"keywords":{}}],["ol",{"_index":4039,"title":{},"content":{"125":{"position":[[1263,3]]}},"keywords":{}}],["old",{"_index":2739,"title":{},"content":{"76":{"position":[[2822,3]]},"88":{"position":[[234,3]]},"161":{"position":[[343,3]]}},"keywords":{}}],["older",{"_index":4024,"title":{},"content":{"125":{"position":[[703,5]]}},"keywords":{}}],["oldschool",{"_index":2181,"title":{},"content":{"52":{"position":[[490,11]]}},"keywords":{}}],["omega",{"_index":780,"title":{},"content":{"20":{"position":[[606,8],[637,6],[664,6],[701,6]]}},"keywords":{}}],["on",{"_index":20,"title":{},"content":{"1":{"position":[[210,3]]},"7":{"position":[[1040,3]]},"20":{"position":[[6,3]]},"22":{"position":[[50,3],[96,3]]},"30":{"position":[[2768,3]]},"38":{"position":[[383,3]]},"39":{"position":[[1922,4]]},"45":{"position":[[907,4],[2567,4],[2743,3]]},"49":{"position":[[512,4]]},"51":{"position":[[841,3],[3260,4]]},"53":{"position":[[989,3],[1713,5]]},"61":{"position":[[1603,3]]},"62":{"position":[[251,3]]},"66":{"position":[[834,4]]},"70":{"position":[[19,3],[46,3]]},"71":{"position":[[6,3],[33,3]]},"73":{"position":[[794,3]]},"76":{"position":[[950,3],[1072,3],[1125,3],[2826,4]]},"80":{"position":[[25,3],[61,3]]},"89":{"position":[[90,3]]},"90":{"position":[[5039,3]]},"91":{"position":[[2922,3]]},"92":{"position":[[734,3]]},"96":{"position":[[1596,4]]},"97":{"position":[[2074,4],[2903,3],[5271,3]]},"102":{"position":[[670,5]]},"111":{"position":[[925,3]]},"118":{"position":[[324,4]]},"122":{"position":[[112,3]]},"125":{"position":[[4268,4]]},"135":{"position":[[582,3]]},"139":{"position":[[73,4]]},"155":{"position":[[750,3]]},"160":{"position":[[2050,3]]},"166":{"position":[[44,3]]},"174":{"position":[[891,3],[1024,3]]},"180":{"position":[[568,3]]},"188":{"position":[[1952,3]]},"197":{"position":[[741,3],[848,3]]}},"keywords":{}}],["onc",{"_index":1511,"title":{},"content":{"32":{"position":[[37,4]]},"34":{"position":[[1841,4],[3263,4]]},"57":{"position":[[78,4]]},"91":{"position":[[4556,4]]},"125":{"position":[[5697,4]]},"129":{"position":[[401,4]]},"155":{"position":[[1047,4]]},"164":{"position":[[247,4]]},"176":{"position":[[1597,4]]},"179":{"position":[[1217,5],[1261,4],[1308,6],[1411,6]]},"186":{"position":[[314,4]]},"189":{"position":[[1502,4]]},"193":{"position":[[73,4],[565,4]]},"199":{"position":[[711,4]]}},"keywords":{}}],["once::new",{"_index":5080,"title":{},"content":{"179":{"position":[[1268,12]]},"186":{"position":[[321,12]]}},"keywords":{}}],["ones(5",{"_index":445,"title":{},"content":{"8":{"position":[[89,7]]},"11":{"position":[[350,7]]}},"keywords":{}}],["ones(m",{"_index":530,"title":{},"content":{"12":{"position":[[351,7]]}},"keywords":{}}],["ones(n)*i",{"_index":435,"title":{},"content":{"7":{"position":[[1194,10]]}},"keywords":{}}],["onev",{"_index":51,"title":{},"content":{"1":{"position":[[581,7]]}},"keywords":{}}],["onlin",{"_index":39,"title":{},"content":{"1":{"position":[[447,6]]},"4":{"position":[[450,6],[520,6]]},"96":{"position":[[644,7]]},"97":{"position":[[2933,7]]}},"keywords":{}}],["onward",{"_index":3354,"title":{},"content":{"96":{"position":[[2339,8]]},"124":{"position":[[856,8]]},"148":{"position":[[267,7]]}},"keywords":{}}],["oookay",{"_index":3389,"title":{},"content":{"97":{"position":[[2057,10]]}},"keywords":{}}],["opaqu",{"_index":4509,"title":{},"content":{"152":{"position":[[270,7]]}},"keywords":{}}],["open",{"_index":1018,"title":{},"content":{"24":{"position":[[115,7],[259,7],[416,5],[1059,7]]},"25":{"position":[[779,7]]},"26":{"position":[[127,9],[495,4]]},"32":{"position":[[509,7]]},"33":{"position":[[185,7],[657,7]]},"39":{"position":[[1868,4]]},"90":{"position":[[3298,4]]},"91":{"position":[[298,7]]},"93":{"position":[[2126,5]]},"161":{"position":[[170,4]]}},"keywords":{}}],["open('city_forecasts.p",{"_index":1498,"title":{},"content":{"30":{"position":[[10096,24]]}},"keywords":{}}],["open('earnings_dates.yaml",{"_index":3107,"title":{},"content":{"91":{"position":[[1934,27]]},"93":{"position":[[3308,27],[4347,27]]}},"keywords":{}}],["open_histori",{"_index":1607,"title":{},"content":{"34":{"position":[[1122,13],[1322,13],[1466,13],[1513,13]]},"39":{"position":[[653,14],[842,14]]}},"keywords":{}}],["open_history).sum",{"_index":1726,"title":{},"content":{"39":{"position":[[697,19],[955,19]]}},"keywords":{}}],["open_v",{"_index":1035,"title":{},"content":{"24":{"position":[[656,8],[702,9]]},"25":{"position":[[342,8],[436,9],[448,8]]},"34":{"position":[[1700,9]]}},"keywords":{}}],["open_vals[0:day",{"_index":1735,"title":{},"content":{"39":{"position":[[1388,17]]}},"keywords":{}}],["open_vals[0:len(invest",{"_index":1731,"title":{},"content":{"39":{"position":[[1145,27],[1218,27],[1626,27],[1699,27],[1973,28]]}},"keywords":{}}],["open_vals[0:len(invested)]).sum",{"_index":1737,"title":{},"content":{"39":{"position":[[1510,33],[1748,33]]}},"keywords":{}}],["open_vals[1:day",{"_index":1638,"title":{},"content":{"34":{"position":[[2177,17]]}},"keywords":{}}],["open_vals[1:length(invest",{"_index":1632,"title":{},"content":{"34":{"position":[[1928,30],[2004,30],[2294,30],[2404,30],[2480,30],[2540,30]]}},"keywords":{}}],["open_vals[day",{"_index":1733,"title":{},"content":{"39":{"position":[[1285,14],[2056,14]]}},"keywords":{}}],["open_vals[day+1",{"_index":1635,"title":{},"content":{"34":{"position":[[2070,16],[2605,17]]}},"keywords":{}}],["openingfutur",{"_index":1170,"title":{},"content":{"26":{"position":[[207,14]]}},"keywords":{}}],["openingsnasdaq",{"_index":1121,"title":{},"content":{"24":{"position":[[3010,14]]}},"keywords":{}}],["oper",{"_index":3339,"title":{},"content":{"96":{"position":[[1272,9]]},"160":{"position":[[522,9],[1935,9]]},"172":{"position":[[1284,9]]},"173":{"position":[[104,9],[1046,9],[1189,9]]},"176":{"position":[[160,8],[512,10],[584,10]]},"186":{"position":[[77,10]]},"193":{"position":[[966,10]]},"198":{"position":[[953,8]]}},"keywords":{}}],["opinion",{"_index":3349,"title":{},"content":{"96":{"position":[[1941,8]]}},"keywords":{}}],["opportun",{"_index":3931,"title":{},"content":{"122":{"position":[[57,11]]},"163":{"position":[[530,11]]}},"keywords":{}}],["opposit",{"_index":2941,"title":{},"content":{"88":{"position":[[3708,8]]}},"keywords":{}}],["opt",{"_index":4995,"title":{},"content":{"174":{"position":[[1166,3]]},"194":{"position":[[406,3]]}},"keywords":{}}],["optim",{"_index":700,"title":{"17":{"position":[[20,13]]},"136":{"position":[[0,10]]},"151":{"position":[[30,13]]},"153":{"position":[[40,10]]}},"content":{"20":{"position":[[519,12],[2197,7],[2298,12],[2771,13]]},"35":{"position":[[234,8]]},"73":{"position":[[661,8],[731,9]]},"75":{"position":[[23,8],[189,9]]},"76":{"position":[[2218,12]]},"82":{"position":[[1044,12]]},"83":{"position":[[250,12]]},"85":{"position":[[385,8],[463,9]]},"86":{"position":[[118,12],[193,12],[320,13],[993,8],[1208,13]]},"128":{"position":[[1378,9]]},"130":{"position":[[165,9]]},"141":{"position":[[252,8]]},"152":{"position":[[11,12]]},"153":{"position":[[134,13],[385,13],[923,9]]},"160":{"position":[[3037,8]]},"172":{"position":[[1844,8],[2257,13]]},"176":{"position":[[1638,8]]},"178":{"position":[[249,14]]},"188":{"position":[[216,9]]}},"keywords":{}}],["optimal.fun",{"_index":854,"title":{},"content":{"20":{"position":[[2491,11]]}},"keywords":{}}],["optimal.x",{"_index":850,"title":{},"content":{"20":{"position":[[2400,13]]}},"keywords":{}}],["optimize(d1_v",{"_index":2757,"title":{},"content":{"78":{"position":[[290,16]]}},"keywords":{}}],["optimize(data",{"_index":2718,"title":{},"content":{"76":{"position":[[1891,14]]}},"keywords":{}}],["option",{"_index":3430,"title":{},"content":{"97":{"position":[[5839,7],[5967,7]]},"173":{"position":[[647,8]]}},"keywords":{}}],["option<fixedoffset>)>",{"_index":4389,"title":{},"content":{"136":{"position":[[332,30]]}},"keywords":{}}],["option::some(z",{"_index":5317,"title":{},"content":{"194":{"position":[[412,16]]}},"keywords":{}}],["options={'maxit",{"_index":845,"title":{},"content":{"20":{"position":[[2270,19]]}},"keywords":{}}],["oracl",{"_index":1180,"title":{},"content":{"26":{"position":[[766,6]]}},"keywords":{}}],["orang",{"_index":4934,"title":{},"content":{"172":{"position":[[2383,7]]}},"keywords":{}}],["orchrt",{"_index":4953,"title":{},"content":{"173":{"position":[[844,6]]}},"keywords":{}}],["order",{"_index":305,"title":{},"content":{"6":{"position":[[4,5]]},"11":{"position":[[161,5]]},"20":{"position":[[1170,5]]},"24":{"position":[[1041,5]]},"25":{"position":[[761,5]]},"34":{"position":[[86,5],[874,5],[952,5]]},"88":{"position":[[3627,5]]},"104":{"position":[[282,5],[431,5]]},"139":{"position":[[441,6]]},"152":{"position":[[455,10]]},"156":{"position":[[905,10]]},"175":{"position":[[618,5]]},"188":{"position":[[2851,5]]},"189":{"position":[[810,5]]},"196":{"position":[[542,8],[1683,5]]}},"keywords":{}}],["ordering::seqcst",{"_index":4515,"title":{},"content":{"152":{"position":[[556,18],[1085,18]]},"156":{"position":[[997,18],[1190,18]]}},"keywords":{}}],["organ",{"_index":4056,"title":{},"content":{"125":{"position":[[1942,8]]},"150":{"position":[[501,13],[546,14]]}},"keywords":{}}],["orient",{"_index":4919,"title":{},"content":{"172":{"position":[[1373,8]]}},"keywords":{}}],["origin",{"_index":140,"title":{},"content":{"3":{"position":[[140,8]]},"4":{"position":[[292,8]]},"30":{"position":[[331,10]]},"61":{"position":[[1089,8]]},"86":{"position":[[628,10]]},"97":{"position":[[5847,11]]},"98":{"position":[[1252,10]]},"102":{"position":[[556,8],[661,8],[726,8],[825,8],[1287,8],[1393,8]]},"103":{"position":[[1890,10]]},"105":{"position":[[108,9]]},"106":{"position":[[646,8]]},"115":{"position":[[575,8],[613,8],[2967,8]]},"121":{"position":[[436,8],[2020,10]]},"122":{"position":[[502,8]]},"173":{"position":[[2148,8]]},"192":{"position":[[208,8],[293,6],[465,8],[539,7]]},"196":{"position":[[1353,8],[1504,8]]}},"keywords":{}}],["ornot",{"_index":2200,"title":{},"content":{"53":{"position":[[232,6],[421,6]]}},"keywords":{}}],["orresult",{"_index":5309,"title":{},"content":{"194":{"position":[[58,8]]}},"keywords":{}}],["os",{"_index":4651,"title":{},"content":{"160":{"position":[[254,2]]},"173":{"position":[[1797,2]]},"176":{"position":[[417,2]]}},"keywords":{}}],["oscil",{"_index":61,"title":{},"content":{"1":{"position":[[683,10]]}},"keywords":{}}],["osx",{"_index":3993,"title":{},"content":{"124":{"position":[[246,4]]}},"keywords":{}}],["other",{"_index":4921,"title":{},"content":{"172":{"position":[[1578,6]]}},"keywords":{}}],["ourselv",{"_index":2021,"title":{},"content":{"45":{"position":[[2721,10]]},"105":{"position":[[315,9]]}},"keywords":{}}],["out",{"_index":98,"title":{},"content":{"2":{"position":[[364,3]]},"3":{"position":[[1481,3],[1521,3]]},"4":{"position":[[1497,3]]},"7":{"position":[[397,3]]},"12":{"position":[[35,3]]},"22":{"position":[[242,3],[1157,3]]},"26":{"position":[[16,3]]},"28":{"position":[[588,3]]},"30":{"position":[[9,3]]},"32":{"position":[[1387,3]]},"45":{"position":[[304,3],[1571,3],[1795,3],[2592,3]]},"46":{"position":[[459,3]]},"51":{"position":[[376,3],[720,3],[2563,3],[3113,3],[3443,3]]},"52":{"position":[[16,3]]},"53":{"position":[[245,3],[557,3],[2223,3]]},"61":{"position":[[686,4],[1859,3]]},"64":{"position":[[28,3]]},"65":{"position":[[202,4],[1360,3],[1504,3],[1540,3],[2232,3],[2589,4]]},"73":{"position":[[220,3],[490,3]]},"77":{"position":[[199,3]]},"86":{"position":[[885,3]]},"88":{"position":[[2395,4]]},"91":{"position":[[2467,3]]},"92":{"position":[[280,3]]},"93":{"position":[[399,4]]},"95":{"position":[[480,4],[581,4]]},"96":{"position":[[1814,3]]},"97":{"position":[[2123,3],[5004,3],[5126,3],[5201,4],[5893,4],[6182,3],[6483,3]]},"102":{"position":[[20,3]]},"104":{"position":[[911,3]]},"105":{"position":[[3011,3]]},"112":{"position":[[1100,3]]},"120":{"position":[[444,4],[706,3]]},"121":{"position":[[897,3],[1414,4],[2198,3]]},"122":{"position":[[977,3]]},"123":{"position":[[89,3]]},"125":{"position":[[1254,3],[3032,3],[5329,3],[5436,3],[5877,3],[10000,3]]},"128":{"position":[[797,3],[1388,3]]},"129":{"position":[[375,3]]},"135":{"position":[[615,3]]},"141":{"position":[[261,3]]},"143":{"position":[[395,3]]},"146":{"position":[[425,3]]},"147":{"position":[[25,3]]},"148":{"position":[[370,3]]},"150":{"position":[[450,3]]},"152":{"position":[[854,3]]},"153":{"position":[[49,3],[99,3],[933,3]]},"155":{"position":[[1141,3]]},"157":{"position":[[104,3]]},"161":{"position":[[1046,3],[1397,3],[1570,3]]},"164":{"position":[[1112,3]]},"165":{"position":[[67,4]]},"170":{"position":[[29,3]]},"174":{"position":[[517,3],[750,3]]},"179":{"position":[[616,3],[696,3]]},"189":{"position":[[1692,3]]},"192":{"position":[[455,3]]},"193":{"position":[[764,3]]},"196":{"position":[[649,4]]}},"keywords":{}}],["out_dir",{"_index":3734,"title":{},"content":{"113":{"position":[[490,7]]}},"keywords":{}}],["outcom",{"_index":2678,"title":{},"content":{"76":{"position":[[257,7]]}},"keywords":{}}],["outdat",{"_index":248,"title":{},"content":{"4":{"position":[[644,9]]}},"keywords":{}}],["outhashmap::new",{"_index":4603,"title":{},"content":{"156":{"position":[[1835,18]]}},"keywords":{}}],["outhe'",{"_index":3900,"title":{},"content":{"121":{"position":[[1425,7]]}},"keywords":{}}],["outlier",{"_index":3175,"title":{},"content":{"91":{"position":[[5776,9]]}},"keywords":{}}],["outliv",{"_index":3416,"title":{},"content":{"97":{"position":[[4546,7]]},"155":{"position":[[95,7]]}},"keywords":{}}],["outlock_api::rwlock,lock_api::mutex",{"_index":4611,"title":{},"content":{"157":{"position":[[480,36]]}},"keywords":{}}],["outpac",{"_index":4019,"title":{},"content":{"125":{"position":[[564,8]]}},"keywords":{}}],["outperform",{"_index":1805,"title":{},"content":{"40":{"position":[[1048,12]]}},"keywords":{}}],["output",{"_index":1500,"title":{},"content":{"30":{"position":[[10132,7]]},"95":{"position":[[215,6]]},"125":{"position":[[2612,6]]},"128":{"position":[[409,6]]},"176":{"position":[[1244,6]]},"193":{"position":[[2305,7]]}},"keywords":{}}],["output_notebook",{"_index":1324,"title":{},"content":{"30":{"position":[[129,16],[280,17]]}},"keywords":{}}],["outsid",{"_index":2244,"title":{},"content":{"53":{"position":[[1060,7]]},"96":{"position":[[1932,8]]},"125":{"position":[[10436,7]]},"129":{"position":[[1088,7]]}},"keywords":{}}],["outu32,f64",{"_index":4277,"title":{},"content":{"129":{"position":[[248,10]]}},"keywords":{}}],["oven",{"_index":3845,"title":{},"content":{"118":{"position":[[307,5]]},"161":{"position":[[984,4],[1057,5],[1091,5],[1210,5],[1436,4]]}},"keywords":{}}],["over",{"_index":596,"title":{"91":{"position":[[28,4]]}},"content":{"13":{"position":[[1709,4],[2206,4]]},"14":{"position":[[2792,4],[3278,4]]},"15":{"position":[[2466,4],[2949,4]]},"18":{"position":[[53,4]]},"19":{"position":[[23,5],[71,4],[130,4]]},"20":{"position":[[53,4]]},"24":{"position":[[130,4],[274,4]]},"26":{"position":[[659,4]]},"28":{"position":[[80,4],[715,4],[2726,4],[4401,4]]},"30":{"position":[[538,4],[2374,4],[4547,4],[5590,4],[5661,4],[9167,4]]},"34":{"position":[[3549,4]]},"38":{"position":[[1096,4]]},"39":{"position":[[233,4]]},"40":{"position":[[62,4],[523,4],[861,4],[2059,4],[3003,4]]},"45":{"position":[[164,4]]},"73":{"position":[[354,4]]},"76":{"position":[[1241,5]]},"83":{"position":[[621,4]]},"85":{"position":[[394,5]]},"89":{"position":[[584,4]]},"91":{"position":[[95,4],[334,4],[2995,4],[4224,4],[4975,4],[5818,4]]},"92":{"position":[[140,4],[807,4]]},"95":{"position":[[355,4]]},"113":{"position":[[2500,4]]},"124":{"position":[[664,4]]},"125":{"position":[[152,4],[2254,4]]},"136":{"position":[[881,4],[890,5]]},"148":{"position":[[374,4]]},"199":{"position":[[873,4],[1017,4],[1306,4]]}},"keywords":{}}],["overal",{"_index":1400,"title":{},"content":{"30":{"position":[[4357,7]]},"105":{"position":[[3400,8]]},"188":{"position":[[3282,7]]}},"keywords":{}}],["overfit",{"_index":2809,"title":{},"content":{"82":{"position":[[1209,7]]},"83":{"position":[[454,9]]}},"keywords":{}}],["overflow",{"_index":5324,"title":{},"content":{"195":{"position":[[1066,8]]}},"keywords":{}}],["overhead",{"_index":5019,"title":{},"content":{"175":{"position":[[894,9]]}},"keywords":{}}],["overli",{"_index":4688,"title":{},"content":{"160":{"position":[[2295,6]]}},"keywords":{}}],["overloadable"becaus",{"_index":5360,"title":{},"content":{"198":{"position":[[636,25]]}},"keywords":{}}],["own",{"_index":3417,"title":{},"content":{"97":{"position":[[4608,5]]},"117":{"position":[[168,4],[236,5],[1485,5],[1507,5],[1632,4]]}},"keywords":{}}],["ownedseg",{"_index":3830,"title":{},"content":{"117":{"position":[[1460,13]]}},"keywords":{}}],["ownership",{"_index":3419,"title":{},"content":{"97":{"position":[[4702,9]]},"116":{"position":[[641,10],[677,9]]},"155":{"position":[[451,9]]},"160":{"position":[[1371,9]]},"193":{"position":[[3034,9]]}},"keywords":{}}],["ownershipmak",{"_index":3429,"title":{},"content":{"97":{"position":[[5728,13]]}},"keywords":{}}],["oxi",{"_index":713,"title":{},"content":{"17":{"position":[[176,6]]},"18":{"position":[[269,6]]},"19":{"position":[[495,6]]},"20":{"position":[[415,6],[2903,7]]}},"keywords":{}}],["p",{"_index":1722,"title":{},"content":{"39":{"position":[[571,2]]}},"keywords":{}}],["p"",{"_index":1489,"title":{},"content":{"30":{"position":[[9796,11],[10042,11]]}},"keywords":{}}],["p(pcurrent,pproposed)\\mathcal{p}(p_{curr",{"_index":2670,"title":{},"content":{"75":{"position":[[907,45]]}},"keywords":{}}],["p1−p",{"_index":1974,"title":{},"content":{"45":{"position":[[772,5]]}},"keywords":{}}],["p\\mathcal{p}p",{"_index":2672,"title":{},"content":{"75":{"position":[[1038,14]]}},"keywords":{}}],["p_2",{"_index":2636,"title":{},"content":{"74":{"position":[[598,3]]}},"keywords":{}}],["p_3",{"_index":2637,"title":{},"content":{"74":{"position":[[616,3]]}},"keywords":{}}],["p_val",{"_index":2595,"title":{},"content":{"70":{"position":[[990,7]]}},"keywords":{}}],["p_{11",{"_index":2639,"title":{},"content":{"74":{"position":[[650,6]]}},"keywords":{}}],["p_{12",{"_index":2640,"title":{},"content":{"74":{"position":[[672,6]]}},"keywords":{}}],["p_{proposed})p(pcurrent​,pproposed​)switch",{"_index":2671,"title":{},"content":{"75":{"position":[[953,42]]}},"keywords":{}}],["pack",{"_index":4861,"title":{},"content":{"168":{"position":[[206,6]]},"169":{"position":[[320,6]]}},"keywords":{}}],["packag",{"_index":107,"title":{},"content":{"2":{"position":[[462,7]]},"3":{"position":[[319,8]]},"108":{"position":[[397,7],[613,7]]},"109":{"position":[[240,9]]},"125":{"position":[[3942,7],[9556,8]]},"134":{"position":[[55,7]]},"190":{"position":[[544,8]]}},"keywords":{}}],["packages/ipykernel/parentpoller.py"",{"_index":5211,"title":{},"content":{"188":{"position":[[3822,41]]}},"keywords":{}}],["packaging/upgrades/etc",{"_index":4049,"title":{},"content":{"125":{"position":[[1516,23]]}},"keywords":{}}],["packet",{"_index":4774,"title":{},"content":{"163":{"position":[[1518,6],[1599,6]]},"175":{"position":[[802,7],[863,6],[1112,7],[1185,7]]}},"keywords":{}}],["packet_data",{"_index":4793,"title":{},"content":{"163":{"position":[[2054,12],[2116,13]]}},"keywords":{}}],["packet_len",{"_index":4789,"title":{},"content":{"163":{"position":[[1929,11]]}},"keywords":{}}],["pad",{"_index":3497,"title":{},"content":{"102":{"position":[[1060,6]]},"103":{"position":[[942,3],[1072,6]]}},"keywords":{}}],["padded.reshape((len(pad",{"_index":3530,"title":{},"content":{"103":{"position":[[1201,27]]}},"keywords":{}}],["page",{"_index":221,"title":{},"content":{"4":{"position":[[45,5]]},"22":{"position":[[86,5],[210,4],[790,4]]},"125":{"position":[[3857,4],[4025,5],[6667,4]]},"160":{"position":[[2936,4]]},"174":{"position":[[398,7],[593,6],[639,5],[697,4],[790,5]]}},"keywords":{}}],["paid",{"_index":547,"title":{},"content":{"13":{"position":[[237,4],[312,4]]},"14":{"position":[[164,4],[380,4]]},"15":{"position":[[178,4],[400,5],[480,5]]}},"keywords":{}}],["paid.at",{"_index":636,"title":{},"content":{"14":{"position":[[828,7]]}},"keywords":{}}],["pain",{"_index":3894,"title":{},"content":{"121":{"position":[[1246,5]]},"165":{"position":[[957,7]]},"190":{"position":[[45,4]]}},"keywords":{}}],["pair",{"_index":3116,"title":{},"content":{"91":{"position":[[2174,5]]}},"keywords":{}}],["palett",{"_index":1327,"title":{},"content":{"30":{"position":[[189,7]]}},"keywords":{}}],["palette[i",{"_index":1235,"title":{},"content":{"28":{"position":[[1057,10]]}},"keywords":{}}],["pan",{"_index":4821,"title":{},"content":{"165":{"position":[[63,3]]}},"keywords":{}}],["panda",{"_index":1328,"title":{},"content":{"30":{"position":[[204,6],[8325,6]]},"39":{"position":[[440,6]]},"43":{"position":[[274,6]]},"51":{"position":[[108,6]]},"62":{"position":[[304,6],[415,6]]},"68":{"position":[[428,6]]},"88":{"position":[[531,6]]},"90":{"position":[[202,6]]},"93":{"position":[[1252,6],[3838,6]]},"105":{"position":[[480,6]]}},"keywords":{}}],["pandas.tseries.holiday",{"_index":2963,"title":{},"content":{"90":{"position":[[220,22]]}},"keywords":{}}],["pandas.tseries.offset",{"_index":2965,"title":{},"content":{"90":{"position":[[280,22]]}},"keywords":{}}],["panic",{"_index":3507,"title":{},"content":{"103":{"position":[[269,5]]},"143":{"position":[[146,6],[287,5],[458,6]]},"144":{"position":[[234,5],[352,5],[401,5]]},"146":{"position":[[453,5]]},"147":{"position":[[352,5],[459,5],[514,5]]},"186":{"position":[[518,6]]}},"keywords":{}}],["panic!("init",{"_index":5143,"title":{},"content":{"186":{"position":[[619,17]]}},"keywords":{}}],["panic!("unexpect",{"_index":4532,"title":{},"content":{"152":{"position":[[1409,23],[1576,23]]},"156":{"position":[[1492,23],[1659,23]]}},"keywords":{}}],["panicalloc",{"_index":4525,"title":{},"content":{"152":{"position":[[1158,14],[1175,15],[1252,15],[1296,14]]},"156":{"position":[[1241,14],[1258,15],[1335,15],[1379,14]]}},"keywords":{}}],["panick",{"_index":166,"title":{},"content":{"3":{"position":[[631,9]]},"152":{"position":[[498,9],[998,10]]},"156":{"position":[[939,9],[1100,9]]}},"keywords":{}}],["paper",{"_index":2262,"title":{},"content":{"53":{"position":[[1271,5],[1987,5]]}},"keywords":{}}],["par",{"_index":1431,"title":{},"content":{"30":{"position":[[7543,3]]}},"keywords":{}}],["parallel",{"_index":4904,"title":{},"content":{"172":{"position":[[476,9],[685,9]]},"188":{"position":[[1864,8],[2410,9]]},"189":{"position":[[2354,9]]},"190":{"position":[[988,11]]}},"keywords":{}}],["param",{"_index":2375,"title":{},"content":{"61":{"position":[[1569,6]]}},"keywords":{}}],["paramet",{"_index":317,"title":{},"content":{"6":{"position":[[274,11],[624,10],[952,10]]},"14":{"position":[[1232,11]]},"15":{"position":[[599,10]]},"41":{"position":[[460,11]]},"74":{"position":[[124,11]]},"75":{"position":[[161,10],[427,10],[459,10],[505,10],[617,11],[668,9],[746,9],[806,9],[884,9],[1007,9]]},"85":{"position":[[208,9]]},"86":{"position":[[1011,10]]},"97":{"position":[[1720,9],[2396,10]]},"174":{"position":[[1104,10]]}},"keywords":{}}],["parameters.calcul",{"_index":2665,"title":{},"content":{"75":{"position":[[536,20]]}},"keywords":{}}],["parcel",{"_index":290,"title":{},"content":{"4":{"position":[[1339,6]]}},"keywords":{}}],["pardon",{"_index":3569,"title":{},"content":{"104":{"position":[[1630,7]]}},"keywords":{}}],["parking_lot",{"_index":4609,"title":{},"content":{"157":{"position":[[445,11]]}},"keywords":{}}],["pars",{"_index":879,"title":{"163":{"position":[[17,7]]}},"content":{"22":{"position":[[32,7],[236,5],[1151,5]]},"91":{"position":[[1881,5]]},"93":{"position":[[3891,5]]},"116":{"position":[[3234,6]]},"117":{"position":[[412,6],[903,7]]},"120":{"position":[[426,8]]},"122":{"position":[[284,8]]},"124":{"position":[[180,7]]},"165":{"position":[[405,7]]},"167":{"position":[[293,6]]}},"keywords":{}}],["parse(ev",{"_index":3283,"title":{},"content":{"93":{"position":[[4868,13],[5283,13]]}},"keywords":{}}],["parse(iso_str",{"_index":3124,"title":{},"content":{"91":{"position":[[2396,16]]}},"keywords":{}}],["parse(timestr",{"_index":4386,"title":{},"content":{"136":{"position":[[270,14]]}},"keywords":{}}],["parser",{"_index":920,"title":{},"content":{"22":{"position":[[988,6],[2486,6]]},"93":{"position":[[1388,6]]},"124":{"position":[[44,7]]},"136":{"position":[[689,6],[825,6],[874,6]]},"163":{"position":[[697,8],[725,6],[1642,6],[2433,6]]}},"keywords":{}}],["parser.articl",{"_index":923,"title":{},"content":{"22":{"position":[[1068,17]]}},"keywords":{}}],["parser.data",{"_index":974,"title":{},"content":{"22":{"position":[[2656,11]]}},"keywords":{}}],["parser.data.update({"text"",{"_index":972,"title":{},"content":{"22":{"position":[[2591,37]]}},"keywords":{}}],["parser.data.update({"url"",{"_index":971,"title":{},"content":{"22":{"position":[[2548,36]]}},"keywords":{}}],["parser.feed(article_html.text",{"_index":970,"title":{},"content":{"22":{"position":[[2517,30]]}},"keywords":{}}],["parser.feed(articles_html.text",{"_index":922,"title":{},"content":{"22":{"position":[[1017,31]]}},"keywords":{}}],["parser.parse(x",{"_index":3241,"title":{},"content":{"93":{"position":[[2779,15]]}},"keywords":{}}],["parser::default().pars",{"_index":4390,"title":{},"content":{"136":{"position":[[375,24]]}},"keywords":{}}],["parser::pars",{"_index":4395,"title":{},"content":{"136":{"position":[[515,13]]}},"keywords":{}}],["parseresult<(naivedatetim",{"_index":4388,"title":{},"content":{"136":{"position":[[301,30]]}},"keywords":{}}],["parsingpcap",{"_index":4769,"title":{},"content":{"163":{"position":[[817,11]]}},"keywords":{}}],["part",{"_index":1782,"title":{"40":{"position":[[24,5]]}},"content":{"51":{"position":[[1516,5]]},"64":{"position":[[195,4]]},"104":{"position":[[68,5]]},"113":{"position":[[572,4],[1082,4]]},"127":{"position":[[104,4]]},"133":{"position":[[21,4]]},"137":{"position":[[229,4]]},"150":{"position":[[956,4]]},"152":{"position":[[296,4]]},"160":{"position":[[2526,4]]},"164":{"position":[[37,4]]},"165":{"position":[[1186,4]]},"173":{"position":[[491,5]]},"176":{"position":[[948,5]]},"178":{"position":[[376,5]]},"180":{"position":[[74,4]]},"186":{"position":[[568,4]]}},"keywords":{}}],["parti",{"_index":4014,"title":{},"content":{"125":{"position":[[427,8]]}},"keywords":{}}],["particularli",{"_index":1341,"title":{},"content":{"30":{"position":[[656,12]]},"41":{"position":[[293,12]]}},"keywords":{}}],["partner",{"_index":3457,"title":{},"content":{"100":{"position":[[134,8]]}},"keywords":{}}],["pass",{"_index":473,"title":{},"content":{"9":{"position":[[634,6]]},"93":{"position":[[5101,6]]},"105":{"position":[[171,4]]},"121":{"position":[[1154,4]]},"141":{"position":[[331,4]]},"193":{"position":[[1294,4],[2951,7],[2998,7],[3047,7]]}},"keywords":{}}],["password",{"_index":2351,"title":{},"content":{"61":{"position":[[180,9],[646,9],[1017,9]]}},"keywords":{}}],["past",{"_index":1199,"title":{"91":{"position":[[37,4]]}},"content":{"28":{"position":[[89,4]]},"30":{"position":[[547,4],[5711,4]]},"33":{"position":[[341,4]]},"40":{"position":[[71,4]]},"57":{"position":[[200,4]]},"65":{"position":[[2253,4]]},"76":{"position":[[1431,4]]},"89":{"position":[[593,4]]},"91":{"position":[[104,4]]},"92":{"position":[[149,4]]},"93":{"position":[[2825,4],[2920,6]]},"125":{"position":[[161,4]]}},"keywords":{}}],["patch",{"_index":4119,"title":{},"content":{"125":{"position":[[5430,5]]}},"keywords":{}}],["path",{"_index":276,"title":{},"content":{"4":{"position":[[1051,4]]},"6":{"position":[[703,5],[1047,5]]},"7":{"position":[[585,6],[1059,5]]},"11":{"position":[[116,5]]},"12":{"position":[[187,5]]},"14":{"position":[[585,5]]},"108":{"position":[[504,5],[748,6]]},"112":{"position":[[608,5],[765,4],[894,5]]},"132":{"position":[[1006,4]]},"175":{"position":[[183,4]]}},"keywords":{}}],["path>",{"_index":122,"title":{},"content":{"2":{"position":[[730,9]]}},"keywords":{}}],["pattern",{"_index":2962,"title":{},"content":{"90":{"position":[[161,8]]},"91":{"position":[[5408,7],[5936,7]]},"92":{"position":[[1285,8],[1560,7]]},"121":{"position":[[527,9]]},"155":{"position":[[304,7]]},"179":{"position":[[343,7]]}},"keywords":{}}],["paus",{"_index":4914,"title":{},"content":{"172":{"position":[[1121,8]]},"173":{"position":[[1765,5]]}},"keywords":{}}],["pay",{"_index":670,"title":{},"content":{"15":{"position":[[215,4]]},"30":{"position":[[9479,3]]},"115":{"position":[[2590,3]]},"132":{"position":[[250,6]]},"161":{"position":[[686,6]]}},"keywords":{}}],["paymillion",{"_index":5002,"title":{},"content":{"175":{"position":[[58,11]]}},"keywords":{}}],["payoff",{"_index":582,"title":{},"content":{"13":{"position":[[1356,7]]},"14":{"position":[[2428,7]]},"15":{"position":[[2100,7]]}},"keywords":{}}],["pb",{"_index":2307,"title":{},"content":{"57":{"position":[[4,3]]}},"keywords":{}}],["pbar",{"_index":3265,"title":{},"content":{"93":{"position":[[3500,4]]}},"keywords":{}}],["pbar.update(i",{"_index":3270,"title":{},"content":{"93":{"position":[[3639,14]]}},"keywords":{}}],["pca",{"_index":1983,"title":{"99":{"position":[[0,3]]},"102":{"position":[[2,3]]}},"content":{"45":{"position":[[1382,3],[1575,3],[1978,3],[2036,3],[2628,3],[2823,3]]},"102":{"position":[[29,3],[65,3],[457,3],[862,3],[1090,3]]},"103":{"position":[[165,3],[756,4],[785,3],[850,3],[1281,3],[1293,3],[1467,4]]},"104":{"position":[[28,3],[112,3],[589,3],[747,3],[841,4],[1060,3],[1158,3],[1406,3],[1936,3]]},"105":{"position":[[523,5],[655,3],[961,3],[1005,5],[1387,4],[1510,4],[1560,4],[1952,3],[1956,3]]},"106":{"position":[[51,4],[271,3],[484,3],[563,3],[1007,3]]}},"keywords":{}}],["pca(n_components=dim",{"_index":1995,"title":{},"content":{"45":{"position":[[2042,22],[2829,22]]}},"keywords":{}}],["pca(n_components=n_compon",{"_index":3531,"title":{},"content":{"103":{"position":[[1299,30]]}},"keywords":{}}],["pca.components_.tobyt",{"_index":3593,"title":{},"content":{"105":{"position":[[1055,25]]}},"keywords":{}}],["pca.fit(reshap",{"_index":3532,"title":{},"content":{"103":{"position":[[1330,17]]}},"keywords":{}}],["pca.fit_transform(x",{"_index":2025,"title":{},"content":{"45":{"position":[[2862,20]]}},"keywords":{}}],["pca.fit_transform(x_no_bin",{"_index":1997,"title":{},"content":{"45":{"position":[[2075,27]]}},"keywords":{}}],["pca.inverse_transform(transformed).reshape((len(pad",{"_index":3536,"title":{},"content":{"103":{"position":[[1402,57]]}},"keywords":{}}],["pca.transform(reshap",{"_index":3534,"title":{},"content":{"103":{"position":[[1362,23]]}},"keywords":{}}],["pca_compression_result",{"_index":3608,"title":{},"content":{"105":{"position":[[1659,23],[1921,23]]}},"keywords":{}}],["pca_compression_results.column",{"_index":3611,"title":{},"content":{"105":{"position":[[1775,31]]}},"keywords":{}}],["pca_compression_results.index",{"_index":3616,"title":{},"content":{"105":{"position":[[1868,29]]}},"keywords":{}}],["pca_reduce(sign",{"_index":3520,"title":{},"content":{"103":{"position":[[877,18]]}},"keywords":{}}],["pca_reduce(tabulasa_left",{"_index":3539,"title":{},"content":{"103":{"position":[[1752,25],[2071,25]]},"105":{"position":[[1413,25],[2709,25],[2910,25],[3182,25]]}},"keywords":{}}],["pctl",{"_index":4858,"title":{},"content":{"168":{"position":[[172,4],[184,4]]},"169":{"position":[[286,4],[298,4]]}},"keywords":{}}],["pd",{"_index":1329,"title":{},"content":{"30":{"position":[[214,2],[8335,2]]},"39":{"position":[[450,2]]},"43":{"position":[[284,2]]},"51":{"position":[[118,2]]},"62":{"position":[[425,2]]},"68":{"position":[[438,2]]},"88":{"position":[[541,2]]},"90":{"position":[[212,2]]},"93":{"position":[[1262,2],[3848,2]]},"105":{"position":[[490,2]]}},"keywords":{}}],["pd.concat(hr_datafram",{"_index":2428,"title":{},"content":{"62":{"position":[[1225,24]]}},"keywords":{}}],["pd.concat(list(results.valu",{"_index":1779,"title":{},"content":{"39":{"position":[[3275,33]]}},"keywords":{}}],["pd.datafram",{"_index":1761,"title":{},"content":{"39":{"position":[[2642,14]]},"105":{"position":[[1685,14]]}},"keywords":{}}],["pd.dataframe(record['act",{"_index":2419,"title":{},"content":{"62":{"position":[[967,31]]}},"keywords":{}}],["pd.dataframe({"accuracy"",{"_index":1917,"title":{},"content":{"44":{"position":[[710,35]]}},"keywords":{}}],["pd.dataframe({'hashtag",{"_index":2128,"title":{},"content":{"51":{"position":[[2418,25]]}},"keywords":{}}],["pd.dataframe.from_dict(article_data).dropna",{"_index":987,"title":{},"content":{"22":{"position":[[3043,45]]}},"keywords":{}}],["pd.dataframe.from_dict(city_forecast",{"_index":1230,"title":{},"content":{"28":{"position":[[940,38]]},"30":{"position":[[1271,38]]}},"keywords":{}}],["pd.date_range(hr_df_concat.index[0",{"_index":2430,"title":{},"content":{"62":{"position":[[1338,36]]}},"keywords":{}}],["pd.date_range(start=datetime(year",{"_index":1479,"title":{},"content":{"30":{"position":[[9305,35]]}},"keywords":{}}],["pd.date_range(start_d",{"_index":2410,"title":{},"content":{"62":{"position":[[642,25]]}},"keywords":{}}],["pd.datetimeindex(start=datetime(year",{"_index":1240,"title":{},"content":{"28":{"position":[[1251,37],[3051,37]]},"30":{"position":[[1617,37],[2966,37],[4890,37],[6034,37]]}},"keywords":{}}],["pd.hdfstore('price_data.hdf",{"_index":3294,"title":{},"content":{"93":{"position":[[5494,29]]}},"keywords":{}}],["pd.read_csv('https://www.ishares.com/us/products/239714",{"_index":3247,"title":{},"content":{"93":{"position":[[3007,57]]}},"keywords":{}}],["pd.read_csv('split_train.csv",{"_index":1867,"title":{},"content":{"43":{"position":[[482,30]]}},"keywords":{}}],["pd.read_csv('train.csv",{"_index":2042,"title":{},"content":{"47":{"position":[[109,24]]}},"keywords":{}}],["pd.read_csv('tweets.csv",{"_index":2071,"title":{},"content":{"51":{"position":[[130,25]]}},"keywords":{}}],["pd.read_hdf('price_data.hdf",{"_index":3129,"title":{},"content":{"91":{"position":[[2775,29],[3531,29]]},"92":{"position":[[587,29]]}},"keywords":{}}],["pd.series(fair_1",{"_index":2564,"title":{},"content":{"68":{"position":[[572,16]]}},"keywords":{}}],["pd.series(sim",{"_index":1760,"title":{},"content":{"39":{"position":[[2618,14]]}},"keywords":{}}],["pd.series(word_dist[curr",{"_index":2165,"title":{},"content":{"51":{"position":[[4124,29]]}},"keywords":{}}],["pd.series(x1",{"_index":2603,"title":{},"content":{"70":{"position":[[1161,12]]},"71":{"position":[[1312,12]]}},"keywords":{}}],["peac",{"_index":3895,"title":{},"content":{"121":{"position":[[1257,5]]}},"keywords":{}}],["peak",{"_index":3101,"title":{},"content":{"91":{"position":[[1566,4]]}},"keywords":{}}],["peek",{"_index":4293,"title":{},"content":{"129":{"position":[[980,7]]}},"keywords":{}}],["penal",{"_index":1687,"title":{},"content":{"38":{"position":[[97,8],[823,8]]}},"keywords":{}}],["penalti",{"_index":4985,"title":{},"content":{"174":{"position":[[562,7]]}},"keywords":{}}],["peopl",{"_index":1322,"title":{},"content":{"30":{"position":[[21,6],[394,6],[2456,6],[9222,6],[9238,6]]},"32":{"position":[[25,7]]},"51":{"position":[[224,6]]},"59":{"position":[[33,6]]},"61":{"position":[[13,6],[105,6]]},"66":{"position":[[194,6]]},"89":{"position":[[227,6]]},"96":{"position":[[632,6]]},"101":{"position":[[909,6]]},"112":{"position":[[305,6]]},"120":{"position":[[349,6],[603,6]]},"122":{"position":[[1317,6]]},"123":{"position":[[901,6]]},"125":{"position":[[350,6]]},"150":{"position":[[156,6],[587,6]]},"160":{"position":[[2411,8]]},"176":{"position":[[180,7]]}},"keywords":{}}],["people'",{"_index":1342,"title":{},"content":{"30":{"position":[[717,8]]}},"keywords":{}}],["pep",{"_index":361,"title":{},"content":{"6":{"position":[[896,3]]}},"keywords":{}}],["per",{"_index":369,"title":{},"content":{"6":{"position":[[1025,3],[1094,3]]},"51":{"position":[[1950,3]]},"64":{"position":[[639,3]]},"65":{"position":[[525,3],[560,3]]},"101":{"position":[[87,3]]},"105":{"position":[[605,3],[752,3]]}},"keywords":{}}],["percentag",{"_index":1274,"title":{},"content":{"28":{"position":[[2189,12],[3862,12]]},"30":{"position":[[844,11],[2584,10]]},"90":{"position":[[4816,10]]}},"keywords":{}}],["percept",{"_index":1343,"title":{},"content":{"30":{"position":[[726,11]]}},"keywords":{}}],["perci",{"_index":4159,"title":{},"content":{"125":{"position":[[8266,5],[8339,6],[8787,5],[8853,5]]}},"keywords":{}}],["percymov",{"_index":4210,"title":{},"content":{"125":{"position":[[11358,11]]}},"keywords":{}}],["perf",{"_index":4989,"title":{},"content":{"174":{"position":[[715,4]]},"176":{"position":[[671,4]]}},"keywords":{}}],["perfect",{"_index":3989,"title":{},"content":{"123":{"position":[[1125,8]]}},"keywords":{}}],["perfectli",{"_index":5256,"title":{},"content":{"189":{"position":[[2998,9]]}},"keywords":{}}],["perform",{"_index":775,"title":{"171":{"position":[[17,11]]}},"content":{"20":{"position":[[504,10]]},"40":{"position":[[1165,10],[1512,8],[2519,8],[3268,9],[3370,9]]},"44":{"position":[[1741,8]]},"45":{"position":[[30,8],[100,11],[1131,7],[2650,10]]},"46":{"position":[[307,7]]},"73":{"position":[[239,7]]},"75":{"position":[[820,8]]},"88":{"position":[[2288,7],[2351,7]]},"91":{"position":[[55,7],[1723,8]]},"93":{"position":[[97,11],[168,12],[655,7],[785,11]]},"143":{"position":[[472,11]]},"148":{"position":[[42,11],[442,11]]},"158":{"position":[[14,11]]},"160":{"position":[[3320,12]]},"163":{"position":[[2361,12]]},"164":{"position":[[226,11]]},"165":{"position":[[182,12],[1022,12],[1472,7]]},"166":{"position":[[142,11]]},"169":{"position":[[108,7],[197,11]]},"170":{"position":[[255,12],[283,11]]},"172":{"position":[[1432,12],[1692,11],[2539,12]]},"174":{"position":[[130,11]]},"176":{"position":[[6,11],[289,11],[1419,11]]},"189":{"position":[[567,11],[1252,11],[1645,7],[2640,12]]}},"keywords":{}}],["performance"",{"_index":5049,"title":{},"content":{"176":{"position":[[911,18]]}},"keywords":{}}],["performancey",{"_index":4620,"title":{},"content":{"158":{"position":[[147,14]]}},"keywords":{}}],["period",{"_index":496,"title":{},"content":{"10":{"position":[[356,8]]},"18":{"position":[[68,7]]},"19":{"position":[[89,7]]},"20":{"position":[[71,7]]},"34":{"position":[[3556,6]]},"40":{"position":[[1268,7],[1535,7],[3250,7],[3469,8]]},"52":{"position":[[698,7]]},"65":{"position":[[318,7],[778,7],[957,7],[1058,8],[1111,7],[1167,8],[1221,7]]},"91":{"position":[[341,6]]}},"keywords":{}}],["peripher",{"_index":4687,"title":{},"content":{"160":{"position":[[2171,11]]}},"keywords":{}}],["permut",{"_index":2693,"title":{},"content":{"76":{"position":[[864,7],[2800,11]]}},"keywords":{}}],["permute(cur_d1",{"_index":2737,"title":{},"content":{"76":{"position":[[2611,15]]}},"keywords":{}}],["permute(d1_dens",{"_index":2696,"title":{},"content":{"76":{"position":[[969,19]]}},"keywords":{}}],["person",{"_index":1890,"title":{},"content":{"43":{"position":[[1361,7],[1409,7]]},"59":{"position":[[54,8]]},"60":{"position":[[27,8]]},"101":{"position":[[919,10]]},"105":{"position":[[3347,10]]},"125":{"position":[[10875,10]]},"150":{"position":[[539,6]]},"161":{"position":[[91,8]]}},"keywords":{}}],["perspect",{"_index":2651,"title":{},"content":{"74":{"position":[[1307,12]]},"173":{"position":[[247,12]]},"198":{"position":[[191,11]]}},"keywords":{}}],["phasea",{"_index":4214,"title":{},"content":{"125":{"position":[[11490,6]]}},"keywords":{}}],["philosoph",{"_index":2545,"title":{},"content":{"66":{"position":[[518,15]]}},"keywords":{}}],["philosophi",{"_index":5053,"title":{},"content":{"176":{"position":[[1455,11]]}},"keywords":{}}],["phoenix",{"_index":622,"title":{"14":{"position":[[0,7]]},"15":{"position":[[0,7]]}},"content":{"14":{"position":[[27,7],[227,7],[2943,7],[3334,7]]},"15":{"position":[[5,7],[58,8],[2617,7],[3005,7]]}},"keywords":{}}],["phoenix_no_memori",{"_index":651,"title":{},"content":{"14":{"position":[[2322,17],[2601,19]]}},"keywords":{}}],["phoenix_with_memori",{"_index":683,"title":{},"content":{"15":{"position":[[1992,19],[2273,21]]}},"keywords":{}}],["phonomena",{"_index":2898,"title":{},"content":{"88":{"position":[[2076,10]]}},"keywords":{}}],["pic",{"_index":3841,"title":{},"content":{"118":{"position":[[134,5]]},"161":{"position":[[252,5]]}},"keywords":{}}],["pick",{"_index":2143,"title":{},"content":{"51":{"position":[[3255,4],[3327,4]]},"124":{"position":[[479,4]]}},"keywords":{}}],["pickl",{"_index":1330,"title":{},"content":{"30":{"position":[[273,6],[900,6],[10061,6]]}},"keywords":{}}],["pickle.dump(city_forecast",{"_index":1497,"title":{},"content":{"30":{"position":[[10068,27]]}},"keywords":{}}],["pickle.load(open('city_forecasts.p",{"_index":1227,"title":{},"content":{"28":{"position":[[881,36]]},"30":{"position":[[1213,36]]}},"keywords":{}}],["pictur",{"_index":2557,"title":{},"content":{"68":{"position":[[224,7]]},"118":{"position":[[238,8]]},"135":{"position":[[70,7]]}},"keywords":{}}],["piec",{"_index":2717,"title":{},"content":{"76":{"position":[[1869,6]]},"97":{"position":[[5460,5]]}},"keywords":{}}],["pij∈(0,1);i,j∈{1,…,6}p_{ij",{"_index":2821,"title":{},"content":{"85":{"position":[[241,27]]}},"keywords":{}}],["pin",{"_index":4972,"title":{},"content":{"173":{"position":[[2201,7]]},"176":{"position":[[1002,7]]}},"keywords":{}}],["pip_ipi",{"_index":2642,"title":{},"content":{"74":{"position":[[778,8]]}},"keywords":{}}],["pipelin",{"_index":4198,"title":{},"content":{"125":{"position":[[10309,9]]},"174":{"position":[[321,9]]}},"keywords":{}}],["pipelining/specul",{"_index":4973,"title":{},"content":{"174":{"position":[[5,23]]}},"keywords":{}}],["place",{"_index":147,"title":{},"content":{"3":{"position":[[299,7]]},"4":{"position":[[334,5]]},"22":{"position":[[2695,6]]},"30":{"position":[[8064,6]]},"32":{"position":[[681,6]]},"98":{"position":[[262,6]]},"123":{"position":[[1004,5]]},"125":{"position":[[3324,6],[5071,6],[10583,5]]},"135":{"position":[[520,7]]},"136":{"position":[[758,6]]},"155":{"position":[[961,6]]},"156":{"position":[[652,5]]},"179":{"position":[[99,6]]}},"keywords":{}}],["plan",{"_index":1848,"title":{"41":{"position":[[12,5]]}},"content":{"75":{"position":[[1216,5]]},"96":{"position":[[2094,4]]},"113":{"position":[[2485,8]]},"132":{"position":[[381,8]]},"161":{"position":[[120,8],[1714,8]]}},"keywords":{}}],["platform",{"_index":4187,"title":{},"content":{"125":{"position":[[9513,8]]},"160":{"position":[[3469,8]]}},"keywords":{}}],["play",{"_index":62,"title":{},"content":{"1":{"position":[[694,7]]},"41":{"position":[[28,7],[435,7]]},"45":{"position":[[2635,4]]},"46":{"position":[[91,5]]},"98":{"position":[[617,7]]},"125":{"position":[[9917,4]]},"139":{"position":[[931,4]]},"150":{"position":[[620,4]]}},"keywords":{}}],["playground",{"_index":4538,"title":{},"content":{"152":{"position":[[1689,10]]},"153":{"position":[[1060,10]]},"156":{"position":[[1749,10]]},"179":{"position":[[754,10],[1178,10],[1618,10]]},"184":{"position":[[390,10],[739,10],[1172,10]]},"185":{"position":[[868,10]]},"186":{"position":[[675,10]]},"195":{"position":[[853,10]]}},"keywords":{}}],["pleas",{"_index":1445,"title":{},"content":{"30":{"position":[[8195,6]]},"43":{"position":[[223,6]]},"111":{"position":[[256,6]]},"147":{"position":[[65,6]]},"158":{"position":[[425,6]]},"160":{"position":[[4308,6]]}},"keywords":{}}],["plenti",{"_index":1216,"title":{},"content":{"28":{"position":[[620,6]]},"35":{"position":[[187,6]]},"89":{"position":[[50,6]]},"118":{"position":[[47,6]]},"125":{"position":[[340,6]]},"139":{"position":[[548,6]]},"176":{"position":[[1554,6]]},"183":{"position":[[670,6]]}},"keywords":{}}],["plot",{"_index":2919,"title":{},"content":{"88":{"position":[[2747,4],[3152,4]]},"91":{"position":[[902,6],[1378,7]]},"175":{"position":[[100,4]]}},"keywords":{}}],["plot(x=x",{"_index":436,"title":{},"content":{"7":{"position":[[1209,9]]}},"keywords":{}}],["plot_hilo(ax",{"_index":2906,"title":{},"content":{"88":{"position":[[2442,13]]}},"keywords":{}}],["plot_hilo(ax_aapl",{"_index":2921,"title":{},"content":{"88":{"position":[[2812,18],[2882,18]]}},"keywords":{}}],["plot_hilo(ax_fb",{"_index":2931,"title":{},"content":{"88":{"position":[[3211,16],[3278,16]]}},"keywords":{}}],["plot_study(array",{"_index":2978,"title":{},"content":{"90":{"position":[[743,18]]}},"keywords":{}}],["plot_study(five_day_ev",{"_index":3154,"title":{},"content":{"91":{"position":[[4169,27]]}},"keywords":{}}],["plot_study_small(array",{"_index":3014,"title":{},"content":{"90":{"position":[[2122,24]]}},"keywords":{}}],["plot_study_small(data",{"_index":3046,"title":{},"content":{"90":{"position":[[4169,22]]}},"keywords":{}}],["plt",{"_index":1718,"title":{},"content":{"39":{"position":[[481,3]]},"43":{"position":[[334,3]]},"51":{"position":[[1653,3]]},"68":{"position":[[469,3]]},"88":{"position":[[310,3]]}},"keywords":{}}],["plt.annot",{"_index":3051,"title":{},"content":{"90":{"position":[[4380,16]]}},"keywords":{}}],["plt.annotate('$\\pm",{"_index":3057,"title":{},"content":{"90":{"position":[[4472,19]]}},"keywords":{}}],["plt.annotate('mean",{"_index":3047,"title":{},"content":{"90":{"position":[[4244,18]]}},"keywords":{}}],["plt.annotate('min/max",{"_index":3061,"title":{},"content":{"90":{"position":[[4589,21]]}},"keywords":{}}],["plt.axhline(1",{"_index":2012,"title":{},"content":{"45":{"position":[[2365,13],[3145,13]]}},"keywords":{}}],["plt.axhline(naive_guess",{"_index":2009,"title":{},"content":{"45":{"position":[[2302,24],[3082,24]]}},"keywords":{}}],["plt.bar(coef_rang",{"_index":2763,"title":{},"content":{"78":{"position":[[470,19],[669,19]]}},"keywords":{}}],["plt.errorbar(range(1",{"_index":3017,"title":{},"content":{"90":{"position":[[3015,21]]}},"keywords":{}}],["plt.fill_between(range(0",{"_index":3016,"title":{},"content":{"90":{"position":[[2790,25]]}},"keywords":{}}],["plt.gcf().set_size_inches(10",{"_index":2773,"title":{},"content":{"78":{"position":[[764,29]]}},"keywords":{}}],["plt.gcf().set_size_inches(12",{"_index":2014,"title":{},"content":{"45":{"position":[[2440,29],[3220,29]]},"90":{"position":[[4210,29]]}},"keywords":{}}],["plt.gcf().set_size_inches(18",{"_index":1792,"title":{},"content":{"40":{"position":[[276,29],[445,29],[1810,29],[1981,29],[2753,29],[2925,29]]},"91":{"position":[[4292,29]]}},"keywords":{}}],["plt.gcf().suptitle("distribut",{"_index":1793,"title":{},"content":{"40":{"position":[[310,37],[1844,37],[2787,37]]}},"keywords":{}}],["plt.gcf().suptitle("profit",{"_index":1798,"title":{},"content":{"40":{"position":[[478,38],[2014,38],[2958,38]]}},"keywords":{}}],["plt.gcf().suptitle('act",{"_index":3155,"title":{},"content":{"91":{"position":[[4197,26]]}},"keywords":{}}],["plt.hist(d1_val",{"_index":2768,"title":{},"content":{"78":{"position":[[579,16]]}},"keywords":{}}],["plt.legend",{"_index":2015,"title":{},"content":{"45":{"position":[[2473,13],[3253,13]]}},"keywords":{}}],["plt.legend(loc=2",{"_index":2896,"title":{},"content":{"88":{"position":[[2006,18]]},"90":{"position":[[3121,17]]}},"keywords":{}}],["plt.legend(loc=3",{"_index":2884,"title":{},"content":{"88":{"position":[[1631,17]]},"90":{"position":[[4192,17]]}},"keywords":{}}],["plt.plot(dim_rang",{"_index":2004,"title":{},"content":{"45":{"position":[[2200,19],[2980,19]]}},"keywords":{}}],["plt.plot(range(range_begin",{"_index":3015,"title":{},"content":{"90":{"position":[[2743,27]]}},"keywords":{}}],["plt.subplot",{"_index":2864,"title":{},"content":{"88":{"position":[[1079,14]]}},"keywords":{}}],["plt.subplot(221",{"_index":2762,"title":{},"content":{"78":{"position":[[453,16]]}},"keywords":{}}],["plt.subplot(222",{"_index":2767,"title":{},"content":{"78":{"position":[[562,16]]}},"keywords":{}}],["plt.subplot(223",{"_index":2770,"title":{},"content":{"78":{"position":[[652,16]]}},"keywords":{}}],["plt.subplots(1",{"_index":2914,"title":{},"content":{"88":{"position":[[2690,15]]},"90":{"position":[[1321,15]]},"91":{"position":[[419,15]]}},"keywords":{}}],["plt.title("$d_1",{"_index":2610,"title":{},"content":{"71":{"position":[[1358,21]]}},"keywords":{}}],["plt.title("appl",{"_index":2885,"title":{},"content":{"88":{"position":[[1649,21]]}},"keywords":{}}],["plt.title('$d_1",{"_index":2605,"title":{},"content":{"70":{"position":[[1208,16]]}},"keywords":{}}],["plt.title('empir",{"_index":2769,"title":{},"content":{"78":{"position":[[616,20]]}},"keywords":{}}],["plt.title('facebook",{"_index":2893,"title":{},"content":{"88":{"position":[[1958,19]]}},"keywords":{}}],["plt.title('fair",{"_index":2567,"title":{},"content":{"68":{"position":[[627,15]]}},"keywords":{}}],["plt.title('recov",{"_index":2772,"title":{},"content":{"78":{"position":[[728,20]]}},"keywords":{}}],["plt.title('tru",{"_index":2766,"title":{},"content":{"78":{"position":[[531,15]]}},"keywords":{}}],["plt.vlines(date2num(datetime(2016",{"_index":2878,"title":{},"content":{"88":{"position":[[1510,34],[1837,34]]}},"keywords":{}}],["plt.xlim",{"_index":3018,"title":{},"content":{"90":{"position":[[3139,10]]}},"keywords":{}}],["plu",{"_index":634,"title":{},"content":{"14":{"position":[[806,4],[1143,4]]},"61":{"position":[[1117,5]]},"194":{"position":[[518,4]]}},"keywords":{}}],["plugin",{"_index":204,"title":{},"content":{"3":{"position":[[1296,7]]},"4":{"position":[[32,6]]}},"keywords":{}}],["pm",{"_index":1502,"title":{},"content":{"30":{"position":[[10194,2],[10248,2],[10298,2],[10349,2],[10387,2]]},"53":{"position":[[1431,3]]},"65":{"position":[[2549,2]]},"121":{"position":[[1089,2]]}},"keywords":{}}],["podcast",{"_index":3298,"title":{"94":{"position":[[12,10]]}},"content":{},"keywords":{}}],["poi(1)\\sim",{"_index":2116,"title":{},"content":{"51":{"position":[[1963,11]]}},"keywords":{}}],["poi(1)∼poi(1",{"_index":2117,"title":{},"content":{"51":{"position":[[1975,14]]}},"keywords":{}}],["point",{"_index":179,"title":{"113":{"position":[[17,6]]}},"content":{"3":{"position":[[856,6]]},"4":{"position":[[268,5]]},"25":{"position":[[2742,6]]},"28":{"position":[[477,5]]},"33":{"position":[[156,5]]},"50":{"position":[[157,5]]},"82":{"position":[[69,7]]},"86":{"position":[[358,7]]},"91":{"position":[[2642,6]]},"92":{"position":[[454,6],[1632,6]]},"93":{"position":[[2003,5]]},"97":{"position":[[2237,6]]},"105":{"position":[[693,6]]},"110":{"position":[[464,5]]},"112":{"position":[[1094,5],[1499,5]]},"113":{"position":[[932,7],[2102,7]]},"117":{"position":[[562,5]]},"123":{"position":[[482,5]]},"125":{"position":[[1683,5],[2834,6],[3237,5],[3804,5],[7505,6],[9177,5],[10225,5],[10354,5]]},"136":{"position":[[236,5]]},"147":{"position":[[19,5]]},"157":{"position":[[95,8]]},"163":{"position":[[357,6]]},"164":{"position":[[1229,5]]},"175":{"position":[[154,5],[165,5]]},"178":{"position":[[479,6]]},"179":{"position":[[11,5]]},"185":{"position":[[30,6]]},"190":{"position":[[50,6]]},"192":{"position":[[122,5],[165,6],[175,6],[302,5],[327,7],[376,5],[384,5],[478,7],[550,5]]},"193":{"position":[[913,5],[1776,5],[1811,5],[1843,5],[2218,5],[2731,5],[2766,5],[2798,5],[3184,5],[3252,6],[3262,6]]},"194":{"position":[[786,5]]}},"keywords":{}}],["point.capnp",{"_index":3695,"title":{},"content":{"110":{"position":[[422,12]]}},"keywords":{}}],["point_capnp",{"_index":3733,"title":{},"content":{"113":{"position":[[448,11]]}},"keywords":{}}],["point_capnp.r",{"_index":3714,"title":{},"content":{"112":{"position":[[694,14]]},"113":{"position":[[604,14]]}},"keywords":{}}],["point_capnp::point::owned>",{"_index":3828,"title":{},"content":{"117":{"position":[[1332,29]]}},"keywords":{}}],["point_capnp::point::read",{"_index":3813,"title":{},"content":{"116":{"position":[[2955,26]]},"117":{"position":[[1688,26]]}},"keywords":{}}],["point_capnp::point::reader<'_>",{"_index":3807,"title":{},"content":{"116":{"position":[[1007,38],[1307,38],[2001,38]]}},"keywords":{}}],["point_msg",{"_index":3747,"title":{},"content":{"113":{"position":[[1352,9]]}},"keywords":{}}],["point_msg.set_x(12",{"_index":3749,"title":{},"content":{"113":{"position":[[1461,20]]}},"keywords":{}}],["point_msg.set_y(14",{"_index":3750,"title":{},"content":{"113":{"position":[[1482,20]]}},"keywords":{}}],["point_read",{"_index":3761,"title":{},"content":{"113":{"position":[[2177,12]]},"115":{"position":[[365,12],[462,14],[641,14]]},"116":{"position":[[70,13],[465,12]]},"117":{"position":[[1254,13],[1427,12],[1619,12],[1953,12]]}},"keywords":{}}],["point_reader.get().unwrap",{"_index":3833,"title":{},"content":{"117":{"position":[[1750,28]]}},"keywords":{}}],["point_reader:point_capnp::point::reader<'_>",{"_index":3777,"title":{},"content":{"115":{"position":[[1042,51],[1389,51],[2130,51]]}},"keywords":{}}],["point_root",{"_index":3832,"title":{},"content":{"117":{"position":[[1737,10]]}},"keywords":{}}],["pointer",{"_index":3360,"title":{"155":{"position":[[6,9]]}},"content":{"97":{"position":[[121,8]]},"115":{"position":[[2930,7]]},"116":{"position":[[37,7],[2671,8]]},"127":{"position":[[886,8]]},"128":{"position":[[1806,7],[1857,7]]},"155":{"position":[[230,7],[502,8],[628,8],[917,7],[1038,8],[1062,7]]},"156":{"position":[[280,8]]},"157":{"position":[[364,8]]},"159":{"position":[[603,7],[753,9],[969,8],[1131,8]]},"181":{"position":[[805,8],[914,8]]},"193":{"position":[[493,7],[3057,8]]},"197":{"position":[[1247,7]]},"198":{"position":[[415,8]]}},"keywords":{}}],["pointer"",{"_index":4558,"title":{},"content":{"155":{"position":[[45,13]]}},"keywords":{}}],["poisson",{"_index":2061,"title":{},"content":{"49":{"position":[[554,7]]},"51":{"position":[[1870,7]]}},"keywords":{}}],["polici",{"_index":380,"title":{"123":{"position":[[18,7]]}},"content":{"7":{"position":[[105,6]]},"123":{"position":[[107,6]]}},"keywords":{}}],["polyglot",{"_index":4824,"title":{},"content":{"165":{"position":[[195,9]]}},"keywords":{}}],["polynomi",{"_index":1954,"title":{},"content":{"44":{"position":[[1916,10]]},"45":{"position":[[546,10]]},"76":{"position":[[164,10]]},"86":{"position":[[924,10]]}},"keywords":{}}],["polynomial.polynomial(d1_dens",{"_index":2681,"title":{},"content":{"76":{"position":[[349,33]]}},"keywords":{}}],["polynomial.polynomial(d2_dens",{"_index":2683,"title":{},"content":{"76":{"position":[[390,33]]}},"keywords":{}}],["pool",{"_index":3260,"title":{},"content":{"93":{"position":[[3391,5]]}},"keywords":{}}],["pool.submit(earnings_releas",{"_index":3262,"title":{},"content":{"93":{"position":[[3402,31]]}},"keywords":{}}],["poor",{"_index":1125,"title":{"100":{"position":[[26,5]]}},"content":{"24":{"position":[[3114,4]]},"103":{"position":[[2042,5],[2226,5]]},"105":{"position":[[2825,4]]},"165":{"position":[[1003,4]]},"189":{"position":[[2635,4]]}},"keywords":{}}],["poorli",{"_index":2902,"title":{},"content":{"88":{"position":[[2296,7],[2359,7]]},"93":{"position":[[663,6]]}},"keywords":{}}],["pop",{"_index":2968,"title":{},"content":{"90":{"position":[[450,3]]},"128":{"position":[[897,3],[1492,3]]}},"keywords":{}}],["popinstruct",{"_index":4717,"title":{},"content":{"160":{"position":[[4081,15]]}},"keywords":{}}],["popular",{"_index":3480,"title":{},"content":{"101":{"position":[[615,8]]},"150":{"position":[[924,7]]}},"keywords":{}}],["port",{"_index":1711,"title":{"119":{"position":[[15,7]]}},"content":{"39":{"position":[[286,6]]},"164":{"position":[[184,4]]},"166":{"position":[[602,4]]}},"keywords":{}}],["portabl",{"_index":287,"title":{},"content":{"4":{"position":[[1257,9]]}},"keywords":{}}],["portfolio",{"_index":795,"title":{},"content":{"20":{"position":[[860,10],[1527,9],[1554,9],[1605,10]]}},"keywords":{}}],["pose",{"_index":3393,"title":{},"content":{"97":{"position":[[2458,5]]}},"keywords":{}}],["posit",{"_index":745,"title":{},"content":{"19":{"position":[[231,9]]},"20":{"position":[[116,10],[990,10]]},"33":{"position":[[1026,9],[1247,9]]},"34":{"position":[[3540,8],[3939,9]]},"35":{"position":[[104,8]]},"38":{"position":[[1189,9]]},"81":{"position":[[82,8]]},"150":{"position":[[812,9]]},"161":{"position":[[63,10]]}},"keywords":{}}],["possibl",{"_index":1578,"title":{},"content":{"33":{"position":[[557,8],[978,8]]},"51":{"position":[[1100,8]]},"68":{"position":[[38,9]]},"69":{"position":[[261,9]]},"76":{"position":[[1201,13],[1585,11],[2990,8]]},"90":{"position":[[5341,8]]},"102":{"position":[[645,8],[1450,8]]},"115":{"position":[[2911,11]]},"120":{"position":[[1027,8]]},"121":{"position":[[456,9]]},"122":{"position":[[522,9]]},"125":{"position":[[3302,8]]},"132":{"position":[[91,8]]},"159":{"position":[[1230,9]]},"160":{"position":[[1323,9],[1698,8]]},"164":{"position":[[1498,9]]},"175":{"position":[[221,9]]},"181":{"position":[[682,9]]}},"keywords":{}}],["possible.y",{"_index":1579,"title":{},"content":{"33":{"position":[[722,12]]}},"keywords":{}}],["post",{"_index":250,"title":{"41":{"position":[[31,5]]}},"content":{"4":{"position":[[659,5]]},"26":{"position":[[905,7]]},"30":{"position":[[7972,4],[8189,5],[8273,5],[8312,5]]},"35":{"position":[[276,4],[294,4]]},"39":{"position":[[214,5]]},"41":{"position":[[413,5]]},"45":{"position":[[614,5]]},"53":{"position":[[862,4],[1324,7]]},"66":{"position":[[334,4]]},"86":{"position":[[674,4],[697,4]]},"96":{"position":[[639,4]]},"118":{"position":[[230,7]]},"125":{"position":[[2210,4],[2303,4],[2373,4],[2396,4]]},"133":{"position":[[33,5]]},"136":{"position":[[169,4]]},"166":{"position":[[72,6]]}},"keywords":{}}],["posts/contributor",{"_index":4221,"title":{},"content":{"125":{"position":[[11656,19]]}},"keywords":{}}],["potenti",{"_index":359,"title":{},"content":{"6":{"position":[[876,10]]},"35":{"position":[[446,10]]},"38":{"position":[[432,9]]},"91":{"position":[[5800,9]]},"98":{"position":[[1033,11]]},"123":{"position":[[504,9]]},"124":{"position":[[364,11]]},"160":{"position":[[4384,9]]},"172":{"position":[[1108,9]]},"190":{"position":[[583,13]]},"198":{"position":[[303,9]]}},"keywords":{}}],["power",{"_index":2018,"title":{},"content":{"45":{"position":[[2538,6],[3474,6]]}},"keywords":{}}],["ppp",{"_index":1975,"title":{},"content":{"45":{"position":[[783,3]]}},"keywords":{}}],["pr",{"_index":4108,"title":{},"content":{"125":{"position":[[5114,2]]}},"keywords":{}}],["practic",{"_index":1696,"title":{"114":{"position":[[20,9]]}},"content":{"38":{"position":[[731,9]]},"76":{"position":[[1632,8]]},"105":{"position":[[254,9]]},"106":{"position":[[1114,9]]},"113":{"position":[[2530,9]]},"122":{"position":[[712,9]]},"123":{"position":[[991,9]]},"129":{"position":[[2664,8]]},"188":{"position":[[4035,9]]},"197":{"position":[[1461,9]]}},"keywords":{}}],["pre",{"_index":4266,"title":{},"content":{"128":{"position":[[808,3]]},"150":{"position":[[295,3]]},"168":{"position":[[130,3]]},"193":{"position":[[316,3]]}},"keywords":{}}],["preced",{"_index":3099,"title":{},"content":{"91":{"position":[[1465,9],[2527,9]]},"92":{"position":[[339,9]]}},"keywords":{}}],["precip_day",{"_index":1420,"title":{},"content":{"30":{"position":[[6325,11]]}},"keywords":{}}],["precip_prob_sampl",{"_index":1419,"title":{},"content":{"30":{"position":[[6240,19],[6422,19]]}},"keywords":{}}],["precip_prob_v",{"_index":1418,"title":{},"content":{"30":{"position":[[6150,16],[6305,19],[6366,17]]}},"keywords":{}}],["precip_sampl",{"_index":1301,"title":{},"content":{"28":{"position":[[3257,14],[3519,14]]},"30":{"position":[[5091,14],[5198,14]]}},"keywords":{}}],["precip_v",{"_index":1299,"title":{},"content":{"28":{"position":[[3167,11],[3317,14]]},"30":{"position":[[5006,11],[5151,14]]}},"keywords":{}}],["precipit",{"_index":1219,"title":{},"content":{"28":{"position":[[686,13],[3764,13],[4325,13]]},"29":{"position":[[122,13]]},"30":{"position":[[4477,13],[4526,13],[4648,13],[5336,13],[5576,13]]}},"keywords":{}}],["precipprob",{"_index":1296,"title":{},"content":{"28":{"position":[[2916,19]]},"30":{"position":[[4761,19]]}},"keywords":{}}],["precis",{"_index":2657,"title":{},"content":{"74":{"position":[[1629,7]]},"98":{"position":[[1098,7]]},"145":{"position":[[30,10]]},"146":{"position":[[15,7]]},"160":{"position":[[4145,7]]},"176":{"position":[[92,9]]}},"keywords":{}}],["predetermin",{"_index":1597,"title":{},"content":{"34":{"position":[[629,13]]}},"keywords":{}}],["predict",{"_index":1016,"title":{"25":{"position":[[16,10]]},"42":{"position":[[0,10]]}},"content":{"24":{"position":[[92,10],[157,10],[244,10],[2632,10],[2979,10]]},"25":{"position":[[47,7],[2355,10],[2663,10],[2695,10]]},"26":{"position":[[116,10],[268,10],[343,7],[473,10],[578,10]]},"33":{"position":[[747,10]]},"43":{"position":[[716,11],[855,10],[1482,10]]},"44":{"position":[[421,10],[953,10],[1881,11]]},"45":{"position":[[1278,11],[1419,10],[1637,7],[3463,10]]},"46":{"position":[[182,7]]},"63":{"position":[[96,11]]},"65":{"position":[[2267,9]]},"88":{"position":[[3660,7]]},"89":{"position":[[180,8],[423,7]]},"92":{"position":[[1666,12]]},"93":{"position":[[777,7],[843,11]]},"139":{"position":[[867,7]]},"143":{"position":[[343,8]]},"174":{"position":[[166,11]]},"194":{"position":[[548,7]]}},"keywords":{}}],["predictablegold",{"_index":1124,"title":{},"content":{"24":{"position":[[3093,15]]}},"keywords":{}}],["prediction_dict",{"_index":1068,"title":{},"content":{"24":{"position":[[1596,15]]},"25":{"position":[[1350,15]]}},"keywords":{}}],["prediction_dict[index",{"_index":1085,"title":{},"content":{"24":{"position":[[2211,22]]},"25":{"position":[[1935,22]]}},"keywords":{}}],["predictor",{"_index":1126,"title":{},"content":{"24":{"position":[[3119,9]]},"44":{"position":[[174,10]]},"45":{"position":[[942,9]]},"174":{"position":[[386,10]]}},"keywords":{}}],["prefer",{"_index":1881,"title":{},"content":{"43":{"position":[[797,9]]}},"keywords":{}}],["prefetch",{"_index":5092,"title":{},"content":{"180":{"position":[[306,8]]}},"keywords":{}}],["preliminari",{"_index":1850,"title":{},"content":{"41":{"position":[[111,11]]}},"keywords":{}}],["prepar",{"_index":2899,"title":{},"content":{"88":{"position":[[2102,8]]},"100":{"position":[[67,8]]},"109":{"position":[[609,8]]}},"keywords":{}}],["preponder",{"_index":2945,"title":{},"content":{"89":{"position":[[122,13]]}},"keywords":{}}],["prescript",{"_index":4057,"title":{},"content":{"125":{"position":[[2078,13]]}},"keywords":{}}],["present",{"_index":619,"title":{},"content":{"13":{"position":[[2245,7]]},"14":{"position":[[3317,7]]},"15":{"position":[[2988,7]]},"32":{"position":[[700,7]]},"36":{"position":[[25,12]]},"64":{"position":[[135,7]]},"90":{"position":[[131,7]]}},"keywords":{}}],["preserv",{"_index":1483,"title":{},"content":{"30":{"position":[[9597,8]]}},"keywords":{}}],["press",{"_index":2291,"title":{},"content":{"54":{"position":[[204,5]]}},"keywords":{}}],["prestart",{"_index":4138,"title":{},"content":{"125":{"position":[[6427,8]]}},"keywords":{}}],["presum",{"_index":2733,"title":{},"content":{"76":{"position":[[2288,11]]},"91":{"position":[[5017,10]]},"93":{"position":[[855,10]]},"111":{"position":[[837,10]]}},"keywords":{}}],["pretenti",{"_index":3860,"title":{},"content":{"120":{"position":[[738,11]]}},"keywords":{}}],["pretti",{"_index":1119,"title":{"100":{"position":[[19,6]]}},"content":{"24":{"position":[[2965,6]]},"51":{"position":[[2136,6]]},"53":{"position":[[1882,6]]},"55":{"position":[[5,6]]},"63":{"position":[[47,6]]},"98":{"position":[[128,6],[462,6]]},"106":{"position":[[93,6]]},"110":{"position":[[37,6],[502,6]]},"112":{"position":[[973,6]]},"116":{"position":[[2511,6]]},"121":{"position":[[1493,6]]},"125":{"position":[[1768,6],[5000,6],[9187,6]]},"128":{"position":[[1670,6]]},"134":{"position":[[402,6]]},"161":{"position":[[1574,6]]}},"keywords":{}}],["prevail",{"_index":2939,"title":{},"content":{"88":{"position":[[3598,10]]}},"keywords":{}}],["prevent",{"_index":3794,"title":{},"content":{"115":{"position":[[3034,10]]},"125":{"position":[[3520,7]]}},"keywords":{}}],["previou",{"_index":1019,"title":{},"content":{"24":{"position":[[283,8]]},"30":{"position":[[620,8],[4227,8],[4406,8],[5760,8],[7214,8]]},"34":{"position":[[858,8]]},"49":{"position":[[229,8]]},"115":{"position":[[2471,8]]},"116":{"position":[[2329,8]]},"117":{"position":[[197,8]]},"183":{"position":[[215,8]]},"186":{"position":[[580,8]]}},"keywords":{}}],["previous",{"_index":4545,"title":{},"content":{"153":{"position":[[481,10]]},"161":{"position":[[660,11]]},"166":{"position":[[91,10]]},"169":{"position":[[74,10]]},"183":{"position":[[648,10]]}},"keywords":{}}],["price",{"_index":306,"title":{},"content":{"6":{"position":[[13,5],[1098,5]]},"12":{"position":[[88,7]]},"13":{"position":[[74,5],[766,5],[792,5]]},"14":{"position":[[17,7],[215,6],[638,6],[1623,5],[1649,5],[1765,5]]},"15":{"position":[[1010,5],[1036,5],[1155,5]]},"32":{"position":[[496,5],[548,5],[1101,5],[1259,5],[2315,6]]},"33":{"position":[[142,5],[193,5],[327,6],[434,5],[496,5],[631,5],[665,6]]},"34":{"position":[[426,5],[520,5],[566,5],[651,5]]},"88":{"position":[[1671,5],[1978,5],[3134,5],[3513,5]]},"90":{"position":[[4263,5],[4779,5],[4834,5],[4916,5],[5087,5],[5180,5],[5264,5]]},"91":{"position":[[318,5],[2602,5]]},"92":{"position":[[414,5]]},"93":{"position":[[2027,5],[3753,5],[5536,6],[5589,6]]},"163":{"position":[[228,7]]}},"keywords":{}}],["price_athena",{"_index":563,"title":{},"content":{"13":{"position":[[601,12]]}},"keywords":{}}],["price_athena(s0",{"_index":579,"title":{},"content":{"13":{"position":[[1170,16]]}},"keywords":{}}],["price_data.hdf",{"_index":3128,"title":{},"content":{"91":{"position":[[2695,14]]},"92":{"position":[[507,14]]}},"keywords":{}}],["price_dict",{"_index":3276,"title":{},"content":{"93":{"position":[[4655,10]]}},"keywords":{}}],["price_dict.item",{"_index":3295,"title":{},"content":{"93":{"position":[[5546,19]]}},"keywords":{}}],["price_dict[tick",{"_index":3286,"title":{},"content":{"93":{"position":[[4931,18],[5346,18]]}},"keywords":{}}],["price_funct",{"_index":578,"title":{},"content":{"13":{"position":[[1133,14]]},"14":{"position":[[2167,14]]},"15":{"position":[[1835,14]]}},"keywords":{}}],["price_function(motion[i",{"_index":583,"title":{},"content":{"13":{"position":[[1366,25]]},"14":{"position":[[2438,25]]},"15":{"position":[[2110,25]]}},"keywords":{}}],["price_phoenix_no_memori",{"_index":646,"title":{},"content":{"14":{"position":[[1431,23]]}},"keywords":{}}],["price_phoenix_no_memory(s0",{"_index":650,"title":{},"content":{"14":{"position":[[2204,27]]}},"keywords":{}}],["price_phoenix_with_memori",{"_index":677,"title":{},"content":{"15":{"position":[[800,25]]}},"keywords":{}}],["price_phoenix_with_memory(s0",{"_index":682,"title":{},"content":{"15":{"position":[[1872,29]]}},"keywords":{}}],["prices_stor",{"_index":3293,"title":{},"content":{"93":{"position":[[5479,12]]}},"keywords":{}}],["prices_store[tick",{"_index":3296,"title":{},"content":{"93":{"position":[[5566,20]]}},"keywords":{}}],["primit",{"_index":4222,"title":{"126":{"position":[[0,10]]},"127":{"position":[[9,10]]},"128":{"position":[[22,10]]},"129":{"position":[[5,9]]}},"content":{"127":{"position":[[31,9],[274,11],[422,10],[1011,9]]},"128":{"position":[[1720,11]]},"129":{"position":[[120,9],[199,10],[2071,10]]},"130":{"position":[[109,10],[150,10]]},"157":{"position":[[568,11]]},"196":{"position":[[179,10],[224,10]]}},"keywords":{}}],["principl",{"_index":554,"title":{},"content":{"13":{"position":[[390,9],[461,9]]},"14":{"position":[[514,9]]},"38":{"position":[[48,10]]},"45":{"position":[[1082,9]]},"68":{"position":[[277,10]]},"97":{"position":[[1333,9],[3398,9]]},"117":{"position":[[831,9]]},"122":{"position":[[465,9]]},"172":{"position":[[796,9]]},"188":{"position":[[805,9]]}},"keywords":{}}],["print",{"_index":1090,"title":{},"content":{"24":{"position":[[2385,7]]},"25":{"position":[[2108,7]]},"53":{"position":[[174,7]]},"61":{"position":[[1853,5]]},"179":{"position":[[609,6],[689,6],[999,6],[1112,6]]}},"keywords":{}}],["print(",{"_index":1494,"title":{},"content":{"30":{"position":[[9908,8]]}},"keywords":{}}],["print("articl",{"_index":1087,"title":{},"content":{"24":{"position":[[2305,20]]},"25":{"position":[[2029,20]]}},"keywords":{}}],["print("end",{"_index":1495,"title":{},"content":{"30":{"position":[[9951,15]]}},"keywords":{}}],["print("four",{"_index":2509,"title":{},"content":{"65":{"position":[[935,16]]}},"keywords":{}}],["print("heartbeat",{"_index":2436,"title":{},"content":{"62":{"position":[[1479,22]]},"64":{"position":[[1741,22]]}},"keywords":{}}],["print("look",{"_index":3219,"title":{},"content":{"93":{"position":[[2288,20]]}},"keywords":{}}],["print("na",{"_index":1943,"title":{},"content":{"44":{"position":[[1501,17]]}},"keywords":{}}],["print("predict",{"_index":1091,"title":{},"content":{"24":{"position":[[2393,22]]},"25":{"position":[[2116,22]]}},"keywords":{}}],["print("quart",{"_index":2524,"title":{},"content":{"65":{"position":[[1897,20]]}},"keywords":{}}],["print("remain",{"_index":2492,"title":{},"content":{"64":{"position":[[1812,21]]},"65":{"position":[[1012,21],[1970,21]]}},"keywords":{}}],["print("retriev",{"_index":1486,"title":{},"content":{"30":{"position":[[9688,22]]}},"keywords":{}}],["print("run",{"_index":2036,"title":{},"content":{"46":{"position":[[609,19]]}},"keywords":{}}],["print("satisfi",{"_index":1938,"title":{},"content":{"44":{"position":[[1356,21]]}},"keywords":{}}],["print("simul",{"_index":2758,"title":{},"content":{"78":{"position":[[344,21]]}},"keywords":{}}],["print("{}".format(list_2[index_dt",{"_index":1067,"title":{},"content":{"24":{"position":[[1533,47]]},"25":{"position":[[1253,47]]}},"keywords":{}}],["print('iter",{"_index":2735,"title":{},"content":{"76":{"position":[[2502,17]]}},"keywords":{}}],["print(pd.dataframe.from_dict(count_dict",{"_index":1089,"title":{},"content":{"24":{"position":[[2343,41]]},"25":{"position":[[2066,41]]}},"keywords":{}}],["print(pd.dataframe.from_dict(prediction_dict",{"_index":1093,"title":{},"content":{"24":{"position":[[2433,46]]},"25":{"position":[[2156,46]]}},"keywords":{}}],["print(self.x",{"_index":4306,"title":{},"content":{"129":{"position":[[1962,13]]}},"keywords":{}}],["print(simulate_tweet",{"_index":2197,"title":{},"content":{"53":{"position":[[150,23]]}},"keywords":{}}],["printf("mean",{"_index":590,"title":{},"content":{"13":{"position":[[1551,18]]},"14":{"position":[[2634,18]]},"15":{"position":[[2308,18]]}},"keywords":{}}],["printf("pres",{"_index":601,"title":{},"content":{"13":{"position":[[1829,21]]},"14":{"position":[[2912,21]]},"15":{"position":[[2586,21]]}},"keywords":{}}],["printf("tim",{"_index":537,"title":{},"content":{"12":{"position":[[588,18]]}},"keywords":{}}],["println",{"_index":3351,"title":{},"content":{"96":{"position":[[1968,8]]}},"keywords":{}}],["println!("cel",{"_index":5074,"title":{},"content":{"179":{"position":[[623,20],[703,20],[1021,20],[1122,20]]}},"keywords":{}}],["println!("const",{"_index":5126,"title":{},"content":{"184":{"position":[[663,20]]}},"keywords":{}}],["println!("initi",{"_index":5084,"title":{},"content":{"179":{"position":[[1561,27]]}},"keywords":{}}],["println!("initializing..."",{"_index":5083,"title":{},"content":{"179":{"position":[[1360,39]]},"186":{"position":[[459,39]]}},"keywords":{}}],["println!("stat",{"_index":5123,"title":{},"content":{"184":{"position":[[323,21]]}},"keywords":{}}],["println("actu",{"_index":504,"title":{},"content":{"10":{"position":[[484,20]]}},"keywords":{}}],["println("day",{"_index":1652,"title":{},"content":{"34":{"position":[[2908,18]]}},"keywords":{}}],["println("max",{"_index":1650,"title":{},"content":{"34":{"position":[[2857,17]]}},"keywords":{}}],["println("mean",{"_index":595,"title":{},"content":{"13":{"position":[[1690,18]]},"14":{"position":[[2773,18]]},"15":{"position":[[2447,18]]}},"keywords":{}}],["println("profit",{"_index":1654,"title":{},"content":{"34":{"position":[[2967,21]]}},"keywords":{}}],["prior",{"_index":669,"title":{},"content":{"15":{"position":[[186,5]]},"18":{"position":[[62,5]]},"30":{"position":[[7552,5]]},"43":{"position":[[128,5]]},"91":{"position":[[124,5],[5379,5]]},"93":{"position":[[109,5]]}},"keywords":{}}],["prior_clos",{"_index":1032,"title":{},"content":{"24":{"position":[[617,11],[714,12],[729,11]]}},"keywords":{}}],["priorit",{"_index":4628,"title":{},"content":{"159":{"position":[[310,10]]}},"keywords":{}}],["prioriti",{"_index":3892,"title":{},"content":{"121":{"position":[[1159,8]]}},"keywords":{}}],["privaci",{"_index":2480,"title":{},"content":{"64":{"position":[[1374,7]]}},"keywords":{}}],["privat",{"_index":4816,"title":{},"content":{"164":{"position":[[1339,7]]}},"keywords":{}}],["prob",{"_index":1421,"title":{},"content":{"30":{"position":[[6339,5],[6358,4]]},"51":{"position":[[2461,7],[3632,7],[3679,6],[3965,5],[4071,6],[4154,5],[4222,6]]}},"keywords":{}}],["probabl",{"_index":1380,"title":{},"content":{"30":{"position":[[2851,8]]},"51":{"position":[[776,11],[947,8],[3242,12],[3339,11],[3363,11],[3451,13]]},"74":{"position":[[65,11],[794,11],[878,11]]},"75":{"position":[[848,11],[1026,11]]},"76":{"position":[[235,13],[522,13],[1085,11]]},"91":{"position":[[365,8]]},"121":{"position":[[2537,8]]},"125":{"position":[[396,8]]},"150":{"position":[[424,8]]},"174":{"position":[[940,8]]},"188":{"position":[[4099,8]]}},"keywords":{}}],["problem",{"_index":81,"title":{},"content":{"2":{"position":[[101,8],[495,7]]},"3":{"position":[[430,8]]},"4":{"position":[[492,8],[576,7]]},"45":{"position":[[3495,7]]},"73":{"position":[[687,9]]},"74":{"position":[[178,8]]},"85":{"position":[[172,7]]},"86":{"position":[[98,8]]},"125":{"position":[[905,8],[1145,8]]},"143":{"position":[[41,9]]},"150":{"position":[[286,8]]},"165":{"position":[[152,8],[583,7],[1303,8]]},"172":{"position":[[1978,7]]},"190":{"position":[[880,8]]}},"keywords":{}}],["proce",{"_index":2093,"title":{},"content":{"51":{"position":[[924,7]]}},"keywords":{}}],["procedur",{"_index":4445,"title":{"144":{"position":[[8,10]]}},"content":{},"keywords":{}}],["proceed",{"_index":2106,"title":{},"content":{"51":{"position":[[1372,10],[1437,10]]}},"keywords":{}}],["process",{"_index":1854,"title":{"75":{"position":[[4,7]]},"111":{"position":[[29,8]]}},"content":{"41":{"position":[[521,8]]},"45":{"position":[[1542,8]]},"51":{"position":[[2801,7]]},"61":{"position":[[1415,11]]},"73":{"position":[[252,8]]},"82":{"position":[[1057,7]]},"93":{"position":[[1041,10]]},"100":{"position":[[250,10]]},"102":{"position":[[131,7]]},"103":{"position":[[1285,7]]},"104":{"position":[[713,10]]},"106":{"position":[[1161,10]]},"111":{"position":[[44,7]]},"113":{"position":[[745,7]]},"122":{"position":[[1426,7]]},"125":{"position":[[4096,8]]},"164":{"position":[[738,7]]},"165":{"position":[[965,7]]},"173":{"position":[[375,7],[551,9],[679,7],[740,9],[2067,7]]},"176":{"position":[[440,8]]},"188":{"position":[[245,11],[2668,10]]}},"keywords":{}}],["processbecom",{"_index":4128,"title":{},"content":{"125":{"position":[[5723,14]]}},"keywords":{}}],["processor",{"_index":128,"title":{},"content":{"2":{"position":[[814,9]]},"163":{"position":[[44,10]]},"173":{"position":[[1747,9]]},"174":{"position":[[61,10]]}},"keywords":{}}],["prod(forward_structur",{"_index":599,"title":{},"content":{"13":{"position":[[1797,24]]},"14":{"position":[[2879,24]]},"15":{"position":[[2553,24]]}},"keywords":{}}],["prod_{i=1}^n",{"_index":2646,"title":{},"content":{"74":{"position":[[1105,13]]}},"keywords":{}}],["produc",{"_index":1674,"title":{},"content":{"35":{"position":[[416,8]]}},"keywords":{}}],["product",{"_index":246,"title":{"150":{"position":[[22,10]]}},"content":{"4":{"position":[[605,10]]},"12":{"position":[[116,9]]},"14":{"position":[[83,11],[235,7]]},"74":{"position":[[1379,7]]},"125":{"position":[[10815,10]]},"143":{"position":[[296,10]]},"160":{"position":[[896,12]]},"161":{"position":[[137,11]]},"176":{"position":[[1367,10]]}},"keywords":{}}],["profit",{"_index":1590,"title":{"37":{"position":[[0,13]]}},"content":{"33":{"position":[[1319,10]]},"34":{"position":[[304,7],[1859,6],[1874,10],[2041,11],[2350,10],[2623,6],[2686,7],[2734,7],[3232,7],[3281,7],[3303,6],[3404,7],[3464,7],[3694,6],[3795,7],[3856,7],[3980,6]]},"35":{"position":[[439,6]]},"38":{"position":[[75,7],[297,6],[501,13]]},"39":{"position":[[548,13],[1089,10],[1256,11],[1570,10],[1883,11],[2071,6],[2135,6]]},"40":{"position":[[817,7],[841,13],[973,13],[1425,13],[2219,13],[2393,13],[3331,14],[3442,10]]},"41":{"position":[[156,7]]}},"keywords":{}}],["profit"",{"_index":1655,"title":{},"content":{"34":{"position":[[2989,14]]}},"keywords":{}}],["profitability"",{"_index":1794,"title":{},"content":{"40":{"position":[[362,20],[1896,20],[2839,20]]}},"keywords":{}}],["profitability(x[1",{"_index":1770,"title":{},"content":{"39":{"position":[[2903,19]]}},"keywords":{}}],["program",{"_index":2283,"title":{},"content":{"53":{"position":[[1845,7]]},"86":{"position":[[1125,7]]},"97":{"position":[[80,8],[490,7]]},"112":{"position":[[418,11]]},"117":{"position":[[2146,9]]},"125":{"position":[[998,11]]},"127":{"position":[[521,7]]},"128":{"position":[[1070,7]]},"134":{"position":[[200,7]]},"135":{"position":[[176,7]]},"136":{"position":[[153,8]]},"137":{"position":[[144,7]]},"139":{"position":[[761,8]]},"143":{"position":[[178,7]]},"153":{"position":[[467,8],[966,7]]},"160":{"position":[[554,7],[1167,8],[1854,7],[2262,8],[3161,7],[3270,8]]},"163":{"position":[[565,7]]},"172":{"position":[[1858,7],[1993,7],[2493,11]]},"173":{"position":[[141,8],[465,9],[1242,8],[1920,7]]},"176":{"position":[[637,7]]},"178":{"position":[[53,7],[390,9]]},"180":{"position":[[87,7],[154,7]]},"182":{"position":[[151,8],[539,7]]},"188":{"position":[[25,11]]},"195":{"position":[[157,8],[806,7]]}},"keywords":{}}],["programm",{"_index":3442,"title":{},"content":{"98":{"position":[[437,11]]},"120":{"position":[[879,11]]},"121":{"position":[[53,11],[82,12]]},"160":{"position":[[103,11],[274,11]]}},"keywords":{}}],["progress",{"_index":1394,"title":{},"content":{"30":{"position":[[4104,11]]},"123":{"position":[[1100,9]]},"125":{"position":[[11095,9]]}},"keywords":{}}],["progressbar",{"_index":3105,"title":{},"content":{"91":{"position":[[1892,11],[1911,11]]},"93":{"position":[[1402,11],[3947,11],[3966,11]]}},"keywords":{}}],["progressbar()(ticker_d",{"_index":3146,"title":{},"content":{"91":{"position":[[3445,28]]}},"keywords":{}}],["progressbar()(tickers[0:1500",{"_index":3278,"title":{},"content":{"93":{"position":[[4706,31]]}},"keywords":{}}],["progressbar()(tickers[1500",{"_index":3292,"title":{},"content":{"93":{"position":[[5122,30]]}},"keywords":{}}],["progressbar.progressbar(term_width=80",{"_index":3266,"title":{},"content":{"93":{"position":[[3507,38]]}},"keywords":{}}],["project",{"_index":10,"title":{"107":{"position":[[20,7]]},"109":{"position":[[36,8]]}},"content":{"1":{"position":[[85,7],[226,8]]},"3":{"position":[[192,7]]},"57":{"position":[[307,8],[355,8]]},"58":{"position":[[899,7]]},"100":{"position":[[87,7],[334,8],[390,7]]},"109":{"position":[[73,8],[657,8]]},"110":{"position":[[173,8]]},"111":{"position":[[818,8]]},"112":{"position":[[86,7],[666,7]]},"113":{"position":[[40,7],[2453,8]]},"118":{"position":[[182,9]]},"125":{"position":[[7389,8],[7757,7],[8204,8],[11628,7]]},"161":{"position":[[182,9]]},"163":{"position":[[290,7]]},"190":{"position":[[124,8]]}},"keywords":{}}],["project"",{"_index":4357,"title":{},"content":{"132":{"position":[[870,13]]}},"keywords":{}}],["prologu",{"_index":4760,"title":{"163":{"position":[[0,9]]}},"content":{},"keywords":{}}],["promis",{"_index":2551,"title":{},"content":{"66":{"position":[[841,7]]},"125":{"position":[[4256,7],[4354,7]]}},"keywords":{}}],["proof",{"_index":4195,"title":{},"content":{"125":{"position":[[10195,5],[10444,6]]}},"keywords":{}}],["proper",{"_index":448,"title":{},"content":{"8":{"position":[[144,6]]}},"keywords":{}}],["properli",{"_index":3899,"title":{},"content":{"121":{"position":[[1397,8]]},"133":{"position":[[108,8]]}},"keywords":{}}],["properti",{"_index":667,"title":{},"content":{"15":{"position":[[125,9]]},"156":{"position":[[185,8]]},"185":{"position":[[519,9]]}},"keywords":{}}],["proport",{"_index":5030,"title":{},"content":{"175":{"position":[[1316,12]]}},"keywords":{}}],["proportion",{"_index":4896,"title":{},"content":{"170":{"position":[[299,15]]}},"keywords":{}}],["propos",{"_index":2666,"title":{},"content":{"75":{"position":[[659,8]]},"76":{"position":[[73,8],[876,8]]},"139":{"position":[[920,7]]}},"keywords":{}}],["protect",{"_index":555,"title":{},"content":{"13":{"position":[[400,10],[422,10],[945,10]]},"14":{"position":[[453,10],[475,10],[1300,10],[1963,10]]},"15":{"position":[[1631,10]]},"38":{"position":[[569,7]]},"146":{"position":[[483,10]]}},"keywords":{}}],["protection_barri",{"_index":560,"title":{},"content":{"13":{"position":[[549,18],[667,19],[981,18],[1214,19]]},"14":{"position":[[1379,18],[1524,19],[1999,18],[2275,19]]},"15":{"position":[[748,18],[895,19],[1667,18],[1945,19]]}},"keywords":{}}],["proto",{"_index":3679,"title":{"109":{"position":[[25,5]]},"164":{"position":[[6,6]]}},"content":{"109":{"position":[[541,5],[651,5]]},"111":{"position":[[76,5],[612,5]]},"112":{"position":[[1244,5]]},"113":{"position":[[24,6],[133,5],[773,5],[2558,5]]},"116":{"position":[[3247,5]]},"117":{"position":[[55,5],[695,5],[2101,5]]},"164":{"position":[[62,5],[306,5],[806,5],[1027,5],[1198,5],[1481,5]]},"165":{"position":[[170,6],[398,6],[1130,5]]},"166":{"position":[[332,5]]},"168":{"position":[[200,5],[246,5]]},"169":{"position":[[314,5],[360,5]]}},"keywords":{}}],["proto'",{"_index":3663,"title":{},"content":{"108":{"position":[[277,7]]}},"keywords":{}}],["proto'sbenchmarksto",{"_index":4808,"title":{},"content":{"164":{"position":[[635,19]]}},"keywords":{}}],["protocol",{"_index":3707,"title":{},"content":{"111":{"position":[[515,8]]},"125":{"position":[[4885,8],[4905,8]]},"175":{"position":[[552,9],[579,8]]}},"keywords":{}}],["proud",{"_index":4080,"title":{},"content":{"125":{"position":[[3358,5]]}},"keywords":{}}],["prove",{"_index":2356,"title":{"68":{"position":[[0,7]]}},"content":{"61":{"position":[[626,5]]},"125":{"position":[[3288,5],[9261,5]]},"155":{"position":[[1225,5]]},"160":{"position":[[4179,5]]},"183":{"position":[[857,5]]},"193":{"position":[[2200,5]]}},"keywords":{}}],["proven",{"_index":3802,"title":{},"content":{"116":{"position":[[634,6]]}},"keywords":{}}],["provid",{"_index":2365,"title":{},"content":{"61":{"position":[[1170,9]]},"97":{"position":[[780,8]]},"157":{"position":[[179,8],[421,8]]},"179":{"position":[[315,8]]},"183":{"position":[[74,8]]},"190":{"position":[[386,8],[911,7]]},"195":{"position":[[438,8]]}},"keywords":{}}],["providesextens",{"_index":5260,"title":{},"content":{"190":{"position":[[352,17]]}},"keywords":{}}],["pt",{"_index":1895,"title":{"44":{"position":[[25,3]]},"45":{"position":[[25,3]]}},"content":{},"keywords":{}}],["ptr",{"_index":4262,"title":{},"content":{"128":{"position":[[529,3],[642,3],[876,3],[1594,3]]},"152":{"position":[[1507,4]]},"156":{"position":[[1590,4]]},"183":{"position":[[393,3],[539,3]]}},"keywords":{}}],["pub",{"_index":3731,"title":{},"content":{"113":{"position":[[440,3]]},"129":{"position":[[414,3],[1526,3]]},"136":{"position":[[263,3]]},"152":{"position":[[466,3]]},"153":{"position":[[743,3]]},"155":{"position":[[1339,3],[1402,3],[1463,3],[1526,3]]},"156":{"position":[[623,3]]},"163":{"position":[[1737,3]]},"180":{"position":[[418,3]]},"181":{"position":[[98,3],[214,3]]},"183":{"position":[[323,3],[463,3]]},"192":{"position":[[184,3]]},"193":{"position":[[1738,3],[2693,3],[3173,3],[3227,3],[3528,3]]},"194":{"position":[[299,3]]},"196":{"position":[[1141,3],[1523,3],[1734,3]]},"197":{"position":[[928,3],[1147,3]]},"199":{"position":[[1231,3],[1368,3],[1524,3]]}},"keywords":{}}],["public",{"_index":4229,"title":{},"content":{"127":{"position":[[594,6],[1244,6]]},"199":{"position":[[102,6],[262,6]]}},"keywords":{}}],["publicli",{"_index":5042,"title":{},"content":{"176":{"position":[[218,8]]}},"keywords":{}}],["publish",{"_index":3874,"title":{},"content":{"121":{"position":[[122,7]]}},"keywords":{}}],["pubugn9",{"_index":1326,"title":{},"content":{"30":{"position":[[178,7]]}},"keywords":{}}],["pull",{"_index":2168,"title":{"52":{"position":[[0,7]]}},"content":{"59":{"position":[[43,4]]},"62":{"position":[[339,4]]},"161":{"position":[[1392,4]]}},"keywords":{}}],["pun",{"_index":3570,"title":{},"content":{"104":{"position":[[1642,4]]},"160":{"position":[[3640,4]]}},"keywords":{}}],["purchas",{"_index":1537,"title":{},"content":{"32":{"position":[[1143,9]]},"33":{"position":[[1278,9]]}},"keywords":{}}],["purchase_histori",{"_index":1606,"title":{},"content":{"34":{"position":[[1104,17],[1448,17]]},"39":{"position":[[635,17],[677,17],[824,17],[900,17],[920,16]]}},"keywords":{}}],["purchase_history*current_clos",{"_index":1617,"title":{},"content":{"34":{"position":[[1288,30]]}},"keywords":{}}],["pure",{"_index":2448,"title":{},"content":{"63":{"position":[[135,6]]},"97":{"position":[[2277,4]]},"161":{"position":[[277,6]]},"190":{"position":[[736,4]]}},"keywords":{}}],["purpos",{"_index":2481,"title":{},"content":{"64":{"position":[[1382,8]]},"125":{"position":[[5036,7],[6238,7],[9617,7]]}},"keywords":{}}],["push",{"_index":4255,"title":{},"content":{"128":{"position":[[447,4],[759,4],[1281,4]]},"160":{"position":[[4072,4]]},"176":{"position":[[981,7]]}},"keywords":{}}],["push_vec(&v",{"_index":4455,"title":{},"content":{"144":{"position":[[358,17],[407,17]]}},"keywords":{}}],["push_vec(v",{"_index":4451,"title":{},"content":{"144":{"position":[[177,11]]}},"keywords":{}}],["put",{"_index":45,"title":{"116":{"position":[[11,3]]}},"content":{"1":{"position":[[527,3]]},"13":{"position":[[1020,3],[1081,4]]},"14":{"position":[[2054,3],[2115,4]]},"15":{"position":[[1722,3],[1783,4]]},"52":{"position":[[523,3]]},"64":{"position":[[1396,3]]},"97":{"position":[[547,3]]},"102":{"position":[[172,3]]},"109":{"position":[[196,3]]},"110":{"position":[[393,3]]},"111":{"position":[[263,3]]},"113":{"position":[[162,3],[213,3]]},"125":{"position":[[932,3]]},"130":{"position":[[348,3]]},"136":{"position":[[797,3]]},"160":{"position":[[3066,3]]},"161":{"position":[[618,3],[759,3],[1109,3]]},"164":{"position":[[1443,3]]},"172":{"position":[[900,3]]},"188":{"position":[[1,3]]},"193":{"position":[[718,3]]}},"keywords":{}}],["pv",{"_index":598,"title":{},"content":{"13":{"position":[[1773,2],[1905,3]]},"14":{"position":[[2856,2],[2986,3]]},"15":{"position":[[2530,2],[2657,3]]}},"keywords":{}}],["pyeval_savethread",{"_index":5206,"title":{},"content":{"188":{"position":[[3666,18]]}},"keywords":{}}],["pyo3",{"_index":3915,"title":{},"content":{"121":{"position":[[2080,5]]}},"keywords":{}}],["pypi",{"_index":4927,"title":{},"content":{"172":{"position":[[1815,5]]}},"keywords":{}}],["python",{"_index":1712,"title":{"129":{"position":[[20,8]]}},"content":{"39":{"position":[[296,6]]},"95":{"position":[[382,7]]},"96":{"position":[[41,6],[112,6],[424,6],[868,6]]},"98":{"position":[[600,7]]},"103":{"position":[[115,6]]},"120":{"position":[[81,6],[157,6]]},"121":{"position":[[75,6],[130,6],[234,7],[1272,6],[1615,6]]},"122":{"position":[[255,7]]},"129":{"position":[[1763,6],[2035,6],[2707,6]]},"130":{"position":[[288,6]]},"132":{"position":[[115,6],[131,7],[220,7]]},"160":{"position":[[1036,8]]},"172":{"position":[[111,7],[1600,7]]},"188":{"position":[[68,7],[168,6],[482,6],[664,6],[3652,6]]},"189":{"position":[[88,6],[134,6]]},"190":{"position":[[299,6],[741,7],[1052,7]]},"196":{"position":[[325,6]]}},"keywords":{}}],["python'",{"_index":3908,"title":{},"content":{"121":{"position":[[1704,8]]}},"keywords":{}}],["python,java",{"_index":5045,"title":{},"content":{"176":{"position":[[595,14]]}},"keywords":{}}],["python."",{"_index":5226,"title":{},"content":{"189":{"position":[[40,13]]}},"keywords":{}}],["q",{"_index":354,"title":{},"content":{"6":{"position":[[791,1],[927,1]]},"11":{"position":[[438,2]]},"12":{"position":[[396,2]]},"144":{"position":[[142,2]]},"145":{"position":[[118,2]]},"146":{"position":[[146,2]]}},"keywords":{}}],["q_format",{"_index":2854,"title":{},"content":{"88":{"position":[[744,8]]},"93":{"position":[[4159,8]]}},"keywords":{}}],["qadapt",{"_index":4411,"title":{"138":{"position":[[0,6]]}},"content":{"143":{"position":[[22,6],[121,6],[377,6],[531,6]]},"144":{"position":[[145,6],[154,7]]},"145":{"position":[[121,6],[130,7]]},"146":{"position":[[149,6],[158,7]]},"147":{"position":[[34,6]]},"148":{"position":[[157,6],[492,6]]}},"keywords":{}}],["qadapt::assert_no_alloc",{"_index":4457,"title":{},"content":{"145":{"position":[[46,24]]}},"keywords":{}}],["qadapt::enter_protect",{"_index":4464,"title":{},"content":{"146":{"position":[[46,24]]}},"keywords":{}}],["qadapt::exit_protect",{"_index":4465,"title":{},"content":{"146":{"position":[[75,23]]}},"keywords":{}}],["qadapt::no_alloc",{"_index":4448,"title":{},"content":{"144":{"position":[[77,17]]}},"keywords":{}}],["qadapt::qadapt",{"_index":4449,"title":{},"content":{"144":{"position":[[99,15]]},"145":{"position":[[75,15]]},"146":{"position":[[103,15]]}},"keywords":{}}],["qget",{"_index":1719,"title":{},"content":{"39":{"position":[[511,4]]}},"keywords":{}}],["qget(nam",{"_index":1744,"title":{},"content":{"39":{"position":[[2216,10]]}},"keywords":{}}],["qr−q",{"_index":332,"title":{},"content":{"6":{"position":[[448,4]]}},"keywords":{}}],["qualifi",{"_index":3139,"title":{},"content":{"91":{"position":[[3165,7]]},"92":{"position":[[977,7]]}},"keywords":{}}],["qualiti",{"_index":3439,"title":{},"content":{"98":{"position":[[389,8]]},"101":{"position":[[1115,8]]},"102":{"position":[[1220,8]]},"103":{"position":[[2009,7]]},"105":{"position":[[344,8]]},"106":{"position":[[401,8]]},"125":{"position":[[7010,7]]},"175":{"position":[[418,7]]}},"keywords":{}}],["quality"",{"_index":4079,"title":{},"content":{"125":{"position":[[3214,13]]}},"keywords":{}}],["quandl",{"_index":706,"title":{},"content":{"17":{"position":[[96,6]]},"23":{"position":[[189,6]]},"34":{"position":[[1017,6]]},"39":{"position":[[490,6]]},"88":{"position":[[487,6],[603,6]]},"93":{"position":[[3935,6],[4018,6],[4599,6]]}},"keywords":{}}],["quandl.get("goog/amex_iwm"",{"_index":1010,"title":{},"content":{"23":{"position":[[505,37]]}},"keywords":{}}],["quandl.get("goog/ams_dia"",{"_index":1008,"title":{},"content":{"23":{"position":[[438,36]]}},"keywords":{}}],["quandl.get("goog/epa_qqq"",{"_index":1011,"title":{},"content":{"23":{"position":[[575,36]]}},"keywords":{}}],["quandl.get("goog/nyse_spy"",{"_index":1005,"title":{},"content":{"23":{"position":[[370,37]]}},"keywords":{}}],["quandl.get('yahoo",{"_index":2856,"title":{},"content":{"88":{"position":[[780,19]]},"93":{"position":[[4195,19]]}},"keywords":{}}],["quandl.get('yahoo/{}'.format(tick",{"_index":722,"title":{},"content":{"17":{"position":[[266,36]]}},"keywords":{}}],["quandl.get(market_tick",{"_index":724,"title":{},"content":{"17":{"position":[[344,25]]}},"keywords":{}}],["quandl.notfounderror",{"_index":3289,"title":{},"content":{"93":{"position":[[5011,21],[5426,21]]}},"keywords":{}}],["quandl_key",{"_index":2842,"title":{},"content":{"88":{"position":[[271,10]]},"93":{"position":[[3820,10]]}},"keywords":{}}],["quandlget(nam",{"_index":1625,"title":{},"content":{"34":{"position":[[1655,15]]}},"keywords":{}}],["quantiti",{"_index":1559,"title":{},"content":{"32":{"position":[[2219,8]]},"49":{"position":[[465,8]]}},"keywords":{}}],["quarter",{"_index":2457,"title":{},"content":{"64":{"position":[[444,9],[710,9]]},"65":{"position":[[351,7],[587,8],[1373,8],[1553,8],[2051,8]]}},"keywords":{}}],["quarterhrdhr_dhrd",{"_index":2463,"title":{},"content":{"64":{"position":[[643,19]]},"65":{"position":[[529,19]]}},"keywords":{}}],["quarterli",{"_index":462,"title":{},"content":{"9":{"position":[[220,9],[311,9],[519,9]]}},"keywords":{}}],["quarterly_count",{"_index":2466,"title":{},"content":{"64":{"position":[[777,15],[978,15]]},"65":{"position":[[649,15]]}},"keywords":{}}],["quarters_left",{"_index":2522,"title":{},"content":{"65":{"position":[[1775,13],[1862,13]]}},"keywords":{}}],["queen",{"_index":2242,"title":{},"content":{"53":{"position":[[1010,5]]}},"keywords":{}}],["quest",{"_index":3942,"title":{},"content":{"122":{"position":[[546,5]]}},"keywords":{}}],["question",{"_index":19,"title":{"89":{"position":[[16,9]]}},"content":{"1":{"position":[[187,8]]},"32":{"position":[[345,8]]},"44":{"position":[[1190,8]]},"66":{"position":[[726,8]]},"68":{"position":[[10,8]]},"86":{"position":[[16,9]]},"89":{"position":[[374,8],[479,8]]},"93":{"position":[[960,9]]},"125":{"position":[[1557,8]]},"159":{"position":[[142,10]]},"176":{"position":[[751,10]]}},"keywords":{}}],["quick",{"_index":55,"title":{},"content":{"1":{"position":[[624,5]]},"51":{"position":[[3278,5]]},"90":{"position":[[4709,5]]},"108":{"position":[[322,5]]},"121":{"position":[[2465,5]]},"139":{"position":[[938,5]]},"161":{"position":[[473,5]]}},"keywords":{}}],["quickli",{"_index":1618,"title":{},"content":{"34":{"position":[[1398,8]]},"66":{"position":[[658,7]]},"73":{"position":[[653,7]]},"76":{"position":[[705,7]]},"83":{"position":[[215,8]]},"86":{"position":[[524,7],[543,7],[873,7]]},"110":{"position":[[570,7]]},"122":{"position":[[594,7]]},"125":{"position":[[2491,8],[3696,7]]},"132":{"position":[[798,8]]}},"keywords":{}}],["quirk",{"_index":3905,"title":{},"content":{"121":{"position":[[1622,6]]}},"keywords":{}}],["quirki",{"_index":4336,"title":{},"content":{"130":{"position":[[431,6]]}},"keywords":{}}],["quit",{"_index":1184,"title":{},"content":{"26":{"position":[[837,5]]},"121":{"position":[[1437,5]]}},"keywords":{}}],["quiz",{"_index":2233,"title":{},"content":{"53":{"position":[[885,4]]}},"keywords":{}}],["quot",{"_index":1088,"title":{},"content":{"24":{"position":[[2335,7]]},"96":{"position":[[1201,6],[1739,7],[2285,9]]},"163":{"position":[[221,6]]},"179":{"position":[[644,11],[724,11],[1042,11],[1143,11]]},"184":{"position":[[355,11],[704,11]]}},"keywords":{}}],["quot;$app_dir"",{"_index":4117,"title":{},"content":{"125":{"position":[[5337,20],[5885,20]]}},"keywords":{}}],["quot;$app_dir/app_loader.js"",{"_index":4122,"title":{},"content":{"125":{"position":[[5545,34],[6006,34]]}},"keywords":{}}],["quot;$app_dir/bundle.js"",{"_index":4124,"title":{},"content":{"125":{"position":[[5583,30],[5666,30],[6044,30]]}},"keywords":{}}],["quot;$dir/node_modules/webpack",{"_index":4120,"title":{},"content":{"125":{"position":[[5473,31],[5935,31]]}},"keywords":{}}],["quot;$wasm_dir/debug/$wasm_name.wasm"",{"_index":4115,"title":{},"content":{"125":{"position":[[5283,43],[5831,43]]}},"keywords":{}}],["quot;<stdin>"",{"_index":4330,"title":{},"content":{"129":{"position":[[2471,26]]}},"keywords":{}}],["quot;"",{"_index":1602,"title":{},"content":{"34":{"position":[[1034,12]]}},"keywords":{}}],["quot;""given",{"_index":884,"title":{},"content":{"22":{"position":[[180,23]]}},"keywords":{}}],["quot;.format(c",{"_index":1487,"title":{},"content":{"30":{"position":[[9735,21]]}},"keywords":{}}],["quot;.format(datetime.now().strftime("%i:%m:%",{"_index":1496,"title":{},"content":{"30":{"position":[[9987,54]]}},"keywords":{}}],["quot;.format(end",{"_index":2037,"title":{},"content":{"46":{"position":[[635,19]]}},"keywords":{}}],["quot;.format(four_year_period",{"_index":2510,"title":{},"content":{"65":{"position":[[976,35]]}},"keywords":{}}],["quot;.format(heartbeats_until_2016",{"_index":2491,"title":{},"content":{"64":{"position":[[1772,39]]}},"keywords":{}}],["quot;.format(hr_df_full.index[0",{"_index":2437,"title":{},"content":{"62":{"position":[[1517,36]]}},"keywords":{}}],["quot;.format(len(i",{"_index":1939,"title":{},"content":{"44":{"position":[[1416,22]]}},"keywords":{}}],["quot;.format(list(zip(tick",{"_index":849,"title":{},"content":{"20":{"position":[[2366,33]]}},"keywords":{}}],["quot;.format(naive_guess",{"_index":1944,"title":{},"content":{"44":{"position":[[1535,29]]}},"keywords":{}}],["quot;.format(quarters_left",{"_index":2525,"title":{},"content":{"65":{"position":[[1938,31]]}},"keywords":{}}],["quot;.format(remaining_2016",{"_index":2493,"title":{},"content":{"64":{"position":[[1846,32]]}},"keywords":{}}],["quot;.format(remaining_4i",{"_index":2511,"title":{},"content":{"65":{"position":[[1067,30]]}},"keywords":{}}],["quot;.format(remaining_year",{"_index":2526,"title":{},"content":{"65":{"position":[[2015,32]]}},"keywords":{}}],["quot;.format(request.uri",{"_index":3326,"title":{},"content":{"96":{"position":[[517,28]]}},"keywords":{}}],["quot;.format(tick",{"_index":3220,"title":{},"content":{"93":{"position":[[2319,24]]}},"keywords":{}}],["quot;/home/bspeice/.virtualenvs/releas",{"_index":5209,"title":{},"content":{"188":{"position":[[3754,40]]}},"keywords":{}}],["quot;/point_capnp.rs"",{"_index":3737,"title":{},"content":{"113":{"position":[[693,30]]}},"keywords":{}}],["quot;/usr/lib/python3.7/threading.py"",{"_index":5213,"title":{},"content":{"188":{"position":[[3884,44],[3963,44]]}},"keywords":{}}],["quot;0.1.0"",{"_index":3686,"title":{},"content":{"109":{"position":[[296,17]]}},"keywords":{}}],["quot;0.8"",{"_index":3691,"title":{},"content":{"109":{"position":[[407,15],[450,15]]}},"keywords":{}}],["quot;1000"",{"_index":5103,"title":{},"content":{"181":{"position":[[508,16]]}},"keywords":{}}],["quot;adjust",{"_index":1751,"title":{},"content":{"39":{"position":[[2342,14],[2408,14]]}},"keywords":{}}],["quot;alway",{"_index":1950,"title":{},"content":{"44":{"position":[[1712,12]]}},"keywords":{}}],["quot;appl",{"_index":4157,"title":{},"content":{"125":{"position":[[8230,17]]}},"keywords":{}}],["quot;author_articles_wrapper"",{"_index":892,"title":{},"content":{"22":{"position":[[373,36]]}},"keywords":{}}],["quot;binding"",{"_index":4302,"title":{},"content":{"129":{"position":[[1669,19]]}},"keywords":{}}],["quot;bit",{"_index":4731,"title":{},"content":{"161":{"position":[[367,11]]}},"keywords":{}}],["quot;boilerplate"",{"_index":4215,"title":{},"content":{"125":{"position":[[11502,23]]}},"keywords":{}}],["quot;bradle",{"_index":3687,"title":{},"content":{"109":{"position":[[324,14]]}},"keywords":{}}],["quot;brok",{"_index":3508,"title":{},"content":{"103":{"position":[[278,11]]}},"keywords":{}}],["quot;build",{"_index":224,"title":{},"content":{"4":{"position":[[66,11]]}},"keywords":{}}],["quot;builder"",{"_index":4804,"title":{},"content":{"164":{"position":[[319,19]]}},"keywords":{}}],["quot;bundl",{"_index":226,"title":{},"content":{"4":{"position":[[96,12]]}},"keywords":{}}],["quot;busi",{"_index":5159,"title":{},"content":{"188":{"position":[[751,10]]}},"keywords":{}}],["quot;canon",{"_index":3936,"title":{},"content":{"122":{"position":[[200,15],[1051,15]]}},"keywords":{}}],["quot;capnp_cookbook_1"",{"_index":3685,"title":{},"content":{"109":{"position":[[257,28]]}},"keywords":{}}],["quot;close"",{"_index":1755,"title":{},"content":{"39":{"position":[[2456,17]]}},"keywords":{}}],["quot;cloudy"",{"_index":1351,"title":{},"content":{"30":{"position":[[1112,18]]}},"keywords":{}}],["quot;compil",{"_index":24,"title":{},"content":{"1":{"position":[[258,13]]},"189":{"position":[[25,14]]}},"keywords":{}}],["quot;component"",{"_index":3553,"title":{},"content":{"104":{"position":[[210,21]]}},"keywords":{}}],["quot;components."",{"_index":3552,"title":{},"content":{"104":{"position":[[172,23]]}},"keywords":{}}],["quot;concaten",{"_index":3341,"title":{},"content":{"96":{"position":[[1386,17]]}},"keywords":{}}],["quot;crude"",{"_index":1076,"title":{},"content":{"24":{"position":[[1893,19]]},"25":{"position":[[1617,19]]}},"keywords":{}}],["quot;data",{"_index":4502,"title":{},"content":{"150":{"position":[[767,10]]}},"keywords":{}}],["quot;debug"",{"_index":4705,"title":{},"content":{"160":{"position":[[3546,17]]}},"keywords":{}}],["quot;devops"",{"_index":4492,"title":{},"content":{"150":{"position":[[218,19]]}},"keywords":{}}],["quot;djia"",{"_index":1073,"title":{},"content":{"24":{"position":[[1696,17],[1827,17]]},"25":{"position":[[1417,17],[1551,17]]}},"keywords":{}}],["quot;dow"",{"_index":1078,"title":{},"content":{"24":{"position":[[1931,16]]},"25":{"position":[[1655,16]]}},"keywords":{}}],["quot;extern",{"_index":4183,"title":{},"content":{"125":{"position":[[9404,12]]}},"keywords":{}}],["quot;foreach"",{"_index":5375,"title":{},"content":{"199":{"position":[[334,19]]}},"keywords":{}}],["quot;forward"",{"_index":5032,"title":{},"content":{"175":{"position":[[1436,19]]}},"keywords":{}}],["quot;fun",{"_index":4355,"title":{},"content":{"132":{"position":[[852,9]]}},"keywords":{}}],["quot;futur",{"_index":953,"title":{},"content":{"22":{"position":[[1790,13]]}},"keywords":{}}],["quot;garden",{"_index":4724,"title":{},"content":{"161":{"position":[[27,15]]}},"keywords":{}}],["quot;get",{"_index":199,"title":{},"content":{"3":{"position":[[1216,13]]}},"keywords":{}}],["quot;give"",{"_index":5273,"title":{},"content":{"193":{"position":[[144,16]]}},"keywords":{}}],["quot;given",{"_index":925,"title":{},"content":{"22":{"position":[[1127,11]]}},"keywords":{}}],["quot;global"",{"_index":5110,"title":{},"content":{"182":{"position":[[332,18]]}},"keywords":{}}],["quot;gold"",{"_index":1077,"title":{},"content":{"24":{"position":[[1913,17]]},"25":{"position":[[1637,17]]}},"keywords":{}}],["quot;good",{"_index":3575,"title":{},"content":{"105":{"position":[[227,10]]}},"keywords":{}}],["quot;gotcha"",{"_index":4565,"title":{},"content":{"155":{"position":[[754,19]]}},"keywords":{}}],["quot;heap"",{"_index":4912,"title":{},"content":{"172":{"position":[[763,16]]}},"keywords":{}}],["quot;hey",{"_index":3978,"title":{},"content":{"123":{"position":[[618,10]]}},"keywords":{}}],["quot;high",{"_index":3567,"title":{},"content":{"104":{"position":[[1174,10]]},"125":{"position":[[3203,10]]},"176":{"position":[[900,10]]}},"keywords":{}}],["quot;hold",{"_index":863,"title":{},"content":{"20":{"position":[[2811,15]]}},"keywords":{}}],["quot;http://seekingalpha.com"",{"_index":965,"title":{},"content":{"22":{"position":[[2353,35]]}},"keywords":{}}],["quot;http://seekingalpha.com/author/wal",{"_index":902,"title":{},"content":{"22":{"position":[[607,41]]}},"keywords":{}}],["quot;https://api.forecast.io/forecast/"",{"_index":1469,"title":{},"content":{"30":{"position":[[8806,45]]}},"keywords":{}}],["quot;i",{"_index":3405,"title":{},"content":{"97":{"position":[[3847,8]]},"132":{"position":[[887,7]]}},"keywords":{}}],["quot;id"",{"_index":891,"title":{},"content":{"22":{"position":[[356,16]]}},"keywords":{}}],["quot;if",{"_index":4058,"title":{},"content":{"125":{"position":[[2101,8]]}},"keywords":{}}],["quot;improve"",{"_index":1960,"title":{},"content":{"45":{"position":[[144,19]]}},"keywords":{}}],["quot;index"",{"_index":3409,"title":{},"content":{"97":{"position":[[3919,19],[4481,19],[4917,19],[6428,19]]}},"keywords":{}}],["quot;information"",{"_index":1968,"title":{},"content":{"45":{"position":[[443,23]]}},"keywords":{}}],["quot;it'",{"_index":4081,"title":{},"content":{"125":{"position":[[3451,10]]}},"keywords":{}}],["quot;just",{"_index":295,"title":{},"content":{"4":{"position":[[1459,10]]},"125":{"position":[[7080,10]]}},"keywords":{}}],["quot;knew"",{"_index":2900,"title":{},"content":{"88":{"position":[[2236,16]]}},"keywords":{}}],["quot;likelihood"",{"_index":2655,"title":{},"content":{"74":{"position":[[1556,22]]}},"keywords":{}}],["quot;link"",{"_index":4087,"title":{},"content":{"125":{"position":[[3751,16]]}},"keywords":{}}],["quot;look",{"_index":3865,"title":{},"content":{"120":{"position":[[987,11]]}},"keywords":{}}],["quot;low",{"_index":3554,"title":{},"content":{"104":{"position":[[349,9]]}},"keywords":{}}],["quot;maintenance"",{"_index":3966,"title":{},"content":{"123":{"position":[[20,23]]}},"keywords":{}}],["quot;memory"",{"_index":666,"title":{},"content":{"15":{"position":[[106,18]]}},"keywords":{}}],["quot;miss",{"_index":4164,"title":{},"content":{"125":{"position":[[8418,13]]}},"keywords":{}}],["quot;modern",{"_index":69,"title":{},"content":{"1":{"position":[[763,12]]}},"keywords":{}}],["quot;modules,"",{"_index":112,"title":{},"content":{"2":{"position":[[570,20]]}},"keywords":{}}],["quot;months"",{"_index":423,"title":{},"content":{"7":{"position":[[904,18]]}},"keywords":{}}],["quot;most",{"_index":3558,"title":{},"content":{"104":{"position":[[637,10]]}},"keywords":{}}],["quot;mov",{"_index":4212,"title":{},"content":{"125":{"position":[[11451,10]]}},"keywords":{}}],["quot;nasdaq"",{"_index":1075,"title":{},"content":{"24":{"position":[[1762,19],[1863,19],[1948,19]]},"25":{"position":[[1485,19],[1587,19],[1672,19]]}},"keywords":{}}],["quot;new",{"_index":3493,"title":{},"content":{"102":{"position":[[585,9]]}},"keywords":{}}],["quot;next",{"_index":1971,"title":{},"content":{"45":{"position":[[646,10]]}},"keywords":{}}],["quot;noisy"",{"_index":3565,"title":{},"content":{"104":{"position":[[1079,17]]}},"keywords":{}}],["quot;ops"",{"_index":4491,"title":{},"content":{"150":{"position":[[194,15]]}},"keywords":{}}],["quot;optimize"",{"_index":2662,"title":{},"content":{"75":{"position":[[274,20]]}},"keywords":{}}],["quot;owned"",{"_index":3798,"title":{},"content":{"116":{"position":[[92,17]]}},"keywords":{}}],["quot;packed"",{"_index":4811,"title":{},"content":{"164":{"position":[[841,18],[926,18]]}},"keywords":{}}],["quot;pars",{"_index":4766,"title":{},"content":{"163":{"position":[[636,12]]}},"keywords":{}}],["quot;pca",{"_index":3614,"title":{},"content":{"105":{"position":[[1844,9]]}},"keywords":{}}],["quot;pca"",{"_index":3613,"title":{},"content":{"105":{"position":[[1827,16]]}},"keywords":{}}],["quot;point"",{"_index":3720,"title":{},"content":{"112":{"position":[[1169,17]]}},"keywords":{}}],["quot;primitive"",{"_index":4248,"title":{},"content":{"128":{"position":[[189,21]]}},"keywords":{}}],["quot;prior"",{"_index":2054,"title":{},"content":{"49":{"position":[[119,17]]}},"keywords":{}}],["quot;proposed"",{"_index":2663,"title":{},"content":{"75":{"position":[[399,20]]}},"keywords":{}}],["quot;raini",{"_index":1414,"title":{},"content":{"30":{"position":[[5907,11]]}},"keywords":{}}],["quot;raw"",{"_index":3612,"title":{},"content":{"105":{"position":[[1809,17]]}},"keywords":{}}],["quot;read",{"_index":5062,"title":{},"content":{"179":{"position":[[36,10]]}},"keywords":{}}],["quot;real",{"_index":4685,"title":{},"content":{"160":{"position":[[2134,10]]}},"keywords":{}}],["quot;realized"",{"_index":5090,"title":{},"content":{"180":{"position":[[170,20]]}},"keywords":{}}],["quot;russ"",{"_index":1074,"title":{},"content":{"24":{"position":[[1729,17],[1845,17]]},"25":{"position":[[1451,17],[1569,17]]}},"keywords":{}}],["quot;rust",{"_index":3897,"title":{},"content":{"121":{"position":[[1350,10]]}},"keywords":{}}],["quot;rvalues"",{"_index":5088,"title":{},"content":{"179":{"position":[[1667,20]]}},"keywords":{}}],["quot;s&p"",{"_index":1079,"title":{},"content":{"24":{"position":[[1968,20]]},"25":{"position":[[1692,20]]}},"keywords":{}}],["quot;safe"",{"_index":4702,"title":{},"content":{"160":{"position":[[3421,16]]}},"keywords":{}}],["quot;saturday"",{"_index":3027,"title":{},"content":{"90":{"position":[[3558,20]]}},"keywords":{}}],["quot;scale"",{"_index":78,"title":{},"content":{"2":{"position":[[53,17]]}},"keywords":{}}],["quot;slow,"",{"_index":4418,"title":{},"content":{"139":{"position":[[338,17]]}},"keywords":{}}],["quot;smart",{"_index":4557,"title":{},"content":{"155":{"position":[[33,11]]}},"keywords":{}}],["quot;spy"",{"_index":1072,"title":{},"content":{"24":{"position":[[1664,17],[1809,17]]},"25":{"position":[[1384,17],[1533,17]]}},"keywords":{}}],["quot;stack."",{"_index":4674,"title":{},"content":{"160":{"position":[[1288,18]]}},"keywords":{}}],["quot;stop",{"_index":4911,"title":{},"content":{"172":{"position":[[617,10]]}},"keywords":{}}],["quot;stor",{"_index":5027,"title":{},"content":{"175":{"position":[[1126,11]]}},"keywords":{}}],["quot;store"",{"_index":5031,"title":{},"content":{"175":{"position":[[1371,17]]}},"keywords":{}}],["quot;stored"",{"_index":5104,"title":{},"content":{"181":{"position":[[540,18]]}},"keywords":{}}],["quot;tabulasa.wav"",{"_index":3511,"title":{},"content":{"103":{"position":[[328,24]]}},"keywords":{}}],["quot;th",{"_index":4729,"title":{},"content":{"161":{"position":[[333,9]]},"198":{"position":[[602,9]]}},"keywords":{}}],["quot;trend",{"_index":3073,"title":{},"content":{"91":{"position":[[197,14]]}},"keywords":{}}],["quot;typ",{"_index":237,"title":{},"content":{"4":{"position":[[354,11]]}},"keywords":{}}],["quot;union"",{"_index":4895,"title":{},"content":{"170":{"position":[[90,17]]}},"keywords":{}}],["quot;unlimit",{"_index":1512,"title":{},"content":{"32":{"position":[[66,15]]}},"keywords":{}}],["quot;unpacked"",{"_index":4813,"title":{},"content":{"164":{"position":[[883,20]]}},"keywords":{}}],["quot;us",{"_index":3452,"title":{},"content":{"98":{"position":[[982,9]]}},"keywords":{}}],["quot;value"",{"_index":5057,"title":{},"content":{"178":{"position":[[68,17]]}},"keywords":{}}],["quot;wal",{"_index":5194,"title":{},"content":{"188":{"position":[[2728,10]]}},"keywords":{}}],["quot;webpack",{"_index":271,"title":{},"content":{"4":{"position":[[941,13]]}},"keywords":{}}],["quot;webpack"",{"_index":4016,"title":{},"content":{"125":{"position":[[460,19]]}},"keywords":{}}],["quot;wget/1.13.4"",{"_index":919,"title":{},"content":{"22":{"position":[[962,25],[2460,25]]}},"keywords":{}}],["quot;what",{"_index":4348,"title":{},"content":{"132":{"position":[[459,10]]}},"keywords":{}}],["quot;whi",{"_index":3946,"title":{},"content":{"122":{"position":[[864,9]]}},"keywords":{}}],["quot;yahoo/aapl"",{"_index":1787,"title":{},"content":{"40":{"position":[[158,23]]}},"keywords":{}}],["quot;yahoo/cat"",{"_index":1816,"title":{},"content":{"40":{"position":[[1691,22]]}},"keywords":{}}],["quot;yahoo/goog"",{"_index":1789,"title":{},"content":{"40":{"position":[[206,24],[1738,24]]}},"keywords":{}}],["quot;yahoo/nflx"",{"_index":1788,"title":{},"content":{"40":{"position":[[182,23],[1714,23]]}},"keywords":{}}],["quot;years"",{"_index":421,"title":{},"content":{"7":{"position":[[853,17]]}},"keywords":{}}],["quot;yes/no"",{"_index":4627,"title":{},"content":{"159":{"position":[[123,18]]}},"keywords":{}}],["quot;you",{"_index":3332,"title":{},"content":{"96":{"position":[[757,9],[1176,9]]}},"keywords":{}}],["quot;you'r",{"_index":3325,"title":{},"content":{"96":{"position":[[494,12]]}},"keywords":{}}],["r",{"_index":3381,"title":{},"content":{"97":{"position":[[1877,3]]}},"keywords":{}}],["r>",{"_index":3382,"title":{},"content":{"97":{"position":[[1881,6],[1934,7]]}},"keywords":{}}],["r').read",{"_index":3108,"title":{},"content":{"91":{"position":[[1962,11]]},"93":{"position":[[4375,11]]}},"keywords":{}}],["r3000",{"_index":3246,"title":{},"content":{"93":{"position":[[2999,5]]}},"keywords":{}}],["r3000['exchang",{"_index":3254,"title":{},"content":{"93":{"position":[[3240,18]]}},"keywords":{}}],["r3000[(r3000['exchang",{"_index":3253,"title":{},"content":{"93":{"position":[[3200,24]]}},"keywords":{}}],["r3000_equiti",{"_index":3252,"title":{},"content":{"93":{"position":[[3183,14]]}},"keywords":{}}],["r3000_equities.index",{"_index":3264,"title":{},"content":{"93":{"position":[[3478,21]]}},"keywords":{}}],["r3000_equities.ix[t]['tick",{"_index":3263,"title":{},"content":{"93":{"position":[[3434,32]]}},"keywords":{}}],["r_m",{"_index":737,"title":{},"content":{"19":{"position":[[19,3]]}},"keywords":{}}],["rack",{"_index":4750,"title":{},"content":{"161":{"position":[[1144,4]]}},"keywords":{}}],["radio",{"_index":5010,"title":{},"content":{"175":{"position":[[449,6]]}},"keywords":{}}],["rain",{"_index":1309,"title":{},"content":{"28":{"position":[[4285,4]]},"30":{"position":[[435,7],[4597,4],[5963,4]]}},"keywords":{}}],["rain/cloud",{"_index":1441,"title":{},"content":{"30":{"position":[[8010,10]]}},"keywords":{}}],["rainfal",{"_index":1294,"title":{},"content":{"28":{"position":[[2861,8]]}},"keywords":{}}],["raini",{"_index":1339,"title":{},"content":{"30":{"position":[[592,5],[5749,5],[5845,5],[6646,5],[6851,5],[7097,6],[7151,5],[7685,5]]}},"keywords":{}}],["rais",{"_index":1515,"title":{},"content":{"32":{"position":[[113,7]]}},"keywords":{}}],["ran",{"_index":2617,"title":{},"content":{"72":{"position":[[438,3]]},"125":{"position":[[4122,3]]},"146":{"position":[[421,3]]}},"keywords":{}}],["randn(m",{"_index":401,"title":{},"content":{"7":{"position":[[498,9]]}},"keywords":{}}],["random",{"_index":1708,"title":{},"content":{"39":{"position":[[170,6]]},"51":{"position":[[3024,6]]},"53":{"position":[[52,6]]},"75":{"position":[[140,6]]},"76":{"position":[[904,6]]},"90":{"position":[[4013,6]]}},"keywords":{}}],["randomli",{"_index":2134,"title":{},"content":{"51":{"position":[[2838,8]]},"76":{"position":[[1052,8],[3127,8]]}},"keywords":{}}],["rang",{"_index":2399,"title":{},"content":{"62":{"position":[[292,5]]},"104":{"position":[[1777,5]]}},"keywords":{}}],["range(0",{"_index":1137,"title":{},"content":{"25":{"position":[[294,8]]},"28":{"position":[[1077,8]]},"30":{"position":[[2152,8],[3638,8],[3857,8],[5411,8],[6711,8],[6936,8]]},"44":{"position":[[677,8]]},"53":{"position":[[136,8]]}},"keywords":{}}],["range(1",{"_index":1029,"title":{},"content":{"24":{"position":[[569,8]]},"90":{"position":[[4110,8]]}},"keywords":{}}],["range(1990",{"_index":1255,"title":{},"content":{"28":{"position":[[1768,11]]},"30":{"position":[[1354,11]]}},"keywords":{}}],["range(1990,2016",{"_index":1474,"title":{},"content":{"30":{"position":[[9071,16]]}},"keywords":{}}],["range(2",{"_index":907,"title":{},"content":{"22":{"position":[[751,8]]},"188":{"position":[[1105,8]]},"189":{"position":[[1167,8],[1437,8]]}},"keywords":{}}],["range(7",{"_index":1355,"title":{},"content":{"30":{"position":[[1381,8]]}},"keywords":{}}],["range_begin",{"_index":2994,"title":{},"content":{"90":{"position":[[1340,11],[2695,11]]}},"keywords":{}}],["range_end",{"_index":2995,"title":{},"content":{"90":{"position":[[1364,9],[1421,11],[1473,11],[1523,11],[1672,11],[1898,11],[2719,9],[2771,11],[2816,11],[3037,11]]}},"keywords":{}}],["rap",{"_index":2286,"title":{},"content":{"53":{"position":[[2171,3]]}},"keywords":{}}],["raph",{"_index":4642,"title":{},"content":{"159":{"position":[[1254,4]]}},"keywords":{}}],["rare",{"_index":4342,"title":{},"content":{"132":{"position":[[183,6]]}},"keywords":{}}],["rate",{"_index":461,"title":{},"content":{"9":{"position":[[207,4],[239,5],[329,4],[537,5],[691,4]]},"10":{"position":[[397,5]]},"11":{"position":[[234,5]]},"13":{"position":[[385,4]]},"62":{"position":[[99,4],[1725,4]]},"66":{"position":[[144,4]]},"93":{"position":[[4606,4]]}},"keywords":{}}],["rate=sampler",{"_index":3519,"title":{},"content":{"103":{"position":[[682,16],[1827,16],[2144,16]]},"105":{"position":[[2781,16],[2979,16],[3254,16]]}},"keywords":{}}],["rates)σ\\sigma",{"_index":338,"title":{},"content":{"6":{"position":[[517,14]]}},"keywords":{}}],["rates/pages/textview.aspx?data=yield",{"_index":494,"title":{},"content":{"10":{"position":[[274,36]]}},"keywords":{}}],["ratio",{"_index":735,"title":{"19":{"position":[[23,6]]}},"content":{"105":{"position":[[3068,5]]}},"keywords":{}}],["raw",{"_index":2834,"title":{},"content":{"86":{"position":[[1079,3]]},"105":{"position":[[1948,3]]},"167":{"position":[[140,3]]}},"keywords":{}}],["raw_estimate(transform",{"_index":3581,"title":{},"content":{"105":{"position":[[497,25],[1484,25]]}},"keywords":{}}],["raw_pca_estim",{"_index":3604,"title":{},"content":{"105":{"position":[[1465,16],[1624,17]]}},"keywords":{}}],["raw_siz",{"_index":3606,"title":{},"content":{"105":{"position":[[1565,8],[1614,9]]}},"keywords":{}}],["rax",{"_index":4271,"title":{},"content":{"128":{"position":[[1286,3],[1496,3]]},"129":{"position":[[556,4],[591,3]]},"193":{"position":[[1572,5]]}},"keywords":{}}],["ray",{"_index":5268,"title":{},"content":{"192":{"position":[[423,6],[523,3]]}},"keywords":{}}],["rb",{"_index":1228,"title":{},"content":{"28":{"position":[[918,6]]},"30":{"position":[[1250,6]]}},"keywords":{}}],["rbp",{"_index":4256,"title":{},"content":{"128":{"position":[[452,3],[460,4],[533,4],[646,4],[764,3],[772,4],[880,4],[901,3]]}},"keywords":{}}],["rc",{"_index":4637,"title":{},"content":{"159":{"position":[[984,3]]}},"keywords":{}}],["rc::new(0",{"_index":4583,"title":{},"content":{"155":{"position":[[1449,11]]}},"keywords":{}}],["rdi",{"_index":4283,"title":{},"content":{"129":{"position":[[543,4],[680,4]]},"193":{"position":[[1262,5]]}},"keywords":{}}],["re",{"_index":638,"title":{"94":{"position":[[9,2]]}},"content":{"14":{"position":[[1185,2]]},"25":{"position":[[95,2]]},"55":{"position":[[24,2]]},"88":{"position":[[976,2]]},"93":{"position":[[1364,2]]},"111":{"position":[[635,2]]},"136":{"position":[[369,3],[708,2],[858,2]]},"164":{"position":[[447,2],[578,2]]},"189":{"position":[[354,2]]}},"keywords":{}}],["re.match(r'\\d+/\\d+/\\d",{"_index":3208,"title":{},"content":{"93":{"position":[[1772,24]]}},"keywords":{}}],["reach",{"_index":242,"title":{},"content":{"4":{"position":[[440,5]]},"13":{"position":[[905,7]]},"14":{"position":[[1923,7]]},"15":{"position":[[1591,7]]},"52":{"position":[[688,7]]},"76":{"position":[[2338,5]]},"172":{"position":[[175,7]]}},"keywords":{}}],["react",{"_index":28,"title":{},"content":{"1":{"position":[[320,5]]},"3":{"position":[[365,5],[401,5]]},"4":{"position":[[39,5]]},"91":{"position":[[4891,6]]},"93":{"position":[[566,6]]},"125":{"position":[[963,5],[11586,5]]},"176":{"position":[[1079,5]]}},"keywords":{}}],["reaction",{"_index":3172,"title":{},"content":{"91":{"position":[[5476,8]]}},"keywords":{}}],["read",{"_index":1709,"title":{"55":{"position":[[12,8]]},"135":{"position":[[0,7]]},"179":{"position":[[0,4]]}},"content":{"39":{"position":[[195,4]]},"91":{"position":[[1740,4]]},"104":{"position":[[58,4]]},"128":{"position":[[41,7]]},"160":{"position":[[2202,7],[3994,4]]},"163":{"position":[[143,4],[384,4]]},"164":{"position":[[613,7],[749,7],[918,7],[1400,4]]},"165":{"position":[[1152,7]]},"166":{"position":[[188,4]]},"169":{"position":[[65,4]]},"173":{"position":[[955,7]]},"178":{"position":[[563,4]]},"182":{"position":[[553,4]]},"185":{"position":[[332,5]]},"193":{"position":[[1317,4]]}},"keywords":{}}],["readabl",{"_index":3929,"title":{},"content":{"121":{"position":[[2738,9]]}},"keywords":{}}],["reader",{"_index":3723,"title":{"116":{"position":[[19,6]]}},"content":{"112":{"position":[[1292,6],[1432,7],[1580,6]]},"113":{"position":[[1947,7]]},"116":{"position":[[609,6],[3117,6],[3163,6]]},"117":{"position":[[260,6]]}},"keywords":{}}],["readi",{"_index":4744,"title":{},"content":{"161":{"position":[[934,6]]},"193":{"position":[[1699,5]]}},"keywords":{}}],["real",{"_index":497,"title":{},"content":{"10":{"position":[[374,4]]},"11":{"position":[[78,4]]}},"keywords":{}}],["real_drop_in_plac",{"_index":4597,"title":{},"content":{"156":{"position":[[602,19]]},"199":{"position":[[1200,20]]}},"keywords":{}}],["realist",{"_index":1510,"title":{"105":{"position":[[7,9]]}},"content":{"32":{"position":[[15,9]]},"105":{"position":[[2876,10]]},"190":{"position":[[114,9]]}},"keywords":{}}],["realiti",{"_index":1344,"title":{},"content":{"30":{"position":[[755,8]]}},"keywords":{}}],["realiz",{"_index":2832,"title":{},"content":{"86":{"position":[[836,8]]},"120":{"position":[[590,7]]},"175":{"position":[[346,8]]}},"keywords":{}}],["realli",{"_index":1284,"title":{"149":{"position":[[21,6]]}},"content":{"28":{"position":[[2483,6],[2510,6]]},"40":{"position":[[3680,6]]},"41":{"position":[[12,6]]},"50":{"position":[[46,6]]},"53":{"position":[[438,6]]},"61":{"position":[[510,6],[555,6],[2031,6]]},"73":{"position":[[9,6]]},"88":{"position":[[154,6]]},"91":{"position":[[4591,6]]},"96":{"position":[[1568,6]]},"97":{"position":[[214,6],[3145,6],[4191,6]]},"101":{"position":[[193,6]]},"106":{"position":[[200,6],[988,6]]},"113":{"position":[[2065,6]]},"115":{"position":[[874,6],[3074,6]]},"117":{"position":[[531,6]]},"121":{"position":[[2397,6]]},"125":{"position":[[67,6],[893,6],[1219,6],[1635,7],[3186,6]]},"127":{"position":[[1132,6]]},"128":{"position":[[916,6]]},"129":{"position":[[289,6]]},"130":{"position":[[129,6]]},"132":{"position":[[575,6]]},"163":{"position":[[2233,6]]}},"keywords":{}}],["reallygarbag",{"_index":4670,"title":{},"content":{"160":{"position":[[1057,13]]}},"keywords":{}}],["realtalk",{"_index":2216,"title":{},"content":{"53":{"position":[[518,9]]}},"keywords":{}}],["reason",{"_index":1697,"title":{},"content":{"38":{"position":[[741,6]]},"85":{"position":[[149,10]]},"116":{"position":[[2661,8]]},"117":{"position":[[108,8]]},"120":{"position":[[976,10]]},"127":{"position":[[5,6]]},"139":{"position":[[94,7]]},"152":{"position":[[44,6]]},"160":{"position":[[1119,6],[2616,7],[3251,7]]},"175":{"position":[[20,6]]},"195":{"position":[[1043,10]]}},"keywords":{}}],["reasonable:if",{"_index":5357,"title":{},"content":{"198":{"position":[[230,13]]}},"keywords":{}}],["receiv",{"_index":633,"title":{},"content":{"14":{"position":[[775,7],[924,7],[1009,7],[1112,7]]},"123":{"position":[[557,7]]},"125":{"position":[[840,9]]},"136":{"position":[[621,8]]},"189":{"position":[[1242,7]]}},"keywords":{}}],["recent",{"_index":158,"title":{},"content":{"3":{"position":[[485,6]]},"30":{"position":[[60,6],[443,9],[603,8]]},"88":{"position":[[3,8]]},"125":{"position":[[1576,6]]},"161":{"position":[[7,8],[522,8]]},"163":{"position":[[467,8]]},"165":{"position":[[93,8]]},"172":{"position":[[558,6]]},"188":{"position":[[3729,6]]}},"keywords":{}}],["recip",{"_index":4745,"title":{},"content":{"161":{"position":[[950,6]]}},"keywords":{}}],["reclaim",{"_index":4574,"title":{},"content":{"155":{"position":[[1207,10]]}},"keywords":{}}],["recogn",{"_index":2784,"title":{},"content":{"81":{"position":[[70,9]]}},"keywords":{}}],["recommend",{"_index":120,"title":{},"content":{"2":{"position":[[689,15]]},"3":{"position":[[84,15]]},"97":{"position":[[4400,11]]},"125":{"position":[[3536,12],[7481,9],[10675,9]]}},"keywords":{}}],["recompil",{"_index":4022,"title":{},"content":{"125":{"position":[[649,9]]}},"keywords":{}}],["recon",{"_index":3603,"title":{},"content":{"105":{"position":[[1405,5]]}},"keywords":{}}],["reconcil",{"_index":4009,"title":{},"content":{"125":{"position":[[182,9]]}},"keywords":{}}],["reconstruct",{"_index":3535,"title":{},"content":{"103":{"position":[[1386,13],[1485,13],[1736,13],[2055,13],[2184,13]]},"104":{"position":[[291,11],[971,11]]},"105":{"position":[[2693,13],[2894,13],[3166,13]]},"106":{"position":[[630,11]]}},"keywords":{}}],["record",{"_index":1021,"title":{},"content":{"24":{"position":[[380,8]]},"26":{"position":[[167,8]]},"30":{"position":[[4323,8],[7255,7]]},"43":{"position":[[359,6]]},"62":{"position":[[889,7],[1186,6]]},"93":{"position":[[1887,6]]},"133":{"position":[[117,6]]},"155":{"position":[[1016,8]]},"176":{"position":[[676,6]]},"179":{"position":[[1447,6]]}},"keywords":{}}],["record['act",{"_index":2416,"title":{},"content":{"62":{"position":[[920,18]]}},"keywords":{}}],["record_font_tag",{"_index":927,"title":{},"content":{"22":{"position":[[1193,16]]}},"keywords":{}}],["record_to_df(record",{"_index":2415,"title":{},"content":{"62":{"position":[[838,21]]}},"keywords":{}}],["record_to_df(record.json",{"_index":2426,"title":{},"content":{"62":{"position":[[1153,28]]}},"keywords":{}}],["recov",{"_index":2746,"title":{},"content":{"78":{"position":[[72,7]]},"82":{"position":[[1177,9]]}},"keywords":{}}],["recreat",{"_index":3893,"title":{},"content":{"121":{"position":[[1195,8]]}},"keywords":{}}],["recurs",{"_index":2208,"title":{},"content":{"53":{"position":[[388,9]]},"189":{"position":[[2948,11]]}},"keywords":{}}],["redirect_uri",{"_index":2381,"title":{},"content":{"61":{"position":[[1712,15]]}},"keywords":{}}],["reduc",{"_index":1447,"title":{},"content":{"30":{"position":[[8360,6]]},"43":{"position":[[1444,6]]},"44":{"position":[[21,6]]},"45":{"position":[[312,6],[744,6]]},"51":{"position":[[1083,6]]},"101":{"position":[[660,6]]},"174":{"position":[[800,6]]}},"keywords":{}}],["reduce(lambda",{"_index":1481,"title":{},"content":{"30":{"position":[[9414,13]]},"51":{"position":[[1127,13]]}},"keywords":{}}],["reduct",{"_index":1894,"title":{"44":{"position":[[15,9]]},"45":{"position":[[15,9]]}},"content":{"45":{"position":[[712,10],[1071,10],[1158,9],[1594,9]]},"102":{"position":[[161,10],[1127,9]]},"105":{"position":[[965,9]]}},"keywords":{}}],["redund",{"_index":3919,"title":{},"content":{"121":{"position":[[2235,9]]},"124":{"position":[[680,9]]}},"keywords":{}}],["refcel",{"_index":4568,"title":{},"content":{"155":{"position":[[790,8]]},"159":{"position":[[725,9]]},"180":{"position":[[572,8]]}},"keywords":{}}],["refcell<u32>",{"_index":5093,"title":{},"content":{"180":{"position":[[379,18]]}},"keywords":{}}],["refcell<u8>",{"_index":5077,"title":{},"content":{"179":{"position":[[869,17]]},"184":{"position":[[1126,17]]},"185":{"position":[[682,18]]}},"keywords":{}}],["refcell::new(0",{"_index":5132,"title":{},"content":{"184":{"position":[[1146,16]]}},"keywords":{}}],["refcell::new(24",{"_index":5094,"title":{},"content":{"180":{"position":[[400,17]]}},"keywords":{}}],["refcell::new(25",{"_index":5073,"title":{},"content":{"179":{"position":[[588,17],[889,17]]}},"keywords":{}}],["refcell::new(8",{"_index":5136,"title":{},"content":{"185":{"position":[[840,15]]}},"keywords":{}}],["refcell::newfunct",{"_index":5098,"title":{},"content":{"180":{"position":[[629,21]]}},"keywords":{}}],["refer",{"_index":1593,"title":{"115":{"position":[[20,10]]}},"content":{"34":{"position":[[360,5],[665,8]]},"91":{"position":[[2630,9]]},"92":{"position":[[442,9]]},"93":{"position":[[1993,9]]},"97":{"position":[[5275,9],[5644,10],[5926,10]]},"98":{"position":[[921,9]]},"108":{"position":[[258,5]]},"113":{"position":[[1027,9]]},"115":{"position":[[62,10],[546,9]]},"121":{"position":[[675,9]]},"125":{"position":[[796,10],[2880,9]]},"127":{"position":[[259,8]]},"129":{"position":[[1277,5]]},"136":{"position":[[548,9]]},"155":{"position":[[1159,9]]},"159":{"position":[[503,10]]},"172":{"position":[[159,9]]},"179":{"position":[[473,10],[1715,5]]},"182":{"position":[[113,9]]},"183":{"position":[[680,10],[732,6]]},"184":{"position":[[231,9]]},"193":{"position":[[3009,9]]},"196":{"position":[[301,9],[842,9],[1260,9]]},"199":{"position":[[1186,10]]}},"keywords":{}}],["referenc",{"_index":3420,"title":{},"content":{"97":{"position":[[4737,10]]}},"keywords":{}}],["reference/valu",{"_index":5108,"title":{},"content":{"182":{"position":[[239,15]]}},"keywords":{}}],["references.python",{"_index":5326,"title":{},"content":{"196":{"position":[[246,17]]}},"keywords":{}}],["refin",{"_index":3196,"title":{},"content":{"93":{"position":[[1148,7]]}},"keywords":{}}],["reflect",{"_index":218,"title":{"4":{"position":[[13,11]]}},"content":{"30":{"position":[[747,7],[2663,7],[4017,7]]}},"keywords":{}}],["reform",{"_index":3948,"title":{},"content":{"122":{"position":[[888,6]]}},"keywords":{}}],["refus",{"_index":202,"title":{},"content":{"3":{"position":[[1262,6]]},"97":{"position":[[469,7]]},"185":{"position":[[534,7]]}},"keywords":{}}],["regardless",{"_index":5039,"title":{},"content":{"176":{"position":[[27,10]]}},"keywords":{}}],["regex",{"_index":4109,"title":{},"content":{"125":{"position":[[5138,5]]}},"keywords":{}}],["region",{"_index":4673,"title":{},"content":{"160":{"position":[[1270,6]]}},"keywords":{}}],["regist",{"_index":2341,"title":{"60":{"position":[[0,11]]}},"content":{"59":{"position":[[96,11]]},"60":{"position":[[14,10]]},"173":{"position":[[1498,11]]},"193":{"position":[[518,11],[1278,9],[1578,8],[3161,10]]},"197":{"position":[[1042,8]]}},"keywords":{}}],["regress",{"_index":1882,"title":{},"content":{"43":{"position":[[840,11]]}},"keywords":{}}],["regular",{"_index":4456,"title":{"145":{"position":[[8,7]]}},"content":{"160":{"position":[[153,7]]},"176":{"position":[[172,7]]},"199":{"position":[[170,7]]}},"keywords":{}}],["reject",{"_index":4095,"title":{},"content":{"125":{"position":[[4370,8]]}},"keywords":{}}],["rel",{"_index":1699,"title":{},"content":{"38":{"position":[[859,8]]},"65":{"position":[[134,12]]},"83":{"position":[[525,10]]},"106":{"position":[[105,8]]},"122":{"position":[[1358,10]]},"127":{"position":[[290,8]]},"193":{"position":[[471,8]]}},"keywords":{}}],["relat",{"_index":4201,"title":{},"content":{"125":{"position":[[10530,7]]},"172":{"position":[[1704,7]]},"182":{"position":[[22,7]]}},"keywords":{}}],["relativedelta(days=1",{"_index":1003,"title":{},"content":{"23":{"position":[[342,21]]}},"keywords":{}}],["releas",{"_index":2292,"title":{"87":{"position":[[27,8]]},"187":{"position":[[0,7]]}},"content":{"54":{"position":[[210,8]]},"88":{"position":[[1621,9],[1948,9],[2124,9],[3078,9],[3463,9],[3681,8]]},"89":{"position":[[198,9],[444,9],[624,8],[881,8]]},"90":{"position":[[3579,8]]},"91":{"position":[[135,8],[839,9],[1309,9],[1488,8],[4931,9],[5390,8]]},"93":{"position":[[130,7],[247,8],[356,7]]},"108":{"position":[[685,7]]},"122":{"position":[[1202,8],[1418,7]]},"141":{"position":[[231,8]]},"143":{"position":[[429,7]]},"146":{"position":[[217,7]]},"148":{"position":[[333,8]]},"160":{"position":[[3655,7],[3692,7]]},"163":{"position":[[476,8]]},"188":{"position":[[953,7],[1197,7],[1354,9],[2341,8],[3194,8]]},"189":{"position":[[819,7]]}},"keywords":{}}],["release).al",{"_index":4706,"title":{},"content":{"160":{"position":[[3717,12]]}},"keywords":{}}],["release?given",{"_index":2953,"title":{},"content":{"89":{"position":[[680,13]]}},"keywords":{}}],["reli",{"_index":3654,"title":{},"content":{"106":{"position":[[567,6]]},"158":{"position":[[175,4]]},"176":{"position":[[966,4]]},"181":{"position":[[906,4]]}},"keywords":{}}],["reliabl",{"_index":4666,"title":{},"content":{"160":{"position":[[879,12]]}},"keywords":{}}],["reliev",{"_index":4661,"title":{},"content":{"160":{"position":[[660,8]]}},"keywords":{}}],["religion",{"_index":2205,"title":{},"content":{"53":{"position":[[341,8]]}},"keywords":{}}],["remain",{"_index":2137,"title":{},"content":{"51":{"position":[[2985,9]]},"61":{"position":[[1103,7]]},"64":{"position":[[1911,9]]},"65":{"position":[[93,10],[965,10],[1119,10],[1133,9],[2082,9]]},"70":{"position":[[1296,7]]},"163":{"position":[[1834,10],[2042,11]]},"188":{"position":[[1380,7]]},"189":{"position":[[850,6],[1281,7]]}},"keywords":{}}],["remaining_2016",{"_index":2490,"title":{},"content":{"64":{"position":[[1683,14]]},"65":{"position":[[831,14],[881,14]]}},"keywords":{}}],["remaining_4i",{"_index":2508,"title":{},"content":{"65":{"position":[[866,12],[1598,12]]}},"keywords":{}}],["remaining_leap",{"_index":2520,"title":{},"content":{"65":{"position":[[1581,14],[1791,14],[1845,14]]}},"keywords":{}}],["remaining_year",{"_index":2523,"title":{},"content":{"65":{"position":[[1828,14],[2361,14]]}},"keywords":{}}],["remedi",{"_index":4365,"title":{},"content":{"133":{"position":[[149,6]]},"172":{"position":[[2085,7]]}},"keywords":{}}],["rememb",{"_index":67,"title":{},"content":{"1":{"position":[[745,8]]},"15":{"position":[[138,9]]},"97":{"position":[[2774,8]]},"127":{"position":[[502,8]]}},"keywords":{}}],["remov",{"_index":1966,"title":{},"content":{"45":{"position":[[369,8],[3396,7]]},"90":{"position":[[378,6],[395,7],[595,6],[645,6]]},"91":{"position":[[1984,6],[4101,6]]},"93":{"position":[[4397,6]]},"104":{"position":[[1162,7],[1901,6]]},"115":{"position":[[2500,7]]},"125":{"position":[[5147,6]]},"145":{"position":[[283,6]]},"153":{"position":[[419,6]]}},"keywords":{}}],["render",{"_index":82,"title":{},"content":{"2":{"position":[[122,9],[189,6]]}},"keywords":{}}],["repeat",{"_index":3168,"title":{},"content":{"91":{"position":[[4948,6]]},"92":{"position":[[20,6],[1549,6]]},"115":{"position":[[2638,8]]},"160":{"position":[[4447,10]]},"189":{"position":[[901,6]]}},"keywords":{}}],["replac",{"_index":3279,"title":{},"content":{"93":{"position":[[4745,7],[5160,7]]},"125":{"position":[[287,7]]},"179":{"position":[[491,9]]}},"keywords":{}}],["replay",{"_index":4980,"title":{},"content":{"174":{"position":[[263,7]]}},"keywords":{}}],["repli",{"_index":2074,"title":{},"content":{"51":{"position":[[201,5],[231,7]]}},"keywords":{}}],["replic",{"_index":3568,"title":{},"content":{"104":{"position":[[1498,9]]}},"keywords":{}}],["repmat(1:n",{"_index":410,"title":{},"content":{"7":{"position":[[663,11]]}},"keywords":{}}],["report",{"_index":3024,"title":{},"content":{"90":{"position":[[3487,7]]},"93":{"position":[[1862,7],[1956,7]]},"167":{"position":[[170,8]]}},"keywords":{}}],["repres",{"_index":978,"title":{},"content":{"22":{"position":[[2782,9]]},"43":{"position":[[1273,11]]},"90":{"position":[[4759,10],[4799,11],[5028,10]]},"102":{"position":[[253,10],[767,12]]},"104":{"position":[[144,9],[1244,9],[1321,9]]},"113":{"position":[[2087,9]]},"117":{"position":[[709,11],[857,10]]},"163":{"position":[[268,14]]},"188":{"position":[[2646,10]]}},"keywords":{}}],["represent",{"_index":4812,"title":{},"content":{"164":{"position":[[860,15]]}},"keywords":{}}],["reput",{"_index":1207,"title":{},"content":{"28":{"position":[[274,10],[823,10]]}},"keywords":{}}],["req",{"_index":3412,"title":{},"content":{"97":{"position":[[4439,5],[4875,5]]}},"keywords":{}}],["req.url",{"_index":3336,"title":{},"content":{"96":{"position":[[1210,10],[1747,11],[1907,7],[2295,11]]}},"keywords":{}}],["request",{"_index":914,"title":{"62":{"position":[[0,10]]}},"content":{"22":{"position":[[879,8]]},"30":{"position":[[8374,8]]},"61":{"position":[[831,7],[1277,8],[1867,7]]},"93":{"position":[[1348,8]]},"96":{"position":[[682,8],[980,7],[1101,8],[1631,8],[2177,8]]},"97":{"position":[[683,8],[1512,8],[1574,8],[3668,8],[4454,8],[4890,8]]},"123":{"position":[[807,8]]},"156":{"position":[[86,7]]}},"keywords":{}}],["request_url",{"_index":2382,"title":{},"content":{"61":{"position":[[1767,11]]}},"keywords":{}}],["requests.adapters.httpadapter(max_retries=0",{"_index":3235,"title":{},"content":{"93":{"position":[[2602,44]]}},"keywords":{}}],["requests.get(pag",{"_index":916,"title":{},"content":{"22":{"position":[[910,18]]}},"keywords":{}}],["requests.get(sa",{"_index":967,"title":{},"content":{"22":{"position":[[2404,15]]}},"keywords":{}}],["requests.get(url).json",{"_index":1473,"title":{},"content":{"30":{"position":[[9038,24]]}},"keywords":{}}],["requests.sess",{"_index":3234,"title":{},"content":{"93":{"position":[[2579,18]]}},"keywords":{}}],["requests_oauthlib",{"_index":2401,"title":{},"content":{"62":{"position":[[369,17]]}},"keywords":{}}],["requir",{"_index":6,"title":{},"content":{"1":{"position":[[19,11]]},"3":{"position":[[160,12]]},"32":{"position":[[2248,8]]},"59":{"position":[[87,8]]},"61":{"position":[[1391,8]]},"125":{"position":[[8010,8],[9378,8]]},"128":{"position":[[102,9]]},"136":{"position":[[529,8],[949,9]]},"160":{"position":[[2282,12]]},"164":{"position":[[604,8],[1318,8]]},"174":{"position":[[1254,8]]},"176":{"position":[[76,7]]},"190":{"position":[[327,8],[553,7]]},"196":{"position":[[571,8]]}},"keywords":{}}],["res.1",{"_index":4394,"title":{},"content":{"136":{"position":[[484,7]]}},"keywords":{}}],["rescu",{"_index":32,"title":{},"content":{"1":{"position":[[348,6]]}},"keywords":{}}],["research",{"_index":2303,"title":{},"content":{"55":{"position":[[208,8]]},"125":{"position":[[9839,9]]},"170":{"position":[[447,8]]}},"keywords":{}}],["reserv",{"_index":4432,"title":{},"content":{"140":{"position":[[103,8],[193,7]]},"141":{"position":[[282,9]]},"145":{"position":[[227,8]]},"146":{"position":[[336,8]]},"153":{"position":[[802,7]]},"173":{"position":[[417,7]]}},"keywords":{}}],["reshap",{"_index":3495,"title":{},"content":{"102":{"position":[[993,7]]},"103":{"position":[[1147,7],[1190,8]]}},"keywords":{}}],["resist",{"_index":182,"title":{},"content":{"3":{"position":[[914,7]]}},"keywords":{}}],["resolut",{"_index":3976,"title":{},"content":{"123":{"position":[[421,10]]}},"keywords":{}}],["resolv",{"_index":4099,"title":{},"content":{"125":{"position":[[4651,9],[4963,7],[8544,7],[9012,7]]}},"keywords":{}}],["resourc",{"_index":176,"title":{},"content":{"3":{"position":[[825,10]]},"4":{"position":[[457,9],[682,8]]}},"keywords":{}}],["respond",{"_index":1856,"title":{},"content":{"41":{"position":[[629,7]]},"123":{"position":[[604,8]]}},"keywords":{}}],["respons",{"_index":1612,"title":{},"content":{"34":{"position":[[1207,14]]},"105":{"position":[[3331,9]]},"125":{"position":[[4234,8]]},"155":{"position":[[426,11]]}},"keywords":{}}],["response_typ",{"_index":2378,"title":{},"content":{"61":{"position":[[1657,16]]}},"keywords":{}}],["response_url",{"_index":2387,"title":{},"content":{"61":{"position":[[2155,14]]}},"keywords":{}}],["responsibl",{"_index":5330,"title":{},"content":{"196":{"position":[[620,13]]}},"keywords":{}}],["rest",{"_index":33,"title":{},"content":{"1":{"position":[[363,4]]},"66":{"position":[[268,4]]},"175":{"position":[[1065,5]]}},"keywords":{}}],["result",{"_index":483,"title":{"53":{"position":[[4,8]]},"167":{"position":[[0,8]]}},"content":{"10":{"position":[[86,8]]},"15":{"position":[[486,9]]},"30":{"position":[[2751,8],[7893,8]]},"34":{"position":[[3497,7]]},"39":{"position":[[72,7],[2633,6],[3029,6],[3097,7]]},"40":{"position":[[2116,7]]},"41":{"position":[[123,7],[244,7]]},"43":{"position":[[1302,8]]},"51":{"position":[[3686,7]]},"58":{"position":[[344,6]]},"69":{"position":[[34,7]]},"72":{"position":[[561,7],[593,8],[669,7]]},"73":{"position":[[844,7]]},"74":{"position":[[98,6],[830,7]]},"76":{"position":[[117,8]]},"81":{"position":[[91,7]]},"82":{"position":[[996,7]]},"83":{"position":[[11,7],[146,8],[192,7]]},"91":{"position":[[1659,8],[3927,7],[5892,7]]},"92":{"position":[[1643,7]]},"93":{"position":[[443,7]]},"96":{"position":[[299,6]]},"97":{"position":[[3515,7]]},"101":{"position":[[863,9]]},"105":{"position":[[73,7],[815,6]]},"106":{"position":[[1124,8]]},"132":{"position":[[730,7]]},"152":{"position":[[805,6]]},"167":{"position":[[144,7],[240,7]]},"178":{"position":[[615,9]]},"189":{"position":[[2023,6]]},"193":{"position":[[217,7],[544,7],[1026,6],[1190,7],[1543,6]]}},"keywords":{}}],["result["days"",{"_index":1767,"title":{},"content":{"39":{"position":[[2783,24]]}},"keywords":{}}],["result["investments"",{"_index":1772,"title":{},"content":{"39":{"position":[[2955,31]]}},"keywords":{}}],["result["max"",{"_index":1765,"title":{},"content":{"39":{"position":[[2719,23]]}},"keywords":{}}],["result["profit"",{"_index":1762,"title":{},"content":{"39":{"position":[[2657,26]]}},"keywords":{}}],["result["score"",{"_index":1769,"title":{},"content":{"39":{"position":[[2848,25]]}},"keywords":{}}],["results[tick",{"_index":1778,"title":{},"content":{"39":{"position":[[3239,15]]}},"keywords":{}}],["results_df",{"_index":1775,"title":{},"content":{"39":{"position":[[3162,10],[3257,10]]}},"keywords":{}}],["ret",{"_index":749,"title":{},"content":{"19":{"position":[[295,4]]},"20":{"position":[[249,4]]},"128":{"position":[[742,3],[905,3],[1500,3],[1620,3]]},"129":{"position":[[731,3]]}},"keywords":{}}],["ret.abs().max",{"_index":767,"title":{},"content":{"20":{"position":[[254,15]]}},"keywords":{}}],["ret.mean",{"_index":750,"title":{},"content":{"19":{"position":[[300,11]]}},"keywords":{}}],["ret.std",{"_index":752,"title":{},"content":{"19":{"position":[[346,9]]}},"keywords":{}}],["retriev",{"_index":1348,"title":{},"content":{"30":{"position":[[876,9],[8216,10],[9625,9],[9976,10],[10142,10],[10199,10],[10253,10],[10303,10],[10367,10]]},"60":{"position":[[83,8]]},"62":{"position":[[1691,9]]},"89":{"position":[[951,8]]},"91":{"position":[[3292,9]]},"92":{"position":[[1104,9]]},"117":{"position":[[1668,8]]},"193":{"position":[[1624,8]]}},"keywords":{}}],["retrieve_data(url",{"_index":964,"title":{},"content":{"22":{"position":[[2328,19]]}},"keywords":{}}],["retrieve_int",{"_index":5347,"title":{},"content":{"197":{"position":[[748,14],[873,14]]}},"keywords":{}}],["retrieve_int(&a",{"_index":5352,"title":{},"content":{"197":{"position":[[1370,21]]}},"keywords":{}}],["retrieve_int(&b",{"_index":5353,"title":{},"content":{"197":{"position":[[1392,21]]}},"keywords":{}}],["retrieve_int(u",{"_index":5348,"title":{},"content":{"197":{"position":[[935,15]]}},"keywords":{}}],["return",{"_index":402,"title":{"18":{"position":[[16,7]]},"23":{"position":[[13,7]]}},"content":{"7":{"position":[[512,6]]},"12":{"position":[[510,6]]},"13":{"position":[[813,6],[1000,6],[1063,6],[1418,6]]},"14":{"position":[[1670,6],[2018,6],[2097,6],[2490,6]]},"15":{"position":[[1060,6],[1686,6],[1765,6],[2162,6]]},"17":{"position":[[11,6]]},"18":{"position":[[44,8],[77,7]]},"19":{"position":[[64,6],[122,7]]},"20":{"position":[[828,6],[1718,6],[1727,6],[1844,6],[2533,7],[2977,7]]},"22":{"position":[[1173,7],[1660,6],[1711,6],[2649,6],[2757,8]]},"24":{"position":[[186,7],[267,6],[741,6],[1067,7],[1581,6]]},"25":{"position":[[457,6],[787,7],[1301,6]]},"28":{"position":[[1149,6],[1182,6],[1701,6],[1816,6],[2946,6],[2986,6],[3487,6],[3568,6]]},"30":{"position":[[1521,6],[1554,6],[1907,6],[3316,6],[4791,6],[4831,6],[5166,6],[6384,6],[9031,6]]},"34":{"position":[[1336,6],[1527,6],[2668,6]]},"39":{"position":[[717,6],[975,6],[2118,6],[3022,6],[3268,6]]},"40":{"position":[[3542,7]]},"45":{"position":[[2142,6],[2922,6]]},"51":{"position":[[3715,6],[3789,6],[3863,6],[4008,6],[4193,6]]},"52":{"position":[[1139,6]]},"62":{"position":[[897,6],[1127,6]]},"70":{"position":[[1001,6]]},"76":{"position":[[451,6],[791,6],[1772,6],[3270,6],[3319,6]]},"88":{"position":[[645,9],[902,6],[1400,6]]},"90":{"position":[[3960,6]]},"91":{"position":[[3049,6],[3302,6]]},"92":{"position":[[861,6],[1114,6],[1533,8]]},"93":{"position":[[221,7],[2879,6],[4060,9],[4317,6]]},"96":{"position":[[487,6]]},"97":{"position":[[1298,7],[1669,7],[3504,6],[5548,8]]},"103":{"position":[[1460,6]]},"105":{"position":[[806,6],[835,6],[1115,6],[1607,6]]},"125":{"position":[[4345,8]]},"188":{"position":[[1037,6],[1140,6],[1272,6],[1435,6],[3576,6],[3597,6]]},"189":{"position":[[1126,6],[1202,6],[1396,6],[1472,6],[3120,6],[3129,6]]},"196":{"position":[[787,8]]},"199":{"position":[[248,6],[410,6]]}},"keywords":{}}],["returns[tick].mean",{"_index":729,"title":{},"content":{"18":{"position":[[161,20]]},"20":{"position":[[1414,21]]}},"keywords":{}}],["returns_a",{"_index":817,"title":{},"content":{"20":{"position":[[1371,9],[1904,10]]}},"keywords":{}}],["reveal",{"_index":4274,"title":{},"content":{"129":{"position":[[18,6]]}},"keywords":{}}],["revel",{"_index":4276,"title":{},"content":{"129":{"position":[[47,10],[802,11]]}},"keywords":{}}],["review",{"_index":2209,"title":{},"content":{"53":{"position":[[404,6]]}},"keywords":{}}],["rewind",{"_index":4979,"title":{},"content":{"174":{"position":[[252,6]]}},"keywords":{}}],["rewir",{"_index":150,"title":{},"content":{"3":{"position":[[375,8]]}},"keywords":{}}],["rewrit",{"_index":3997,"title":{},"content":{"124":{"position":[[328,7]]}},"keywords":{}}],["rich",{"_index":4653,"title":{},"content":{"160":{"position":[[330,4]]}},"keywords":{}}],["rid",{"_index":2518,"title":{},"content":{"65":{"position":[[1468,3]]}},"keywords":{}}],["ride",{"_index":1812,"title":{},"content":{"40":{"position":[[1575,6]]}},"keywords":{}}],["right",{"_index":160,"title":{},"content":{"3":{"position":[[538,5]]},"4":{"position":[[467,5]]},"24":{"position":[[3399,6]]},"26":{"position":[[437,6]]},"32":{"position":[[334,6],[2235,5]]},"38":{"position":[[761,5]]},"53":{"position":[[1068,5]]},"57":{"position":[[11,6]]},"70":{"position":[[435,7],[609,7]]},"71":{"position":[[535,7],[709,7]]},"74":{"position":[[704,7]]},"91":{"position":[[3772,5]]},"96":{"position":[[414,6],[819,6],[1453,6]]},"115":{"position":[[687,6]]},"116":{"position":[[706,6]]},"118":{"position":[[94,5]]},"121":{"position":[[1443,6]]},"124":{"position":[[64,6]]},"127":{"position":[[80,5]]},"129":{"position":[[144,6],[608,5]]},"175":{"position":[[82,6]]},"196":{"position":[[1392,5]]}},"keywords":{}}],["rigor",{"_index":1707,"title":{},"content":{"39":{"position":[[29,8]]},"160":{"position":[[4489,10]]},"176":{"position":[[1494,8]]}},"keywords":{}}],["rip",{"_index":4285,"title":{},"content":{"129":{"position":[[561,4]]},"183":{"position":[[397,4],[543,4]]}},"keywords":{}}],["risk",{"_index":556,"title":{},"content":{"13":{"position":[[474,4]]},"14":{"position":[[527,4]]}},"keywords":{}}],["roadmap",{"_index":3990,"title":{"124":{"position":[[0,7]]}},"content":{},"keywords":{}}],["roadmap/issues/16",{"_index":3746,"title":{},"content":{"113":{"position":[[1219,17]]}},"keywords":{}}],["rock",{"_index":3844,"title":{},"content":{"118":{"position":[[294,5]]}},"keywords":{}}],["roman",{"_index":2224,"title":{},"content":{"53":{"position":[[697,5]]}},"keywords":{}}],["room",{"_index":4753,"title":{},"content":{"161":{"position":[[1293,4]]}},"keywords":{}}],["roughli",{"_index":5195,"title":{},"content":{"188":{"position":[[2763,7]]}},"keywords":{}}],["round",{"_index":373,"title":{},"content":{"6":{"position":[[1087,6]]},"74":{"position":[[1436,8]]}},"keywords":{}}],["roundabout",{"_index":4334,"title":{},"content":{"130":{"position":[[18,10]]}},"keywords":{}}],["rout",{"_index":3368,"title":{},"content":{"97":{"position":[[934,7],[3071,6]]},"98":{"position":[[47,7]]},"101":{"position":[[428,6]]},"175":{"position":[[1,8],[371,5],[534,7]]}},"keywords":{}}],["router",{"_index":3366,"title":{},"content":{"97":{"position":[[773,6],[1082,6],[3803,9],[4009,6],[4023,6],[6381,6]]}},"keywords":{}}],["router.get("/"",{"_index":3407,"title":{},"content":{"97":{"position":[[3880,25],[4413,25],[4844,25]]}},"keywords":{}}],["routers/switch",{"_index":5026,"title":{},"content":{"175":{"position":[[1088,16]]}},"keywords":{}}],["row",{"_index":1000,"title":{},"content":{"23":{"position":[[272,4]]},"24":{"position":[[1181,3]]},"25":{"position":[[901,3]]},"75":{"position":[[1178,4]]},"91":{"position":[[4125,3]]},"102":{"position":[[1038,4]]}},"keywords":{}}],["row[1][0",{"_index":1060,"title":{},"content":{"24":{"position":[[1238,9]]},"25":{"position":[[958,9]]}},"keywords":{}}],["row[1][1",{"_index":1058,"title":{},"content":{"24":{"position":[[1216,9]]},"25":{"position":[[936,9]]}},"keywords":{}}],["row_dt",{"_index":1057,"title":{},"content":{"24":{"position":[[1207,6]]},"25":{"position":[[927,6]]}},"keywords":{}}],["row_dt.day",{"_index":1064,"title":{},"content":{"24":{"position":[[1295,11]]},"25":{"position":[[1015,11]]}},"keywords":{}}],["row_dt.month",{"_index":1063,"title":{},"content":{"24":{"position":[[1281,13]]},"25":{"position":[[1001,13]]}},"keywords":{}}],["row_valu",{"_index":1059,"title":{},"content":{"24":{"position":[[1226,9],[1364,10],[1411,10],[1458,10]]},"25":{"position":[[946,9],[1084,10],[1131,10],[1178,10]]}},"keywords":{}}],["rs",{"_index":4043,"title":{},"content":{"125":{"position":[[1322,3]]}},"keywords":{}}],["rsi",{"_index":4287,"title":{},"content":{"129":{"position":[[586,4]]},"193":{"position":[[1272,5]]},"197":{"position":[[1036,5]]}},"keywords":{}}],["rsp",{"_index":4258,"title":{},"content":{"128":{"position":[[465,3],[473,4],[777,3],[1530,4],[1598,6],[1613,4]]},"129":{"position":[[531,4],[548,3],[685,3],[723,4]]},"192":{"position":[[283,5],[688,4]]},"193":{"position":[[501,4],[1135,5],[1661,5]]}},"keywords":{}}],["rss",{"_index":3437,"title":{},"content":{"98":{"position":[[159,3]]}},"keywords":{}}],["rubbl",{"_index":3859,"title":{},"content":{"120":{"position":[[717,6]]}},"keywords":{}}],["rule",{"_index":173,"title":{},"content":{"3":{"position":[[777,6]]},"90":{"position":[[385,6],[454,5]]},"98":{"position":[[662,5]]},"121":{"position":[[2273,4]]},"159":{"position":[[363,5]]},"193":{"position":[[379,5]]},"196":{"position":[[1,5]]}},"keywords":{}}],["run",{"_index":289,"title":{"24":{"position":[[0,7]]},"34":{"position":[[0,7]]},"39":{"position":[[0,7]]},"103":{"position":[[0,7]]},"112":{"position":[[8,7]]},"134":{"position":[[0,7]]}},"content":{"4":{"position":[[1326,7]]},"8":{"position":[[20,3]]},"12":{"position":[[610,3],[656,3]]},"34":{"position":[[1382,3],[3040,3]]},"38":{"position":[[1291,3]]},"41":{"position":[[240,3]]},"43":{"position":[[387,3]]},"45":{"position":[[1802,7]]},"46":{"position":[[668,7]]},"57":{"position":[[472,7]]},"86":{"position":[[293,7]]},"91":{"position":[[4004,7]]},"98":{"position":[[971,3]]},"102":{"position":[[1082,3]]},"103":{"position":[[157,3],[1561,7]]},"106":{"position":[[263,3]]},"112":{"position":[[127,3],[562,7],[632,7]]},"123":{"position":[[668,7]]},"125":{"position":[[746,8],[1068,3],[2769,7],[2937,7],[2985,7],[6847,4],[7192,4],[8149,3],[8325,7],[8378,7],[8932,8],[11212,7]]},"127":{"position":[[1444,3]]},"129":{"position":[[2570,3],[2796,3]]},"147":{"position":[[399,3]]},"153":{"position":[[459,7]]},"160":{"position":[[2054,7],[3088,4],[3186,8],[3608,3],[3686,3],[3746,3]]},"167":{"position":[[112,3],[206,4]]},"172":{"position":[[819,7],[1264,3]]},"173":{"position":[[54,7],[576,3],[753,3],[1908,7]]},"174":{"position":[[833,7]]},"176":{"position":[[1268,3]]},"188":{"position":[[607,4],[1219,7],[1402,7],[1821,4],[1836,7],[1918,3],[2053,3],[2403,3],[2804,7],[3217,8],[3325,7],[3875,3],[4521,3]]},"189":{"position":[[310,8],[683,8],[1213,3],[1730,4],[1901,3],[1987,7],[2347,3]]},"190":{"position":[[146,7],[561,7]]},"196":{"position":[[773,3],[1112,7]]}},"keywords":{}}],["run().expect("compil",{"_index":3705,"title":{},"content":{"111":{"position":[[449,29]]}},"keywords":{}}],["runtim",{"_index":3693,"title":{},"content":{"109":{"position":[[547,7],[574,8]]},"125":{"position":[[4974,7]]},"188":{"position":[[3290,7]]},"189":{"position":[[177,8]]},"190":{"position":[[802,8]]}},"keywords":{}}],["russ",{"_index":1009,"title":{},"content":{"23":{"position":[[498,4]]},"24":{"position":[[2513,4],[2665,4]]},"25":{"position":[[2236,4],[2388,4]]}},"keywords":{}}],["russ_close_ret",{"_index":1144,"title":{},"content":{"25":{"position":[[557,14],[1469,15]]}},"keywords":{}}],["russ_open_ret",{"_index":1042,"title":{},"content":{"24":{"position":[[839,13],[1747,14]]}},"keywords":{}}],["russel",{"_index":995,"title":{},"content":{"23":{"position":[[133,7]]},"24":{"position":[[3059,7],[3370,7],[3503,7]]},"26":{"position":[[605,7]]},"93":{"position":[[1215,7],[2935,7],[3074,7]]}},"keywords":{}}],["rust",{"_index":3308,"title":{"109":{"position":[[31,4]]},"119":{"position":[[35,4]]},"125":{"position":[[29,4]]},"126":{"position":[[14,4]]},"151":{"position":[[15,5]]},"154":{"position":[[15,5]]},"159":{"position":[[15,5]]},"160":{"position":[[15,5]]},"177":{"position":[[15,5]]},"191":{"position":[[15,5]]}},"content":{"95":{"position":[[246,5]]},"96":{"position":[[12,4],[214,4],[572,4],[1818,4]]},"97":{"position":[[133,5],[306,4],[367,4],[455,4],[970,4],[2563,4],[2723,4],[4163,4],[5254,4]]},"98":{"position":[[325,4],[338,4],[736,5],[1066,4],[1158,4]]},"109":{"position":[[68,4],[491,4]]},"111":{"position":[[96,4]]},"112":{"position":[[1347,4]]},"115":{"position":[[48,4],[518,4],[852,4],[3029,4]]},"116":{"position":[[656,4],[2848,4]]},"117":{"position":[[61,4],[1904,4]]},"120":{"position":[[1128,5]]},"121":{"position":[[162,5],[183,4],[271,5],[849,4],[1992,4],[2529,5]]},"122":{"position":[[6,4],[164,4],[581,5],[1187,5]]},"124":{"position":[[307,4]]},"125":{"position":[[3771,4],[6116,4],[6537,4],[7229,4],[7312,5],[7322,4],[7752,4],[7868,4],[9697,5],[9931,4],[11327,4],[11695,4]]},"127":{"position":[[516,4],[1517,4]]},"128":{"position":[[1036,4],[1099,5],[1640,4],[1840,5]]},"129":{"position":[[87,4],[319,4],[1648,4],[2767,5]]},"130":{"position":[[66,4],[387,4]]},"132":{"position":[[526,4]]},"133":{"position":[[47,4],[135,4]]},"139":{"position":[[176,4],[836,5]]},"140":{"position":[[63,4]]},"148":{"position":[[244,4],[454,4]]},"152":{"position":[[356,4],[1684,4]]},"153":{"position":[[268,5],[1055,4]]},"156":{"position":[[201,4],[1744,4]]},"157":{"position":[[144,4]]},"158":{"position":[[275,4]]},"159":{"position":[[300,4]]},"160":{"position":[[269,4],[350,4],[646,4],[827,5],[957,4],[1237,4],[1333,4],[1538,4],[1755,5],[2257,4],[2424,4],[3438,4],[3573,4],[3756,4],[4417,4],[4458,4]]},"164":{"position":[[134,4],[179,4]]},"165":{"position":[[538,5],[1139,4]]},"166":{"position":[[597,4]]},"172":{"position":[[1038,4],[1189,6],[1503,4]]},"179":{"position":[[69,4],[229,4],[749,4],[1173,4],[1613,4]]},"184":{"position":[[385,4],[734,4],[1167,4]]},"185":{"position":[[529,4],[863,4]]},"186":{"position":[[115,5],[670,4]]},"193":{"position":[[706,4]]},"194":{"position":[[109,4]]},"195":{"position":[[152,4],[848,4],[974,4]]},"196":{"position":[[394,5],[1290,4]]},"197":{"position":[[11,4]]},"198":{"position":[[52,4],[80,4]]},"199":{"position":[[806,5]]}},"keywords":{}}],["rust"",{"_index":3342,"title":{},"content":{"96":{"position":[[1415,11]]}},"keywords":{}}],["rust'",{"_index":3356,"title":{},"content":{"97":{"position":[[1,6],[5475,6],[6448,6]]},"130":{"position":[[449,6]]},"160":{"position":[[833,6]]},"164":{"position":[[710,6]]}},"keywords":{}}],["rust.git",{"_index":4075,"title":{},"content":{"125":{"position":[[3099,8]]}},"keywords":{}}],["rustdoesn't",{"_index":4669,"title":{},"content":{"160":{"position":[[1045,11]]}},"keywords":{}}],["rusti",{"_index":38,"title":{},"content":{"1":{"position":[[432,6]]}},"keywords":{}}],["rustic",{"_index":3297,"title":{"94":{"position":[[2,6]]}},"content":{},"keywords":{}}],["rv:46.0",{"_index":3227,"title":{},"content":{"93":{"position":[[2395,8]]}},"keywords":{}}],["rwlock",{"_index":4607,"title":{},"content":{"157":{"position":[[373,7]]}},"keywords":{}}],["rwlockmutex",{"_index":4564,"title":{},"content":{"155":{"position":[[719,11]]}},"keywords":{}}],["r−qr",{"_index":331,"title":{},"content":{"6":{"position":[[441,4]]}},"keywords":{}}],["r−rmσ{r",{"_index":736,"title":{},"content":{"19":{"position":[[9,7]]}},"keywords":{}}],["s",{"_index":784,"title":{},"content":{"20":{"position":[[675,3]]},"93":{"position":[[2575,1]]},"188":{"position":[[2591,3]]},"189":{"position":[[1795,3]]},"195":{"position":[[572,2]]},"199":{"position":[[1280,1],[1356,1],[1423,1],[1512,1],[1581,1],[1692,1]]}},"keywords":{}}],["s&p",{"_index":991,"title":{},"content":{"23":{"position":[[92,7]]},"24":{"position":[[2608,7],[2840,7],[3076,7],[3354,7],[3491,7]]},"25":{"position":[[2331,7],[2563,7]]},"26":{"position":[[593,7]]}},"keywords":{}}],["s.d."",{"_index":3001,"title":{},"content":{"90":{"position":[[1629,11],[1778,11],[2922,11]]}},"keywords":{}}],["s.mount('http",{"_index":3236,"title":{},"content":{"93":{"position":[[2647,18]]}},"keywords":{}}],["s.t",{"_index":776,"title":{},"content":{"20":{"position":[[537,7],[615,5],[768,4]]}},"keywords":{}}],["s/.*instantiatestreaming.*//g",{"_index":4126,"title":{},"content":{"125":{"position":[[5634,31]]}},"keywords":{}}],["s0",{"_index":351,"title":{},"content":{"6":{"position":[[766,2],[902,2]]},"7":{"position":[[386,2]]},"8":{"position":[[99,2]]},"11":{"position":[[360,2]]},"12":{"position":[[313,2],[361,2]]},"13":{"position":[[534,2],[546,2],[570,2]]},"14":{"position":[[1351,2],[1371,2],[1400,2]]},"15":{"position":[[720,2],[740,2],[769,2]]}},"keywords":{}}],["s0s_0s0",{"_index":318,"title":{},"content":{"6":{"position":[[287,8]]}},"keywords":{}}],["sa",{"_index":912,"title":{},"content":{"22":{"position":[[856,2],[2348,2]]}},"keywords":{}}],["sacrif",{"_index":3650,"title":{},"content":{"106":{"position":[[366,11]]}},"keywords":{}}],["sacrific",{"_index":3485,"title":{},"content":{"101":{"position":[[823,10]]},"104":{"position":[[1014,10]]}},"keywords":{}}],["safe",{"_index":2363,"title":{},"content":{"61":{"position":[[1111,5]]},"97":{"position":[[5787,4]]},"115":{"position":[[530,6],[681,5],[1232,6],[1612,6],[1889,6],[2437,6],[2690,7]]},"116":{"position":[[1184,6],[1517,6],[1794,6],[2295,6],[2700,4],[2938,4],[3001,4],[3150,5],[3189,5]]},"117":{"position":[[349,4],[970,4],[1565,4]]},"143":{"position":[[115,5]]},"155":{"position":[[1090,4]]},"178":{"position":[[177,4]]},"182":{"position":[[650,4]]},"184":{"position":[[1103,6]]},"185":{"position":[[134,4],[784,6]]},"186":{"position":[[110,4]]},"188":{"position":[[406,4],[899,4],[4336,6],[4432,4]]},"189":{"position":[[3008,5]]},"195":{"position":[[147,4]]}},"keywords":{}}],["safe_cover(cary_forecast[x]['curr",{"_index":1358,"title":{},"content":{"30":{"position":[[1771,42],[3120,42]]}},"keywords":{}}],["safe_cover(forecasts_df[city][x]['curr",{"_index":1246,"title":{},"content":{"28":{"position":[[1405,47]]}},"keywords":{}}],["safe_cover(fram",{"_index":1236,"title":{},"content":{"28":{"position":[[1094,18]]},"30":{"position":[[1466,18]]}},"keywords":{}}],["safe_float(self",{"_index":946,"title":{},"content":{"22":{"position":[[1629,16]]}},"keywords":{}}],["safe_precip(cary_forecast[x]['curr",{"_index":1405,"title":{},"content":{"30":{"position":[[5039,43],[6188,43]]}},"keywords":{}}],["safe_precip(forecasts_df[city][x]['curr",{"_index":1300,"title":{},"content":{"28":{"position":[[3200,48]]}},"keywords":{}}],["safe_precip(fram",{"_index":1295,"title":{},"content":{"28":{"position":[[2883,19]]},"30":{"position":[[4728,19]]}},"keywords":{}}],["safeguard",{"_index":1608,"title":{},"content":{"34":{"position":[[1157,9]]}},"keywords":{}}],["safeti",{"_index":3358,"title":{},"content":{"97":{"position":[[65,6],[157,7]]},"117":{"position":[[649,6]]}},"keywords":{}}],["saltiel",{"_index":2959,"title":{},"content":{"89":{"position":[[928,7]]}},"keywords":{}}],["same",{"_index":153,"title":{},"content":{"3":{"position":[[425,4]]},"12":{"position":[[149,5]]},"14":{"position":[[1196,4]]},"15":{"position":[[622,5]]},"28":{"position":[[131,4],[4001,4]]},"34":{"position":[[3619,4]]},"38":{"position":[[956,4]]},"40":{"position":[[2478,4]]},"45":{"position":[[3345,5]]},"53":{"position":[[791,4]]},"69":{"position":[[356,4]]},"71":{"position":[[1104,4]]},"89":{"position":[[353,4]]},"91":{"position":[[4959,4],[5403,4],[5931,4]]},"96":{"position":[[856,4]]},"97":{"position":[[1820,4]]},"101":{"position":[[513,4],[750,5]]},"102":{"position":[[200,4]]},"103":{"position":[[1670,4]]},"105":{"position":[[3063,4]]},"111":{"position":[[219,4]]},"112":{"position":[[1338,4]]},"116":{"position":[[898,4]]},"121":{"position":[[339,4],[494,4],[515,4],[1208,4]]},"125":{"position":[[725,4]]},"129":{"position":[[1588,4],[1779,4]]},"136":{"position":[[869,4]]},"156":{"position":[[1801,4]]},"160":{"position":[[2611,4]]},"163":{"position":[[2307,4]]},"165":{"position":[[147,4]]},"169":{"position":[[168,4]]},"172":{"position":[[813,5]]},"176":{"position":[[1348,4]]},"178":{"position":[[348,4]]},"182":{"position":[[521,4]]},"188":{"position":[[1798,4],[3317,4]]},"189":{"position":[[912,4],[1657,4]]},"196":{"position":[[430,4],[682,4]]}},"keywords":{}}],["sampl",{"_index":444,"title":{},"content":{"8":{"position":[[26,6]]},"12":{"position":[[180,6]]},"30":{"position":[[3783,9],[4208,7],[6862,9]]},"103":{"position":[[400,6],[999,7]]},"105":{"position":[[609,6]]},"199":{"position":[[92,8]]}},"keywords":{}}],["sampler",{"_index":3514,"title":{},"content":{"103":{"position":[[505,11],[565,10],[611,10]]}},"keywords":{}}],["sandwich",{"_index":4758,"title":{},"content":{"161":{"position":[[1735,9]]}},"keywords":{}}],["saniti",{"_index":3544,"title":{},"content":{"103":{"position":[[1985,6]]},"125":{"position":[[6889,6]]}},"keywords":{}}],["santand",{"_index":1858,"title":{"42":{"position":[[11,9]]}},"content":{},"keywords":{}}],["satisfact",{"_index":1909,"title":{},"content":{"44":{"position":[[442,13]]},"46":{"position":[[199,13]]}},"keywords":{}}],["satisfi",{"_index":1880,"title":{},"content":{"43":{"position":[[763,9]]},"44":{"position":[[1161,9],[1568,9]]},"46":{"position":[[547,10]]},"97":{"position":[[2045,9]]},"115":{"position":[[995,9],[1342,9],[1714,9],[2083,9]]},"116":{"position":[[994,9],[1294,9],[1619,9],[1988,9]]}},"keywords":{}}],["satisfied"",{"_index":1951,"title":{},"content":{"44":{"position":[[1725,15]]}},"keywords":{}}],["save",{"_index":273,"title":{},"content":{"4":{"position":[[999,5]]},"74":{"position":[[899,4]]},"97":{"position":[[2178,4]]},"101":{"position":[[881,4]]},"102":{"position":[[293,4]]},"106":{"position":[[207,4],[347,4]]},"121":{"position":[[2711,4]]}},"keywords":{}}],["saw",{"_index":119,"title":{},"content":{"2":{"position":[[685,3]]},"28":{"position":[[4152,3]]},"40":{"position":[[1408,3]]},"88":{"position":[[12,3]]}},"keywords":{}}],["say",{"_index":1967,"title":{},"content":{"45":{"position":[[419,6]]},"104":{"position":[[1146,6]]},"160":{"position":[[4156,6]]}},"keywords":{}}],["sayher",{"_index":4066,"title":{},"content":{"125":{"position":[[2654,7]]}},"keywords":{}}],["sbe",{"_index":4836,"title":{},"content":{"166":{"position":[[13,3],[244,3],[466,3],[610,3]]},"168":{"position":[[327,3]]},"169":{"position":[[438,3]]},"170":{"position":[[160,3],[196,3]]}},"keywords":{}}],["sbe'",{"_index":4849,"title":{},"content":{"166":{"position":[[769,5]]}},"keywords":{}}],["scalar",{"_index":4460,"title":{},"content":{"145":{"position":[[343,7]]},"184":{"position":[[103,6]]}},"keywords":{}}],["scalars,struct",{"_index":5058,"title":{},"content":{"178":{"position":[[93,16]]}},"keywords":{}}],["scale",{"_index":11,"title":{},"content":{"1":{"position":[[93,6]]},"20":{"position":[[2436,6]]},"33":{"position":[[1010,5],[1232,5]]},"82":{"position":[[88,5]]},"98":{"position":[[117,5]]},"170":{"position":[[391,6]]}},"keywords":{}}],["scari",{"_index":2550,"title":{},"content":{"66":{"position":[[634,5]]}},"keywords":{}}],["scatter",{"_index":1885,"title":{},"content":{"43":{"position":[[1051,7]]}},"keywords":{}}],["scenario",{"_index":1585,"title":{},"content":{"33":{"position":[[1049,9]]},"69":{"position":[[288,9]]},"77":{"position":[[30,9],[116,8]]}},"keywords":{}}],["schedul",{"_index":4941,"title":{},"content":{"173":{"position":[[319,11],[362,8],[607,10],[862,10]]}},"keywords":{}}],["schema",{"_index":3661,"title":{"110":{"position":[[24,7]]}},"content":{"108":{"position":[[50,6]]},"110":{"position":[[57,6],[250,6],[354,6],[364,6]]},"111":{"position":[[194,6],[570,6],[618,6],[764,6]]},"112":{"position":[[1145,6]]},"113":{"position":[[73,6],[2165,7]]},"163":{"position":[[128,6]]},"166":{"position":[[718,7]]},"168":{"position":[[153,6]]},"169":{"position":[[267,6]]}},"keywords":{}}],["schema"",{"_index":3706,"title":{},"content":{"111":{"position":[[479,14]]}},"keywords":{}}],["scheme",{"_index":3456,"title":{"100":{"position":[[44,7]]},"102":{"position":[[24,7]]}},"content":{"100":{"position":[[445,6]]},"102":{"position":[[700,6],[1489,6]]},"104":{"position":[[1705,7]]}},"keywords":{}}],["scienc",{"_index":2313,"title":{},"content":{"57":{"position":[[299,7]]}},"keywords":{}}],["scientist",{"_index":2032,"title":{},"content":{"46":{"position":[[382,10]]}},"keywords":{}}],["scientist"",{"_index":4503,"title":{},"content":{"150":{"position":[[778,15]]}},"keywords":{}}],["scikit",{"_index":3503,"title":{},"content":{"103":{"position":[[132,6]]}},"keywords":{}}],["scipy.io",{"_index":3512,"title":{},"content":{"103":{"position":[[481,8]]}},"keywords":{}}],["scipy.optim",{"_index":803,"title":{},"content":{"20":{"position":[[1026,14]]}},"keywords":{}}],["scope",{"_index":2355,"title":{},"content":{"61":{"position":[[416,7],[1607,6],[1635,8]]},"97":{"position":[[1417,5],[1730,6]]},"98":{"position":[[654,7]]},"155":{"position":[[107,5],[1148,5]]}},"keywords":{}}],["score",{"_index":1693,"title":{},"content":{"38":{"position":[[515,5],[699,7],[1235,7]]},"40":{"position":[[517,5],[855,5],[987,6],[2053,5],[2407,5],[2997,5],[3107,6]]},"76":{"position":[[26,5],[2532,5],[2967,6]]},"78":{"position":[[906,5]]},"82":{"position":[[281,5],[351,5],[421,5],[491,5],[561,5],[631,5],[701,5],[771,5],[841,5],[912,5]]}},"keywords":{}}],["score(data",{"_index":2727,"title":{},"content":{"76":{"position":[[2069,11],[2647,11]]}},"keywords":{}}],["score(x",{"_index":2686,"title":{},"content":{"76":{"position":[[468,8]]}},"keywords":{}}],["scratch",{"_index":4191,"title":{},"content":{"125":{"position":[[9758,8]]}},"keywords":{}}],["screen",{"_index":4033,"title":{},"content":{"125":{"position":[[952,6]]}},"keywords":{}}],["script",{"_index":4112,"title":{},"content":{"125":{"position":[[5196,7],[6678,6],[6840,6]]},"167":{"position":[[102,6]]}},"keywords":{}}],["scriptprestart",{"_index":4139,"title":{},"content":{"125":{"position":[[6436,14]]}},"keywords":{}}],["scriptto",{"_index":4134,"title":{},"content":{"125":{"position":[[6307,8]]}},"keywords":{}}],["search",{"_index":97,"title":{},"content":{"2":{"position":[[354,9]]},"76":{"position":[[1234,6]]},"190":{"position":[[868,6]]},"199":{"position":[[1150,6]]}},"keywords":{}}],["season",{"_index":2312,"title":{},"content":{"57":{"position":[[215,7]]}},"keywords":{}}],["seattl",{"_index":1192,"title":{"27":{"position":[[10,7]]}},"content":{"28":{"position":[[254,7],[506,7],[791,7],[1020,10],[2537,8],[4175,8]]},"29":{"position":[[66,7],[185,7]]},"30":{"position":[[8657,10],[10219,7]]}},"keywords":{}}],["seattle_loc",{"_index":1456,"title":{},"content":{"30":{"position":[[8535,11],[8668,12]]}},"keywords":{}}],["second",{"_index":134,"title":{},"content":{"3":{"position":[[15,6]]},"38":{"position":[[800,6]]},"40":{"position":[[2459,7]]},"52":{"position":[[193,6],[414,7]]},"57":{"position":[[89,6]]},"83":{"position":[[295,7]]},"85":{"position":[[116,6]]},"88":{"position":[[1713,6]]},"91":{"position":[[2729,6]]},"92":{"position":[[541,6]]},"97":{"position":[[5960,6]]},"103":{"position":[[586,7],[631,6],[1259,7]]},"106":{"position":[[517,7]]},"121":{"position":[[2183,8]]},"123":{"position":[[475,6],[682,7],[772,7]]},"125":{"position":[[7207,7]]},"127":{"position":[[460,7]]},"139":{"position":[[584,7]]},"161":{"position":[[1268,6]]},"165":{"position":[[1036,7]]},"173":{"position":[[719,7]]},"176":{"position":[[1094,7]]},"179":{"position":[[1092,6],[1196,6]]},"188":{"position":[[2363,6],[3180,6],[4144,7]]},"189":{"position":[[342,6]]},"190":{"position":[[440,7]]}},"keywords":{}}],["secret",{"_index":1464,"title":{},"content":{"30":{"position":[[8735,6]]},"60":{"position":[[115,6],[159,6],[201,7]]},"88":{"position":[[256,7]]},"93":{"position":[[3805,7]]}},"keywords":{}}],["section",{"_index":2455,"title":{},"content":{"64":{"position":[[377,7]]},"104":{"position":[[1526,8]]},"172":{"position":[[2662,9]]},"197":{"position":[[363,7],[509,7]]}},"keywords":{}}],["sector",{"_index":3194,"title":{},"content":{"93":{"position":[[825,7]]}},"keywords":{}}],["secur",{"_index":2366,"title":{},"content":{"61":{"position":[[1240,7]]},"195":{"position":[[882,8]]}},"keywords":{}}],["sed",{"_index":4125,"title":{},"content":{"125":{"position":[[5627,3]]}},"keywords":{}}],["see",{"_index":167,"title":{},"content":{"3":{"position":[[647,6]]},"4":{"position":[[479,6]]},"8":{"position":[[47,3]]},"22":{"position":[[1264,3]]},"25":{"position":[[129,3]]},"30":{"position":[[2270,3],[5534,3],[7111,3],[9229,4],[9261,3]]},"39":{"position":[[63,3],[1803,3]]},"40":{"position":[[88,3],[625,6],[2470,3],[3064,3]]},"41":{"position":[[356,3],[605,3]]},"43":{"position":[[230,3]]},"44":{"position":[[130,3],[390,3]]},"57":{"position":[[647,4]]},"69":{"position":[[82,3]]},"70":{"position":[[1269,3]]},"71":{"position":[[1041,3]]},"73":{"position":[[44,3],[470,3]]},"74":{"position":[[80,6],[809,6]]},"77":{"position":[[44,3]]},"83":{"position":[[33,3]]},"88":{"position":[[2220,4],[2406,3],[3568,3]]},"90":{"position":[[4955,3]]},"91":{"position":[[1417,3]]},"92":{"position":[[1479,3]]},"95":{"position":[[290,3]]},"96":{"position":[[992,3]]},"105":{"position":[[2535,4]]},"106":{"position":[[1000,6]]},"112":{"position":[[98,3],[171,3],[326,3],[873,3]]},"116":{"position":[[2627,6]]},"125":{"position":[[244,4],[8836,3],[11232,4]]},"127":{"position":[[1615,3]]},"134":{"position":[[225,3],[357,3]]},"135":{"position":[[329,3],[565,4]]},"136":{"position":[[1,4],[187,3]]},"152":{"position":[[602,3]]},"160":{"position":[[115,3]]},"173":{"position":[[1286,4]]},"176":{"position":[[252,6]]},"181":{"position":[[141,3],[263,3]]},"193":{"position":[[862,3]]}},"keywords":{}}],["seek",{"_index":875,"title":{"22":{"position":[[30,7]]}},"content":{},"keywords":{}}],["seem",{"_index":1283,"title":{},"content":{"28":{"position":[[2429,5],[2788,5],[4042,5],[4121,5]]},"30":{"position":[[2450,5],[2654,5],[4008,5],[7598,5]]},"41":{"position":[[131,4]]},"45":{"position":[[3484,5]]},"46":{"position":[[56,5]]},"50":{"position":[[81,5]]},"58":{"position":[[406,5]]},"97":{"position":[[6467,5]]},"165":{"position":[[1077,5]]},"170":{"position":[[352,5]]}},"keywords":{}}],["seen",{"_index":1290,"title":{},"content":{"28":{"position":[[2693,4]]},"58":{"position":[[217,4],[459,4],[496,4]]},"71":{"position":[[59,4]]},"72":{"position":[[479,4]]},"83":{"position":[[182,4],[326,4]]},"91":{"position":[[5950,4]]},"105":{"position":[[10,4]]},"106":{"position":[[1052,4]]}},"keywords":{}}],["seethi",{"_index":3923,"title":{},"content":{"121":{"position":[[2483,7]]}},"keywords":{}}],["segment",{"_index":4817,"title":{},"content":{"164":{"position":[[1413,7]]}},"keywords":{}}],["select",{"_index":1861,"title":{},"content":{"43":{"position":[[118,9]]},"45":{"position":[[1715,8]]},"51":{"position":[[2847,6],[2891,6],[2946,6],[3150,9]]},"76":{"position":[[2847,6]]}},"keywords":{}}],["self.articles.append(href",{"_index":900,"title":{},"content":{"22":{"position":[[569,26]]}},"keywords":{}}],["self.count",{"_index":955,"title":{},"content":{"22":{"position":[[1906,12],[1974,12],[2046,12],[2117,12],[2187,12],[2251,12]]}},"keywords":{}}],["self.dat",{"_index":3205,"title":{},"content":{"93":{"position":[[1616,10]]}},"keywords":{}}],["self.data",{"_index":936,"title":{},"content":{"22":{"position":[[1348,9]]}},"keywords":{}}],["self.data['crud",{"_index":961,"title":{},"content":{"22":{"position":[[2136,18]]}},"keywords":{}}],["self.data['d",{"_index":943,"title":{},"content":{"22":{"position":[[1567,17]]}},"keywords":{}}],["self.data['dow",{"_index":956,"title":{},"content":{"22":{"position":[[1925,16]]}},"keywords":{}}],["self.data['gold",{"_index":962,"title":{},"content":{"22":{"position":[[2206,17]]}},"keywords":{}}],["self.data['nasdaq",{"_index":960,"title":{},"content":{"22":{"position":[[2065,19]]}},"keywords":{}}],["self.data['s&p",{"_index":959,"title":{},"content":{"22":{"position":[[1993,20]]}},"keywords":{}}],["self.dates.append(match.group(0",{"_index":3209,"title":{},"content":{"93":{"position":[[1813,33]]}},"keywords":{}}],["self.earnings_offset",{"_index":3215,"title":{},"content":{"93":{"position":[[2072,20],[2141,20]]}},"keywords":{}}],["self.fetch_link",{"_index":893,"title":{},"content":{"22":{"position":[[422,16]]}},"keywords":{}}],["self.in_font_tag",{"_index":944,"title":{},"content":{"22":{"position":[[1592,16],[1885,17],[2299,16]]}},"keywords":{}}],["self.messag",{"_index":3404,"title":{},"content":{"97":{"position":[[3743,15],[5091,15],[5349,12],[5690,13]]}},"keywords":{}}],["self.message.clon",{"_index":3432,"title":{},"content":{"97":{"position":[[6087,23]]}},"keywords":{}}],["self.record_font_tag",{"_index":952,"title":{},"content":{"22":{"position":[[1764,21],[1827,21],[1859,21]]}},"keywords":{}}],["self.safe_float(cont",{"_index":957,"title":{},"content":{"22":{"position":[[1944,24],[2016,24],[2087,24],[2157,24],[2226,24]]}},"keywords":{}}],["self.store_d",{"_index":3207,"title":{},"content":{"93":{"position":[[1690,16],[1746,17],[2232,16]]}},"keywords":{}}],["self.x",{"_index":5343,"title":{},"content":{"197":{"position":[[471,6],[620,6]]}},"keywords":{}}],["self.x.to_str",{"_index":4298,"title":{},"content":{"129":{"position":[[1503,18]]}},"keywords":{}}],["sell",{"_index":1569,"title":{},"content":{"33":{"position":[[231,8]]},"40":{"position":[[1293,7]]},"164":{"position":[[1221,7]]}},"keywords":{}}],["semant",{"_index":3425,"title":{},"content":{"97":{"position":[[5482,9]]},"198":{"position":[[20,9],[39,9],[369,9],[885,10]]}},"keywords":{}}],["semest",{"_index":2245,"title":{},"content":{"53":{"position":[[1085,8]]},"88":{"position":[[102,8]]},"100":{"position":[[100,9]]}},"keywords":{}}],["send",{"_index":2384,"title":{},"content":{"61":{"position":[[1922,5]]},"96":{"position":[[910,4]]},"116":{"position":[[143,4],[2525,4],[2708,4],[3009,4],[3062,4]]},"117":{"position":[[357,4],[2121,4]]},"175":{"position":[[1222,4]]}},"keywords":{}}],["sens",{"_index":1169,"title":{},"content":{"26":{"position":[[149,5]]},"43":{"position":[[1190,5]]},"51":{"position":[[1597,5]]},"53":{"position":[[2041,6]]},"68":{"position":[[687,6]]},"106":{"position":[[918,5]]},"120":{"position":[[1047,5]]},"132":{"position":[[1026,5]]},"135":{"position":[[9,5]]},"175":{"position":[[720,5],[946,5]]}},"keywords":{}}],["sensit",{"_index":2385,"title":{},"content":{"61":{"position":[[1962,9]]},"158":{"position":[[26,9]]}},"keywords":{}}],["sent",{"_index":2388,"title":{},"content":{"61":{"position":[[2215,4]]},"115":{"position":[[1211,4],[1591,4],[2416,4],[2669,4]]},"116":{"position":[[1163,4],[1496,4],[2274,4]]}},"keywords":{}}],["sentenc",{"_index":2057,"title":{},"content":{"49":{"position":[[308,9]]},"51":{"position":[[3409,8]]},"52":{"position":[[63,8]]}},"keywords":{}}],["sentiment",{"_index":1167,"title":{"26":{"position":[[6,11]]}},"content":{"30":{"position":[[2878,9]]}},"keywords":{}}],["separ",{"_index":111,"title":{},"content":{"2":{"position":[[561,8],[652,8]]},"49":{"position":[[680,8]]},"100":{"position":[[166,10]]},"112":{"position":[[1352,9]]},"125":{"position":[[2289,8]]},"132":{"position":[[997,8]]},"188":{"position":[[643,8],[1876,8]]},"189":{"position":[[724,8]]}},"keywords":{}}],["septemb",{"_index":1262,"title":{},"content":{"28":{"position":[[1918,13]]},"30":{"position":[[1426,12]]}},"keywords":{}}],["sequenc",{"_index":4240,"title":{},"content":{"127":{"position":[[1107,8]]}},"keywords":{}}],["sequenti",{"_index":3742,"title":{},"content":{"113":{"position":[[1108,10]]}},"keywords":{}}],["seri",{"_index":4626,"title":{},"content":{"159":{"position":[[59,7]]},"160":{"position":[[427,6],[3200,6]]}},"keywords":{}}],["serial",{"_index":3751,"title":{"168":{"position":[[0,14]]}},"content":{"113":{"position":[[1525,9]]},"163":{"position":[[96,9]]},"164":{"position":[[276,9]]},"165":{"position":[[1008,13]]},"168":{"position":[[65,9]]},"169":{"position":[[85,10]]}},"keywords":{}}],["seriou",{"_index":1564,"title":{},"content":{"33":{"position":[[11,7]]},"40":{"position":[[2428,7]]}},"keywords":{}}],["serious",{"_index":3994,"title":{},"content":{"124":{"position":[[259,10]]},"129":{"position":[[1398,9]]}},"keywords":{}}],["serv",{"_index":129,"title":{},"content":{"2":{"position":[[849,6]]}},"keywords":{}}],["server",{"_index":2853,"title":{"94":{"position":[[23,6]]}},"content":{"88":{"position":[[692,6]]},"93":{"position":[[4107,6]]},"95":{"position":[[47,7]]},"97":{"position":[[6238,6]]},"125":{"position":[[4577,6],[4837,6]]}},"keywords":{}}],["server!"",{"_index":3333,"title":{},"content":{"96":{"position":[[777,16]]}},"keywords":{}}],["servic",{"_index":2364,"title":{},"content":{"61":{"position":[[1149,7]]}},"keywords":{}}],["session",{"_index":2403,"title":{},"content":{"62":{"position":[[458,7]]}},"keywords":{}}],["session.get(url.format(d.strftime(format_str",{"_index":2414,"title":{},"content":{"62":{"position":[[772,48]]}},"keywords":{}}],["set",{"_index":104,"title":{"111":{"position":[[8,7]]}},"content":{"2":{"position":[[426,9]]},"3":{"position":[[273,7],[763,7]]},"6":{"position":[[105,3]]},"7":{"position":[[304,3]]},"9":{"position":[[37,3]]},"11":{"position":[[37,3]]},"15":{"position":[[572,3]]},"32":{"position":[[1281,3]]},"33":{"position":[[850,3]]},"39":{"position":[[108,3]]},"44":{"position":[[1950,4]]},"45":{"position":[[2788,4]]},"61":{"position":[[1446,3]]},"62":{"position":[[25,3]]},"65":{"position":[[1658,3]]},"73":{"position":[[436,3]]},"74":{"position":[[1022,4]]},"75":{"position":[[420,3],[529,3],[610,3],[678,3],[756,3],[816,3],[894,3],[1017,3]]},"97":{"position":[[1363,3],[1646,3],[3792,3]]},"98":{"position":[[69,3]]},"102":{"position":[[1161,9]]},"103":{"position":[[1534,3]]},"109":{"position":[[27,3],[477,4]]},"111":{"position":[[27,3],[503,4]]},"112":{"position":[[1678,3]]},"113":{"position":[[48,3],[501,3],[1295,3],[1564,3]]},"125":{"position":[[4508,4],[4588,3]]},"173":{"position":[[662,7],[727,3],[782,7],[1855,3]]},"197":{"position":[[1072,3]]}},"keywords":{}}],["set([x",{"_index":2101,"title":{},"content":{"51":{"position":[[1209,6]]}},"keywords":{}}],["set(all_word",{"_index":2099,"title":{},"content":{"51":{"position":[[1179,14]]}},"keywords":{}}],["set_i",{"_index":3728,"title":{},"content":{"112":{"position":[[1544,7]]}},"keywords":{}}],["set_x",{"_index":3726,"title":{},"content":{"112":{"position":[[1522,8]]}},"keywords":{}}],["settl",{"_index":105,"title":{},"content":{"2":{"position":[[438,7]]}},"keywords":{}}],["setup",{"_index":3299,"title":{"95":{"position":[[4,6]]},"107":{"position":[[28,5]]}},"content":{"175":{"position":[[841,5]]}},"keywords":{}}],["sever",{"_index":3369,"title":{},"content":{"97":{"position":[[1035,6]]}},"keywords":{}}],["sexi",{"_index":2820,"title":{},"content":{"85":{"position":[[110,5]]}},"keywords":{}}],["shade",{"_index":3066,"title":{},"content":{"90":{"position":[[5016,6]]}},"keywords":{}}],["shaki",{"_index":4202,"title":{},"content":{"125":{"position":[[10659,5]]}},"keywords":{}}],["shape",{"_index":2606,"title":{},"content":{"70":{"position":[[1369,6]]},"161":{"position":[[895,7]]},"172":{"position":[[1538,5]]}},"keywords":{}}],["share",{"_index":1522,"title":{},"content":{"32":{"position":[[490,5],[542,5],[1095,5],[1127,6]]},"33":{"position":[[1267,6]]},"34":{"position":[[1480,6],[2515,6],[2632,6]]},"39":{"position":[[668,6],[740,6],[1727,6],[2080,6]]},"61":{"position":[[2049,5]]},"115":{"position":[[1866,6]]},"116":{"position":[[1771,6]]},"124":{"position":[[543,5]]},"125":{"position":[[367,5]]},"161":{"position":[[1664,7]]},"184":{"position":[[1080,6]]},"185":{"position":[[761,6]]}},"keywords":{}}],["sharp",{"_index":703,"title":{"19":{"position":[[16,6]]}},"content":{"17":{"position":[[32,6]]},"19":{"position":[[1,7],[182,7],[224,6],[279,6],[356,7]]},"20":{"position":[[871,6],[2761,6]]},"161":{"position":[[1401,5]]}},"keywords":{}}],["sharpe(returns[tick",{"_index":753,"title":{},"content":{"19":{"position":[[373,21]]}},"keywords":{}}],["sharpe_a",{"_index":812,"title":{},"content":{"20":{"position":[[1211,8],[1485,9]]}},"keywords":{}}],["sharpe_limit",{"_index":805,"title":{},"content":{"20":{"position":[[1057,13],[1497,12]]}},"keywords":{}}],["sharpes[tick",{"_index":814,"title":{},"content":{"20":{"position":[[1253,14]]}},"keywords":{}}],["shebang",{"_index":3881,"title":{},"content":{"121":{"position":[[547,8]]}},"keywords":{}}],["shell",{"_index":3678,"title":{},"content":{"108":{"position":[[863,6]]}},"keywords":{}}],["shift",{"_index":2689,"title":{},"content":{"76":{"position":[[568,5]]},"90":{"position":[[3609,5]]},"91":{"position":[[2910,5]]},"92":{"position":[[722,5]]}},"keywords":{}}],["shine",{"_index":4798,"title":{},"content":{"163":{"position":[[2240,7]]},"164":{"position":[[1204,7]]}},"keywords":{}}],["ship",{"_index":3312,"title":{},"content":{"95":{"position":[[472,4]]},"108":{"position":[[380,7]]}},"keywords":{}}],["shoot",{"_index":3888,"title":{},"content":{"121":{"position":[[930,5]]}},"keywords":{}}],["shootout",{"_index":4759,"title":{"162":{"position":[[14,8]]}},"content":{"163":{"position":[[2290,8]]}},"keywords":{}}],["short",{"_index":743,"title":{},"content":{"19":{"position":[[190,8]]},"20":{"position":[[110,5]]},"33":{"position":[[225,5]]},"103":{"position":[[771,6]]},"112":{"position":[[443,5]]},"118":{"position":[[32,6]]},"127":{"position":[[220,5]]},"152":{"position":[[98,5]]}},"keywords":{}}],["shortest",{"_index":5004,"title":{},"content":{"175":{"position":[[212,8]]}},"keywords":{}}],["shortwav",{"_index":5009,"title":{},"content":{"175":{"position":[[439,9]]}},"keywords":{}}],["shot",{"_index":2903,"title":{},"content":{"88":{"position":[[2379,4]]}},"keywords":{}}],["shouldn't",{"_index":1340,"title":{},"content":{"30":{"position":[[641,9]]},"96":{"position":[[391,9]]},"120":{"position":[[523,9]]},"188":{"position":[[4108,9]]}},"keywords":{}}],["shout",{"_index":213,"title":{},"content":{"3":{"position":[[1474,6]]}},"keywords":{}}],["show",{"_index":25,"title":{},"content":{"1":{"position":[[284,4]]},"2":{"position":[[305,7]]},"29":{"position":[[74,6]]},"30":{"position":[[146,4],[7880,4]]},"53":{"position":[[941,5]]},"83":{"position":[[436,5]]},"89":{"position":[[148,5]]},"116":{"position":[[916,4]]},"125":{"position":[[3420,7]]},"128":{"position":[[129,7],[349,7],[1019,4]]},"129":{"position":[[38,4]]},"135":{"position":[[152,4],[241,4]]},"156":{"position":[[572,5]]},"190":{"position":[[67,4]]},"194":{"position":[[747,4]]},"197":{"position":[[777,5]]}},"keywords":{}}],["show(f",{"_index":1279,"title":{},"content":{"28":{"position":[[2312,7],[3985,7]]},"30":{"position":[[2252,7],[3737,7],[3960,7],[5516,7],[6817,7],[7040,7]]}},"keywords":{}}],["shrink",{"_index":3056,"title":{},"content":{"90":{"position":[[4456,9],[4573,9],[4679,9]]}},"keywords":{}}],["shrink=0.05",{"_index":3050,"title":{},"content":{"90":{"position":[[4366,13]]}},"keywords":{}}],["side",{"_index":1676,"title":{"36":{"position":[[0,4]]}},"content":{"41":{"position":[[193,4]]},"88":{"position":[[699,5],[738,5]]},"93":{"position":[[4114,5],[4153,5]]},"118":{"position":[[177,4]]},"121":{"position":[[1064,5]]},"125":{"position":[[9936,4]]},"150":{"position":[[210,4]]}},"keywords":{}}],["sidenot",{"_index":3435,"title":{},"content":{"97":{"position":[[6301,9]]}},"keywords":{}}],["sigh",{"_index":2016,"title":{},"content":{"45":{"position":[[2491,7]]}},"keywords":{}}],["sigma}σr−rm",{"_index":738,"title":{},"content":{"19":{"position":[[29,14]]}},"keywords":{}}],["sign",{"_index":90,"title":{},"content":{"2":{"position":[[239,4]]},"40":{"position":[[1144,4],[1473,4]]}},"keywords":{}}],["signal",{"_index":3460,"title":{},"content":{"100":{"position":[[243,6]]},"102":{"position":[[735,7],[908,6],[985,7],[1296,7]]},"103":{"position":[[105,6],[950,6],[1159,6],[1675,6]]},"104":{"position":[[693,7],[706,6],[773,6],[987,7],[1270,6],[1348,6]]},"106":{"position":[[655,7],[1020,6],[1154,6]]},"173":{"position":[[1382,6],[1435,7]]}},"keywords":{}}],["signal_byt",{"_index":3582,"title":{},"content":{"105":{"position":[[616,12]]}},"keywords":{}}],["signalsif",{"_index":4965,"title":{},"content":{"173":{"position":[[1577,9]]}},"keywords":{}}],["signatur",{"_index":3399,"title":{},"content":{"97":{"position":[[3301,9]]}},"keywords":{}}],["signific",{"_index":1675,"title":{},"content":{"35":{"position":[[427,11]]},"164":{"position":[[1450,11]]}},"keywords":{}}],["significantli",{"_index":1287,"title":{},"content":{"28":{"position":[[2610,13]]},"40":{"position":[[3278,13]]},"73":{"position":[[122,13]]},"160":{"position":[[1885,13]]},"165":{"position":[[1437,13]]}},"keywords":{}}],["signs_match(article_df[[futur",{"_index":1081,"title":{},"content":{"24":{"position":[[2042,31]]},"25":{"position":[[1766,31]]}},"keywords":{}}],["signs_match(list_1",{"_index":1046,"title":{},"content":{"24":{"position":[[935,19]]},"25":{"position":[[655,19]]}},"keywords":{}}],["sim",{"_index":1756,"title":{},"content":{"39":{"position":[[2474,3]]}},"keywords":{}}],["sim_first_word(first_word_dist",{"_index":2159,"title":{},"content":{"51":{"position":[[3932,32]]},"52":{"position":[[161,31],[759,31]]}},"keywords":{}}],["sim_hashtags(1",{"_index":2177,"title":{},"content":{"52":{"position":[[367,15]]}},"keywords":{}}],["sim_hashtags(n",{"_index":2156,"title":{},"content":{"51":{"position":[[3832,15]]}},"keywords":{}}],["sim_hashtags(n_hash",{"_index":2188,"title":{},"content":{"52":{"position":[[831,20]]}},"keywords":{}}],["sim_n_hashtags(hashtag_freq",{"_index":2154,"title":{},"content":{"51":{"position":[[3759,29]]}},"keywords":{}}],["sim_n_hashtags(ml",{"_index":2187,"title":{},"content":{"52":{"position":[[800,19]]}},"keywords":{}}],["sim_next_word(curr",{"_index":2163,"title":{},"content":{"51":{"position":[[4082,22]]},"52":{"position":[[1051,22]]}},"keywords":{}}],["sim_next_word(first",{"_index":2171,"title":{},"content":{"52":{"position":[[202,20]]}},"keywords":{}}],["sim_next_word(fourth",{"_index":2176,"title":{},"content":{"52":{"position":[[324,21]]}},"keywords":{}}],["sim_next_word(second",{"_index":2172,"title":{},"content":{"52":{"position":[[242,21]]}},"keywords":{}}],["sim_next_word(third",{"_index":2174,"title":{},"content":{"52":{"position":[[284,20]]}},"keywords":{}}],["sim_seri",{"_index":1759,"title":{},"content":{"39":{"position":[[2605,10]]}},"keywords":{}}],["sim_series.apply(lambda",{"_index":1763,"title":{},"content":{"39":{"position":[[2686,23],[2745,23],[2810,23],[2876,23],[2989,23]]}},"keywords":{}}],["sim_summari",{"_index":1643,"title":{},"content":{"34":{"position":[[2698,11]]}},"keywords":{}}],["sim_summary(invest",{"_index":1661,"title":{},"content":{"34":{"position":[[3379,24],[3770,24]]}},"keywords":{}}],["similar",{"_index":626,"title":{},"content":{"14":{"position":[[61,7]]},"15":{"position":[[43,7]]},"30":{"position":[[7885,7]]},"92":{"position":[[1308,8]]},"104":{"position":[[1964,8]]},"112":{"position":[[935,8]]},"117":{"position":[[2044,7]]},"128":{"position":[[1028,7]]},"129":{"position":[[2756,7]]},"160":{"position":[[408,7]]},"186":{"position":[[166,7]]}},"keywords":{}}],["similarli",{"_index":4569,"title":{},"content":{"155":{"position":[[815,10]]},"158":{"position":[[233,10]]}},"keywords":{}}],["simpl",{"_index":1686,"title":{"166":{"position":[[0,6]]}},"content":{"38":{"position":[[38,6]]},"93":{"position":[[1097,6]]},"96":{"position":[[327,7],[586,7]]},"103":{"position":[[807,7]]},"109":{"position":[[120,6]]},"125":{"position":[[216,6],[3918,7]]},"160":{"position":[[4034,7]]},"163":{"position":[[32,6]]},"188":{"position":[[4068,7]]},"193":{"position":[[889,6]]}},"keywords":{}}],["simple_refer",{"_index":5335,"title":{},"content":{"196":{"position":[[1530,18]]}},"keywords":{}}],["simpler",{"_index":375,"title":{},"content":{"7":{"position":[[16,8]]},"97":{"position":[[2326,7]]},"125":{"position":[[5743,8]]},"165":{"position":[[275,7]]},"190":{"position":[[690,7]]}},"keywords":{}}],["simplest",{"_index":4841,"title":{},"content":{"166":{"position":[[263,8]]},"184":{"position":[[44,8]]},"192":{"position":[[5,8]]},"196":{"position":[[743,8]]}},"keywords":{}}],["simpli",{"_index":1981,"title":{},"content":{"45":{"position":[[1311,6]]},"68":{"position":[[22,7]]},"86":{"position":[[206,6]]},"97":{"position":[[1639,6]]},"102":{"position":[[176,7]]},"139":{"position":[[688,6]]},"160":{"position":[[3070,7]]},"188":{"position":[[5,7]]},"193":{"position":[[722,7]]},"196":{"position":[[481,6]]}},"keywords":{}}],["simplifi",{"_index":4217,"title":{},"content":{"125":{"position":[[11549,8]]}},"keywords":{}}],["simul",{"_index":304,"title":{"6":{"position":[[11,11]]},"7":{"position":[[13,11]]},"8":{"position":[[8,11]]},"11":{"position":[[20,11]]},"12":{"position":[[6,11]]},"13":{"position":[[7,11]]},"14":{"position":[[23,11]]},"15":{"position":[[20,11]]},"34":{"position":[[12,11]]},"39":{"position":[[10,11]]},"73":{"position":[[0,9]]},"75":{"position":[[15,9]]},"84":{"position":[[17,9]]},"85":{"position":[[4,9]]}},"content":{"6":{"position":[[54,8],[116,10],[235,11],[639,11],[746,8],[941,10],[1013,11],[1076,10]]},"7":{"position":[[28,8],[156,10],[235,10]]},"8":{"position":[[33,10]]},"11":{"position":[[83,11],[187,8],[305,11]]},"12":{"position":[[201,11],[614,11],[660,11]]},"13":{"position":[[39,11],[1573,10],[1596,10],[1731,12],[1929,10],[1954,10],[1985,10],[2010,10],[2041,10],[2066,10],[2097,10],[2122,10],[2153,10],[2178,10],[2213,12]]},"14":{"position":[[1201,11],[2656,10],[2679,10],[2814,12],[3001,10],[3026,10],[3057,10],[3082,10],[3113,10],[3138,10],[3169,10],[3194,10],[3225,10],[3250,10],[3285,12]]},"15":{"position":[[583,11],[2330,10],[2353,10],[2488,12],[2672,10],[2697,10],[2728,10],[2753,10],[2784,10],[2809,10],[2840,10],[2865,10],[2896,10],[2921,10],[2956,12]]},"34":{"position":[[787,9],[1386,11],[1586,8],[1824,10],[3046,11],[3252,10]]},"39":{"position":[[119,10]]},"41":{"position":[[617,11]]},"51":{"position":[[2164,8],[3512,8]]},"52":{"position":[[52,8],[563,8],[586,8],[618,8]]},"73":{"position":[[275,9],[512,9],[620,9]]},"75":{"position":[[63,9]]},"78":{"position":[[952,9]]},"79":{"position":[[156,9]]},"80":{"position":[[178,9]]},"81":{"position":[[157,9]]},"82":{"position":[[956,9]]},"85":{"position":[[54,9],[473,9]]},"86":{"position":[[381,9],[478,9]]}},"keywords":{}}],["simulate("yahoo/lmt"",{"_index":1657,"title":{},"content":{"34":{"position":[[3312,31],[3703,31]]}},"keywords":{}}],["simulate_casino([1/3",{"_index":2781,"title":{},"content":{"79":{"position":[[65,21]]},"80":{"position":[[87,21]]}},"keywords":{}}],["simulate_casino([1/9",{"_index":2788,"title":{},"content":{"82":{"position":[[166,21]]}},"keywords":{}}],["simulate_casino([2/9",{"_index":2774,"title":{},"content":{"78":{"position":[[798,21]]}},"keywords":{}}],["simulate_casino(d1_dist",{"_index":2747,"title":{},"content":{"78":{"position":[[115,24]]}},"keywords":{}}],["simulate_casino(np.repeat(1/6",{"_index":2785,"title":{},"content":{"81":{"position":[[100,30]]}},"keywords":{}}],["simulate_day(open_v",{"_index":1729,"title":{},"content":{"39":{"position":[[994,23]]}},"keywords":{}}],["simulate_day(ticker_info[d:]["open"",{"_index":1757,"title":{},"content":{"39":{"position":[[2484,47]]}},"keywords":{}}],["simulate_gbm",{"_index":387,"title":{},"content":{"7":{"position":[[262,12]]}},"keywords":{}}],["simulate_gbm(final_motion[:,end",{"_index":532,"title":{},"content":{"12":{"position":[[413,33]]}},"keywords":{}}],["simulate_gbm(full_motion[:,end",{"_index":521,"title":{},"content":{"11":{"position":[[455,32]]}},"keywords":{}}],["simulate_gbm(initi",{"_index":450,"title":{},"content":{"8":{"position":[[173,21]]}},"keywords":{}}],["simulate_tickers(["yahoo/fb"",{"_index":1786,"title":{},"content":{"40":{"position":[[118,39]]}},"keywords":{}}],["simulate_tickers(["yahoo/x"",{"_index":1815,"title":{},"content":{"40":{"position":[[1652,38]]}},"keywords":{}}],["simulate_tickers(['yahoo/regn",{"_index":1826,"title":{},"content":{"40":{"position":[[2620,31]]}},"keywords":{}}],["simulate_tickers(tick",{"_index":1773,"title":{},"content":{"39":{"position":[[3040,26]]}},"keywords":{}}],["simulate_ts(nam",{"_index":1743,"title":{},"content":{"39":{"position":[[2146,17]]}},"keywords":{}}],["simulate_ts(tick",{"_index":1776,"title":{},"content":{"39":{"position":[[3175,19]]}},"keywords":{}}],["simulate_tweet",{"_index":2184,"title":{},"content":{"52":{"position":[[711,17]]}},"keywords":{}}],["simulatem",{"_index":348,"title":{},"content":{"6":{"position":[[678,10]]}},"keywords":{}}],["simulaten",{"_index":349,"title":{},"content":{"6":{"position":[[712,10]]}},"keywords":{}}],["simultan",{"_index":5196,"title":{},"content":{"188":{"position":[[2812,15]]}},"keywords":{}}],["sin",{"_index":2265,"title":{},"content":{"53":{"position":[[1343,3]]}},"keywords":{}}],["since2014",{"_index":4803,"title":{},"content":{"164":{"position":[[189,12]]}},"keywords":{}}],["sine",{"_index":59,"title":{},"content":{"1":{"position":[[673,4]]}},"keywords":{}}],["singer",{"_index":3556,"title":{},"content":{"104":{"position":[[535,8]]}},"keywords":{}}],["singl",{"_index":376,"title":{},"content":{"7":{"position":[[39,6]]},"32":{"position":[[263,6]]},"33":{"position":[[602,6]]},"52":{"position":[[136,6]]},"65":{"position":[[344,6]]},"97":{"position":[[8,6]]},"120":{"position":[[823,6],[846,6]]},"164":{"position":[[499,6]]},"167":{"position":[[216,6]]},"183":{"position":[[5,6]]}},"keywords":{}}],["site",{"_index":4728,"title":{},"content":{"161":{"position":[[317,4]]}},"keywords":{}}],["situat",{"_index":4427,"title":{},"content":{"139":{"position":[[672,10]]},"160":{"position":[[1524,10],[2702,10]]},"197":{"position":[[1471,10]]}},"keywords":{}}],["size",{"_index":3483,"title":{},"content":{"101":{"position":[[676,4]]},"105":{"position":[[299,5],[3097,5],[3295,4],[3381,4]]},"141":{"position":[[148,5],[350,5]]},"146":{"position":[[345,4],[432,5]]},"153":{"position":[[810,4]]},"155":{"position":[[176,5]]},"156":{"position":[[70,5]]},"160":{"position":[[1869,4]]},"163":{"position":[[177,4]]},"165":{"position":[[1278,5],[1336,4]]},"170":{"position":[[411,5]]},"175":{"position":[[1336,4],[1697,5]]},"194":{"position":[[467,4],[490,4]]},"195":{"position":[[76,4],[552,4]]}},"keywords":{}}],["skew",{"_index":1378,"title":{},"content":{"30":{"position":[[2742,4]]},"71":{"position":[[1201,7]]}},"keywords":{}}],["skill",{"_index":37,"title":{},"content":{"1":{"position":[[420,6]]}},"keywords":{}}],["skip",{"_index":1710,"title":{},"content":{"39":{"position":[[228,4]]},"59":{"position":[[236,4]]},"61":{"position":[[2078,7]]},"104":{"position":[[1539,4]]},"121":{"position":[[1303,4],[1523,8]]},"125":{"position":[[1702,4],[2535,4]]},"174":{"position":[[898,4],[1173,4]]}},"keywords":{}}],["sklearn.cross_valid",{"_index":2040,"title":{},"content":{"47":{"position":[[53,24]]}},"keywords":{}}],["sklearn.decomposit",{"_index":1991,"title":{},"content":{"45":{"position":[[1949,21]]},"103":{"position":[[821,21]]}},"keywords":{}}],["sklearn.naive_bay",{"_index":1989,"title":{},"content":{"45":{"position":[[1906,19]]}},"keywords":{}}],["sklearn.preprocess",{"_index":1912,"title":{},"content":{"44":{"position":[[564,21]]}},"keywords":{}}],["slack",{"_index":3999,"title":{},"content":{"124":{"position":[[509,5]]}},"keywords":{}}],["slb",{"_index":714,"title":{},"content":{"17":{"position":[[183,6]]},"18":{"position":[[300,6]]},"19":{"position":[[524,6]]},"20":{"position":[[444,6],[2932,7]]}},"keywords":{}}],["sleep",{"_index":3980,"title":{},"content":{"123":{"position":[[693,5]]}},"keywords":{}}],["slice",{"_index":2852,"title":{},"content":{"88":{"position":[[684,7]]},"93":{"position":[[4099,7]]}},"keywords":{}}],["slightli",{"_index":1175,"title":{},"content":{"26":{"position":[[650,8]]},"30":{"position":[[7572,8]]},"45":{"position":[[966,8]]},"75":{"position":[[477,8]]},"182":{"position":[[61,8]]},"193":{"position":[[3075,8]]}},"keywords":{}}],["slow",{"_index":3847,"title":{"120":{"position":[[0,4]]}},"content":{"176":{"position":[[1071,4]]}},"keywords":{}}],["slowit'",{"_index":4414,"title":{},"content":{"139":{"position":[[136,8]]}},"keywords":{}}],["small",{"_index":826,"title":{"63":{"position":[[25,5]]}},"content":{"20":{"position":[[1687,5]]},"40":{"position":[[1136,7]]},"61":{"position":[[1271,5]]},"63":{"position":[[54,6]]},"74":{"position":[[1346,5]]},"83":{"position":[[536,5]]},"89":{"position":[[799,5]]},"97":{"position":[[6232,5]]},"103":{"position":[[394,5]]},"104":{"position":[[871,5],[1440,5]]},"105":{"position":[[130,5]]},"106":{"position":[[773,5],[800,5]]},"113":{"position":[[202,6]]},"150":{"position":[[29,5],[677,5],[736,5]]},"160":{"position":[[2840,6]]},"175":{"position":[[94,5]]},"181":{"position":[[577,5]]}},"keywords":{}}],["small(u8",{"_index":5312,"title":{},"content":{"194":{"position":[[233,10]]}},"keywords":{}}],["smaller",{"_index":1703,"title":{},"content":{"38":{"position":[[1076,7]]},"93":{"position":[[709,7]]},"102":{"position":[[1315,7]]},"105":{"position":[[3281,7]]},"163":{"position":[[689,7]]}},"keywords":{}}],["smallvec",{"_index":4832,"title":{},"content":{"165":{"position":[[895,8]]}},"keywords":{}}],["smart",{"_index":4556,"title":{"155":{"position":[[0,5]]}},"content":{"155":{"position":[[224,5],[496,5],[622,5],[911,5],[1032,5],[1056,5]]},"156":{"position":[[274,5]]},"157":{"position":[[358,5]]},"159":{"position":[[597,5],[747,5],[963,5],[1125,5]]}},"keywords":{}}],["smarter",{"_index":3809,"title":{},"content":{"116":{"position":[[2369,7]]}},"keywords":{}}],["smell",{"_index":5106,"title":{},"content":{"181":{"position":[[1037,6]]}},"keywords":{}}],["smooth",{"_index":1847,"title":{},"content":{"40":{"position":[[3735,7]]}},"keywords":{}}],["smoother",{"_index":1820,"title":{},"content":{"40":{"position":[[2183,8]]}},"keywords":{}}],["snippet",{"_index":4438,"title":{},"content":{"141":{"position":[[223,7]]}},"keywords":{}}],["socket",{"_index":4956,"title":{},"content":{"173":{"position":[[975,7]]}},"keywords":{}}],["sole",{"_index":5,"title":{},"content":{"1":{"position":[[5,4]]},"169":{"position":[[229,6]]}},"keywords":{}}],["solut",{"_index":161,"title":{},"content":{"3":{"position":[[544,8]]},"74":{"position":[[257,8]]},"125":{"position":[[1305,9],[1850,9],[4747,9],[5011,9]]},"190":{"position":[[856,8]]}},"keywords":{}}],["solv",{"_index":253,"title":{},"content":{"4":{"position":[[713,6]]},"85":{"position":[[191,6]]},"86":{"position":[[87,5],[776,5]]},"125":{"position":[[883,7],[1128,7]]},"143":{"position":[[29,5]]}},"keywords":{}}],["solver",{"_index":2829,"title":{},"content":{"86":{"position":[[571,6]]}},"keywords":{}}],["someon",{"_index":1434,"title":{},"content":{"30":{"position":[[7639,7]]},"65":{"position":[[1437,7]]},"120":{"position":[[43,7]]},"125":{"position":[[1115,7],[2110,7],[10778,7]]}},"keywords":{}}],["somesuch",{"_index":4504,"title":{},"content":{"150":{"position":[[803,8]]}},"keywords":{}}],["someth",{"_index":91,"title":{"86":{"position":[[8,9]]}},"content":{"2":{"position":[[244,9]]},"4":{"position":[[1067,9]]},"20":{"position":[[1677,9]]},"30":{"position":[[9568,9]]},"43":{"position":[[818,9]]},"49":{"position":[[537,9]]},"53":{"position":[[13,9]]},"54":{"position":[[172,9]]},"76":{"position":[[851,9],[1165,9]]},"96":{"position":[[443,9]]},"97":{"position":[[383,9],[716,9],[2713,9],[3255,9],[3523,9]]},"103":{"position":[[1569,10],[2244,9]]},"104":{"position":[[1954,9]]},"105":{"position":[[205,9],[2848,9],[3040,9]]},"112":{"position":[[780,9]]},"115":{"position":[[92,9],[3059,9]]},"116":{"position":[[187,9]]},"117":{"position":[[951,9]]},"120":{"position":[[388,9]]},"125":{"position":[[3342,9],[6382,9],[6801,9],[7157,9]]},"134":{"position":[[361,9]]},"160":{"position":[[4248,9]]},"165":{"position":[[1089,9]]},"173":{"position":[[1696,9]]},"179":{"position":[[1776,9]]}},"keywords":{}}],["sometim",{"_index":3150,"title":{},"content":{"91":{"position":[[3737,9]]},"152":{"position":[[318,9]]}},"keywords":{}}],["somewher",{"_index":3564,"title":{},"content":{"104":{"position":[[1025,10]]},"112":{"position":[[485,9]]},"115":{"position":[[218,9]]},"116":{"position":[[318,9]]},"117":{"position":[[1107,9]]},"128":{"position":[[845,9]]}},"keywords":{}}],["song",{"_index":3500,"title":{},"content":{"103":{"position":[[42,4]]}},"keywords":{}}],["soon",{"_index":1190,"title":{},"content":{"26":{"position":[[918,5]]},"29":{"position":[[448,5]]},"30":{"position":[[7991,5]]},"46":{"position":[[581,5]]},"175":{"position":[[1549,4]]}},"keywords":{}}],["sophist",{"_index":457,"title":{},"content":{"9":{"position":[[82,13]]},"45":{"position":[[1482,13]]}},"keywords":{}}],["sore",{"_index":2211,"title":{},"content":{"53":{"position":[[445,4]]}},"keywords":{}}],["sorri",{"_index":3925,"title":{},"content":{"121":{"position":[[2570,6]]}},"keywords":{}}],["sort",{"_index":999,"title":{},"content":{"23":{"position":[[236,6]]},"36":{"position":[[151,5]]},"93":{"position":[[387,4]]}},"keywords":{}}],["sound",{"_index":3541,"title":{},"content":{"103":{"position":[[1871,5],[2209,5]]},"105":{"position":[[220,6],[2673,6],[2807,6],[3386,6]]},"106":{"position":[[441,5]]},"199":{"position":[[735,6]]}},"keywords":{}}],["sourc",{"_index":4726,"title":{},"content":{"161":{"position":[[175,6]]}},"keywords":{}}],["space",{"_index":2138,"title":{},"content":{"51":{"position":[[2995,5]]},"52":{"position":[[679,5]]},"85":{"position":[[218,5]]},"101":{"position":[[282,6],[897,6],[1058,6]]},"102":{"position":[[301,6]]},"105":{"position":[[409,5],[2618,5]]},"106":{"position":[[216,6],[303,5],[352,5]]},"130":{"position":[[201,5]]},"140":{"position":[[207,5]]},"141":{"position":[[297,5]]},"142":{"position":[[108,5]]},"145":{"position":[[221,5]]},"155":{"position":[[1198,5]]},"195":{"position":[[422,5]]}},"keywords":{}}],["span",{"_index":937,"title":{},"content":{"22":{"position":[[1412,6]]},"125":{"position":[[2457,4]]}},"keywords":{}}],["sparsiti",{"_index":1932,"title":{},"content":{"44":{"position":[[1076,8]]}},"keywords":{}}],["speak",{"_index":4605,"title":{},"content":{"157":{"position":[[30,5]]}},"keywords":{}}],["speaker",{"_index":65,"title":{},"content":{"1":{"position":[[720,9]]}},"keywords":{}}],["spec",{"_index":4092,"title":{},"content":{"125":{"position":[[4204,5]]}},"keywords":{}}],["special",{"_index":665,"title":{},"content":{"15":{"position":[[98,7]]},"49":{"position":[[182,7]]},"61":{"position":[[796,7]]},"68":{"position":[[826,7],[952,7]]},"127":{"position":[[156,7]]},"160":{"position":[[388,7]]},"174":{"position":[[1263,11]]},"188":{"position":[[325,7]]},"189":{"position":[[216,7]]}},"keywords":{}}],["specif",{"_index":66,"title":{"172":{"position":[[9,9]]}},"content":{"1":{"position":[[732,12]]},"3":{"position":[[1287,8]]},"4":{"position":[[133,8]]},"20":{"position":[[886,8]]},"28":{"position":[[2546,12],[4184,12]]},"51":{"position":[[3233,8],[3468,8]]},"61":{"position":[[1984,13]]},"74":{"position":[[89,8],[821,8]]},"88":{"position":[[2067,8]]},"89":{"position":[[21,8]]},"93":{"position":[[809,8]]},"96":{"position":[[195,14]]},"97":{"position":[[333,8]]},"117":{"position":[[873,8]]},"120":{"position":[[287,12]]},"123":{"position":[[1,12]]},"125":{"position":[[4440,13]]},"127":{"position":[[178,8],[823,13]]},"133":{"position":[[215,13]]},"135":{"position":[[591,12]]},"155":{"position":[[384,12]]},"160":{"position":[[1515,8],[2225,8],[3478,8]]},"165":{"position":[[1288,12]]},"172":{"position":[[2573,8]]},"181":{"position":[[867,14]]},"196":{"position":[[82,9]]}},"keywords":{}}],["specifi",{"_index":3708,"title":{},"content":{"111":{"position":[[648,9],[752,7]]}},"keywords":{}}],["specificationdramat",{"_index":4018,"title":{},"content":{"125":{"position":[[538,25]]}},"keywords":{}}],["specificationref",{"_index":5087,"title":{},"content":{"179":{"position":[[1644,19]]}},"keywords":{}}],["spectr",{"_index":4976,"title":{},"content":{"174":{"position":[[101,8]]}},"keywords":{}}],["specul",{"_index":4974,"title":{},"content":{"174":{"position":[[29,11],[197,10]]}},"keywords":{}}],["speech",{"_index":2290,"title":{},"content":{"54":{"position":[[108,7]]}},"keywords":{}}],["speed",{"_index":2835,"title":{},"content":{"86":{"position":[[1083,5]]},"100":{"position":[[372,6]]},"132":{"position":[[963,6]]},"172":{"position":[[2447,5]]},"176":{"position":[[1651,6]]},"178":{"position":[[454,6]]},"198":{"position":[[313,5]]}},"keywords":{}}],["speic",{"_index":3688,"title":{},"content":{"109":{"position":[[339,6]]},"161":{"position":[[347,6]]}},"keywords":{}}],["spend",{"_index":244,"title":{},"content":{"4":{"position":[[544,8],[1273,8]]},"46":{"position":[[7,8]]},"97":{"position":[[2095,5]]},"121":{"position":[[751,5]]},"135":{"position":[[184,6]]},"139":{"position":[[435,5],[719,5]]},"157":{"position":[[55,8]]}},"keywords":{}}],["spent",{"_index":4000,"title":{},"content":{"124":{"position":[[652,5]]}},"keywords":{}}],["spi",{"_index":1004,"title":{},"content":{"23":{"position":[[364,3]]},"24":{"position":[[2518,3],[2670,3]]},"25":{"position":[[2241,3],[2393,3]]}},"keywords":{}}],["spin",{"_index":4852,"title":{},"content":{"167":{"position":[[85,5]]}},"keywords":{}}],["split",{"_index":1862,"title":{},"content":{"43":{"position":[[172,6]]},"47":{"position":[[14,5]]},"93":{"position":[[4557,5]]},"112":{"position":[[1258,6]]}},"keywords":{}}],["spoiler",{"_index":3805,"title":{},"content":{"116":{"position":[[863,7]]}},"keywords":{}}],["spontan",{"_index":4505,"title":{},"content":{"150":{"position":[[855,13]]}},"keywords":{}}],["sporad",{"_index":1281,"title":{},"content":{"28":{"position":[[2410,9]]}},"keywords":{}}],["spot",{"_index":4385,"title":{},"content":{"136":{"position":[[202,4]]}},"keywords":{}}],["springr",{"_index":2267,"title":{},"content":{"53":{"position":[[1359,7]]}},"keywords":{}}],["spy_close_ret",{"_index":1140,"title":{},"content":{"25":{"position":[[469,13],[1402,14]]}},"keywords":{}}],["spy_open_ret",{"_index":1038,"title":{},"content":{"24":{"position":[[753,12],[1682,13]]}},"keywords":{}}],["squar",{"_index":2019,"title":{},"content":{"45":{"position":[[2560,6]]},"193":{"position":[[1487,7],[1512,7],[1522,7],[2648,7],[2673,7],[2683,7],[3411,7],[3436,7],[3446,7],[3725,7],[3750,7],[3760,7]]}},"keywords":{}}],["src/main.r",{"_index":3730,"title":{},"content":{"113":{"position":[[273,12]]}},"keywords":{}}],["src/main.rs:18:40",{"_index":3423,"title":{},"content":{"97":{"position":[[5035,17]]}},"keywords":{}}],["src/main.rs:31:18",{"_index":3778,"title":{},"content":{"115":{"position":[[1101,17],[1448,17],[1731,17],[2189,17]]}},"keywords":{}}],["src/main.rs:33:18",{"_index":3808,"title":{},"content":{"116":{"position":[[1053,17],[1353,17],[1636,17],[2047,17]]}},"keywords":{}}],["src_prefix",{"_index":3709,"title":{},"content":{"111":{"position":[[678,12]]}},"keywords":{}}],["src_prefix("schema"",{"_index":3703,"title":{},"content":{"111":{"position":[[369,31]]}},"keywords":{}}],["stabil",{"_index":4208,"title":{},"content":{"125":{"position":[[11273,10]]}},"keywords":{}}],["stabl",{"_index":3952,"title":{},"content":{"122":{"position":[[1024,7]]},"148":{"position":[[237,6]]}},"keywords":{}}],["stack",{"_index":1198,"title":{},"content":{"28":{"position":[[69,7]]},"121":{"position":[[1308,5],[1541,5]]},"140":{"position":[[144,5]]},"152":{"position":[[197,5]]},"153":{"position":[[818,5],[941,5]]},"157":{"position":[[43,5],[154,5],[392,5]]},"159":{"position":[[556,5],[698,5],[771,5],[929,5]]},"192":{"position":[[77,5],[747,6]]},"193":{"position":[[487,5],[1215,5],[1671,5],[3141,5]]},"195":{"position":[[36,5],[455,6],[546,5],[684,5],[732,7],[781,5],[1079,6]]},"196":{"position":[[558,5],[872,5],[1333,5]]},"197":{"position":[[259,5]]},"198":{"position":[[383,5],[409,5],[436,5]]},"199":{"position":[[765,5],[843,6],[1657,5]]}},"keywords":{}}],["stack.struct",{"_index":4632,"title":{},"content":{"159":{"position":[[636,14]]}},"keywords":{}}],["stack/heap",{"_index":4678,"title":{},"content":{"160":{"position":[[1585,10]]}},"keywords":{}}],["stagger",{"_index":4649,"title":{},"content":{"160":{"position":[[208,10]]}},"keywords":{}}],["stake",{"_index":2615,"title":{},"content":{"72":{"position":[[243,6]]},"101":{"position":[[792,6]]}},"keywords":{}}],["stand",{"_index":1698,"title":{},"content":{"38":{"position":[[785,9],[899,7]]}},"keywords":{}}],["standard",{"_index":741,"title":{},"content":{"19":{"position":[[146,8]]},"22":{"position":[[870,8]]},"90":{"position":[[5043,8]]},"91":{"position":[[4843,8],[5841,8]]},"92":{"position":[[1511,8]]},"120":{"position":[[120,8]]},"155":{"position":[[587,8]]},"156":{"position":[[1767,8]]},"157":{"position":[[341,8]]},"159":{"position":[[1147,8]]}},"keywords":{}}],["start",{"_index":3,"title":{"1":{"position":[[0,8]]},"109":{"position":[[8,8]]}},"content":{"1":{"position":[[10,8],[214,5]]},"9":{"position":[[51,5],[649,6],[760,5]]},"11":{"position":[[61,5]]},"30":{"position":[[2524,5],[7714,5],[9723,8],[10173,8],[10227,8],[10277,8],[10328,8]]},"32":{"position":[[46,5]]},"34":{"position":[[1612,6]]},"38":{"position":[[681,5],[1323,5]]},"39":{"position":[[146,5],[2164,6],[3133,5],[3195,6]]},"40":{"position":[[7,5]]},"41":{"position":[[315,5],[429,5]]},"43":{"position":[[449,5],[1217,5]]},"46":{"position":[[657,7]]},"49":{"position":[[84,8]]},"50":{"position":[[245,5]]},"51":{"position":[[333,5]]},"58":{"position":[[11,8],[108,5]]},"65":{"position":[[1923,8],[2065,8]]},"75":{"position":[[127,5]]},"76":{"position":[[4,5],[1973,5]]},"77":{"position":[[128,5]]},"78":{"position":[[225,5],[410,7]]},"82":{"position":[[132,5]]},"86":{"position":[[349,8]]},"88":{"position":[[588,6],[2456,6]]},"91":{"position":[[4327,5],[5746,5]]},"93":{"position":[[4003,6]]},"96":{"position":[[600,5],[1367,5]]},"97":{"position":[[703,5],[1171,5],[2491,7]]},"98":{"position":[[311,8]]},"101":{"position":[[530,7]]},"102":{"position":[[1347,5]]},"103":{"position":[[557,5],[603,5],[1685,7]]},"110":{"position":[[16,5],[154,5],[285,8]]},"113":{"position":[[112,5],[811,5]]},"120":{"position":[[28,5]]},"125":{"position":[[2825,8],[3162,5],[3228,8],[3842,6],[6332,8],[6408,5],[6672,5],[6834,5],[6920,6],[7407,8],[7496,8],[10115,8],[11562,5]]},"129":{"position":[[2815,7]]},"132":{"position":[[14,7]]},"160":{"position":[[2758,6],[2954,5]]},"161":{"position":[[16,7]]},"164":{"position":[[254,7]]},"188":{"position":[[2144,5],[2878,7],[2952,7],[3235,5]]},"189":{"position":[[2320,6],[2589,8]]},"192":{"position":[[262,8]]},"193":{"position":[[1768,5],[2723,5]]},"196":{"position":[[1106,5]]}},"keywords":{}}],["start_dat",{"_index":1001,"title":{},"content":{"23":{"position":[[277,10]]},"62":{"position":[[570,10]]},"90":{"position":[[3715,10],[3820,11]]}},"keywords":{}}],["start_date=start.strftime(q_format",{"_index":2857,"title":{},"content":{"88":{"position":[[810,36]]},"93":{"position":[[4225,36]]}},"keywords":{}}],["started"",{"_index":200,"title":{},"content":{"3":{"position":[[1230,13]]}},"keywords":{}}],["starter",{"_index":4131,"title":{},"content":{"125":{"position":[[6255,7],[7018,7]]}},"keywords":{}}],["state",{"_index":390,"title":{},"content":{"7":{"position":[[320,5],[405,6]]},"72":{"position":[[623,6]]},"95":{"position":[[412,5]]},"97":{"position":[[5497,5]]},"175":{"position":[[1022,6]]}},"keywords":{}}],["statement",{"_index":3274,"title":{},"content":{"93":{"position":[[4575,10]]}},"keywords":{}}],["static",{"_index":3344,"title":{"182":{"position":[[0,6]]}},"content":{"96":{"position":[[1474,6]]},"97":{"position":[[1135,6],[2009,8],[2535,7],[3094,6]]},"117":{"position":[[1534,7]]},"125":{"position":[[4825,6]]},"127":{"position":[[601,6],[1251,6]]},"129":{"position":[[1254,6],[1738,7]]},"133":{"position":[[306,6]]},"144":{"position":[[135,6]]},"145":{"position":[[111,6]]},"146":{"position":[[139,6]]},"152":{"position":[[1148,6],[1191,6]]},"156":{"position":[[1231,6],[1274,6]]},"182":{"position":[[1,6],[171,6],[205,7],[285,6],[381,7],[417,6],[486,6],[574,6],[681,6]]},"183":{"position":[[49,6],[157,6],[255,7],[296,6]]},"184":{"position":[[74,6],[175,6],[247,7],[286,6],[605,6],[687,6],[837,6],[1110,6]]},"185":{"position":[[37,6],[157,6],[421,8],[791,6]]},"186":{"position":[[16,6],[301,6]]},"197":{"position":[[41,6]]},"199":{"position":[[109,6],[269,6]]}},"keywords":{}}],["static>>>",{"_index":3784,"title":{},"content":{"115":{"position":[[2036,20],[2385,20]]},"116":{"position":[[1941,20],[2243,20]]}},"keywords":{}}],["staticthat",{"_index":4713,"title":{},"content":{"160":{"position":[[3906,10]]}},"keywords":{}}],["statist",{"_index":2319,"title":{"58":{"position":[[0,11]]}},"content":{"90":{"position":[[864,10],[2249,10]]},"102":{"position":[[619,13],[882,11]]},"189":{"position":[[1556,10]]}},"keywords":{}}],["stay",{"_index":117,"title":{},"content":{"2":{"position":[[645,6]]},"30":{"position":[[5616,5]]},"121":{"position":[[415,4]]},"122":{"position":[[478,7]]},"125":{"position":[[10895,4]]},"161":{"position":[[132,4]]},"186":{"position":[[102,4]]}},"keywords":{}}],["std",{"_index":1923,"title":{},"content":{"44":{"position":[[832,3]]},"90":{"position":[[4494,4]]}},"keywords":{}}],["std::alloc::system",{"_index":4369,"title":{},"content":{"133":{"position":[[266,19]]}},"keywords":{}}],["std::alloc::{globalalloc",{"_index":4511,"title":{},"content":{"152":{"position":[[376,25]]},"156":{"position":[[826,25]]}},"keywords":{}}],["std::borrow::cow",{"_index":4577,"title":{},"content":{"155":{"position":[[1321,17]]}},"keywords":{}}],["std::cell::refcel",{"_index":5068,"title":{},"content":{"179":{"position":[[367,19],[837,19]]},"180":{"position":[[347,19]]},"184":{"position":[[1002,19]]},"185":{"position":[[633,19]]}},"keywords":{}}],["std::cell::refcell<u8>",{"_index":5130,"title":{},"content":{"184":{"position":[[1039,30]]},"185":{"position":[[720,30]]}},"keywords":{}}],["std::collections::hashmap",{"_index":5379,"title":{},"content":{"199":{"position":[[1072,26]]}},"keywords":{}}],["std::marker::s",{"_index":3388,"title":{},"content":{"97":{"position":[[2018,19]]}},"keywords":{}}],["std::marker::send",{"_index":3774,"title":{},"content":{"115":{"position":[[969,18],[1316,18],[2057,18]]},"116":{"position":[[968,18],[1268,18],[1962,18]]}},"keywords":{}}],["std::marker::sync",{"_index":3782,"title":{},"content":{"115":{"position":[[1688,18]]},"116":{"position":[[1593,18]]}},"keywords":{}}],["std::ops::fn(&'r",{"_index":3383,"title":{},"content":{"97":{"position":[[1888,20]]}},"keywords":{}}],["std::ptr::read_volatile(&equ",{"_index":4521,"title":{},"content":{"152":{"position":[[946,36]]}},"keywords":{}}],["std::rc::rc",{"_index":4575,"title":{},"content":{"155":{"position":[[1284,12]]}},"keywords":{}}],["std::result::result<iron::respons",{"_index":3386,"title":{},"content":{"97":{"position":[[1948,38]]}},"keywords":{}}],["std::sync::arc",{"_index":4576,"title":{},"content":{"155":{"position":[[1301,15]]}},"keywords":{}}],["std::sync::atomic::{atomicbool",{"_index":4512,"title":{},"content":{"152":{"position":[[423,31]]},"156":{"position":[[873,31]]}},"keywords":{}}],["std::sync::onc",{"_index":5079,"title":{},"content":{"179":{"position":[[1228,16]]},"186":{"position":[[186,16]]}},"keywords":{}}],["std::thread::spawn(mov",{"_index":3779,"title":{},"content":{"115":{"position":[[1139,23],[1486,23],[1769,23],[2227,23]]},"116":{"position":[[726,23],[1091,23],[1391,23],[1674,23],[2085,23]]},"117":{"position":[[1583,23]]}},"keywords":{}}],["std::thread:spawn(mov",{"_index":3769,"title":{},"content":{"115":{"position":[[707,22]]}},"keywords":{}}],["std::vec::vec<std::option::option<std::boxed::box<capnp::private::capability::clienthook",{"_index":3783,"title":{},"content":{"115":{"position":[[1936,97],[2285,97]]},"116":{"position":[[1841,97],[2143,97]]}},"keywords":{}}],["std::vector",{"_index":4691,"title":{},"content":{"160":{"position":[[2369,11]]}},"keywords":{}}],["std_dev",{"_index":2989,"title":{},"content":{"90":{"position":[[1182,7],[1558,8],[1590,8],[1707,8],[1739,8],[2567,7],[2851,8],[2883,8]]}},"keywords":{}}],["stdweb",{"_index":4174,"title":{},"content":{"125":{"position":[[8804,6],[8901,7],[9209,6],[11169,7],[11300,6]]}},"keywords":{}}],["steel",{"_index":1819,"title":{},"content":{"40":{"position":[[2162,5]]}},"keywords":{}}],["step",{"_index":350,"title":{"25":{"position":[[9,4]]},"108":{"position":[[0,4]]},"109":{"position":[[0,4]]},"110":{"position":[[0,4]]},"111":{"position":[[0,4]]},"112":{"position":[[0,4]]},"113":{"position":[[0,4]]}},"content":{"6":{"position":[[737,5]]},"51":{"position":[[2830,6]]},"61":{"position":[[1329,5],[1406,5],[2091,4]]},"64":{"position":[[11,4]]},"65":{"position":[[230,6],[271,5],[2189,5]]},"108":{"position":[[816,4]]},"113":{"position":[[595,5]]},"125":{"position":[[7052,6],[8465,5]]},"160":{"position":[[760,4]]},"164":{"position":[[1263,5]]},"176":{"position":[[1534,5]]},"193":{"position":[[1232,4]]}},"keywords":{}}],["stick",{"_index":1215,"title":{},"content":{"28":{"position":[[570,5]]},"66":{"position":[[809,8]]},"128":{"position":[[1209,5]]},"165":{"position":[[1220,6]]}},"keywords":{}}],["still",{"_index":1402,"title":{},"content":{"30":{"position":[[4386,5],[5808,5]]},"32":{"position":[[126,6]]},"33":{"position":[[956,5]]},"34":{"position":[[488,5]]},"45":{"position":[[2551,5]]},"58":{"position":[[878,5]]},"66":{"position":[[503,6]]},"71":{"position":[[1192,5]]},"81":{"position":[[64,5]]},"82":{"position":[[1123,5]]},"83":{"position":[[487,5]]},"92":{"position":[[1473,5]]},"93":{"position":[[972,5]]},"101":{"position":[[144,5]]},"116":{"position":[[878,5],[910,5]]},"117":{"position":[[525,5]]},"122":{"position":[[233,5]]},"123":{"position":[[629,5],[967,5]]},"125":{"position":[[6193,5],[11044,5],[11438,5]]},"129":{"position":[[2778,5]]},"130":{"position":[[249,5]]},"139":{"position":[[53,5],[542,5]]},"147":{"position":[[450,5]]},"161":{"position":[[1183,5]]},"163":{"position":[[2374,6]]},"164":{"position":[[782,5]]},"165":{"position":[[486,5]]},"166":{"position":[[750,5]]},"179":{"position":[[1104,7],[1770,5]]},"186":{"position":[[401,5]]},"192":{"position":[[724,5]]},"193":{"position":[[2404,6],[3124,5]]}},"keywords":{}}],["stillblownaway",{"_index":2272,"title":{},"content":{"53":{"position":[[1449,15]]}},"keywords":{}}],["stl",{"_index":4693,"title":{},"content":{"160":{"position":[[2407,3]]}},"keywords":{}}],["stock",{"_index":460,"title":{},"content":{"9":{"position":[[155,5]]},"14":{"position":[[715,5],[800,5],[859,5],[970,5],[1052,5],[1137,5]]},"19":{"position":[[201,5]]},"20":{"position":[[1591,6]]},"32":{"position":[[211,5],[287,5]]},"33":{"position":[[774,5],[905,5],[1084,5],[1147,5]]},"34":{"position":[[514,5],[3128,5],[3652,5]]},"35":{"position":[[118,5]]},"38":{"position":[[185,5],[457,6]]},"39":{"position":[[177,7]]},"40":{"position":[[41,6],[695,5],[916,6],[1401,6],[2361,5],[3308,6],[3611,6]]},"88":{"position":[[32,5]]},"89":{"position":[[550,5],[696,5]]},"90":{"position":[[4910,5],[5174,5],[5358,5]]},"91":{"position":[[48,6],[1768,6],[3133,5],[4515,5],[5033,5],[5343,6],[5441,5],[5786,6]]},"92":{"position":[[104,6],[187,6],[945,5],[1351,6],[1572,6]]},"93":{"position":[[91,5],[270,5],[698,7],[877,6],[3272,5],[3747,5]]},"163":{"position":[[185,5]]}},"keywords":{}}],["stock'",{"_index":1562,"title":{},"content":{"32":{"position":[[2299,7]]},"93":{"position":[[160,7]]}},"keywords":{}}],["stocks?how",{"_index":2956,"title":{},"content":{"89":{"position":[[809,10]]}},"keywords":{}}],["stole",{"_index":4410,"title":{},"content":{"137":{"position":[[262,6]]}},"keywords":{}}],["stop",{"_index":1630,"title":{},"content":{"34":{"position":[[1835,5]]},"61":{"position":[[1165,4]]},"76":{"position":[[2231,5]]},"102":{"position":[[943,4]]},"115":{"position":[[2885,4]]},"125":{"position":[[10126,7]]},"172":{"position":[[2001,5]]}},"keywords":{}}],["storag",{"_index":3467,"title":{},"content":{"101":{"position":[[104,7],[889,7]]},"105":{"position":[[2610,7]]},"153":{"position":[[947,7]]}},"keywords":{}}],["store",{"_index":3579,"title":{},"content":{"105":{"position":[[426,5],[555,7],[659,6]]},"110":{"position":[[238,7]]},"117":{"position":[[763,7]]},"121":{"position":[[987,6]]},"156":{"position":[[416,5]]},"174":{"position":[[662,6]]},"178":{"position":[[553,6]]},"180":{"position":[[469,6]]},"192":{"position":[[220,6]]},"193":{"position":[[1558,6]]},"194":{"position":[[628,6]]},"196":{"position":[[834,5],[895,5],[1252,5]]},"197":{"position":[[205,6],[353,6],[499,6]]}},"keywords":{}}],["store_d",{"_index":3203,"title":{},"content":{"93":{"position":[[1491,11]]}},"keywords":{}}],["stori",{"_index":259,"title":{},"content":{"4":{"position":[[768,7]]},"164":{"position":[[49,6]]}},"keywords":{}}],["storm",{"_index":2241,"title":{},"content":{"53":{"position":[[998,7]]}},"keywords":{}}],["str",{"_index":3318,"title":{},"content":{"96":{"position":[[175,3],[1326,4]]}},"keywords":{}}],["strace",{"_index":4963,"title":{},"content":{"173":{"position":[[1309,6]]}},"keywords":{}}],["straight",{"_index":3184,"title":{},"content":{"92":{"position":[[1610,9]]},"121":{"position":[[1981,9]]},"125":{"position":[[1019,8]]},"175":{"position":[[124,8]]}},"keywords":{}}],["strang",{"_index":3350,"title":{},"content":{"96":{"position":[[1959,8]]},"97":{"position":[[4967,8]]},"106":{"position":[[57,9]]},"143":{"position":[[209,7]]},"157":{"position":[[19,7]]},"179":{"position":[[26,7]]}},"keywords":{}}],["strategi",{"_index":1509,"title":{"32":{"position":[[24,9]]}},"content":{"32":{"position":[[156,8]]},"34":{"position":[[114,8],[771,8],[822,8]]},"35":{"position":[[29,8],[150,8],[341,8],[364,8]]},"40":{"position":[[769,8],[1153,8],[1487,8]]},"41":{"position":[[46,8],[373,8]]},"46":{"position":[[427,8]]}},"keywords":{}}],["stream",{"_index":3653,"title":{},"content":{"106":{"position":[[552,10],[683,6],[710,6],[758,6],[898,6]]},"165":{"position":[[1044,9],[1176,6]]},"166":{"position":[[803,9]]}},"keywords":{}}],["street",{"_index":903,"title":{},"content":{"22":{"position":[[649,6]]}},"keywords":{}}],["stress",{"_index":5046,"title":{},"content":{"176":{"position":[[648,9]]}},"keywords":{}}],["strictli",{"_index":762,"title":{},"content":{"20":{"position":[[148,8]]}},"keywords":{}}],["strike",{"_index":559,"title":{},"content":{"13":{"position":[[537,6],[1026,7],[1056,6]]},"14":{"position":[[2060,7],[2090,6]]},"15":{"position":[[1728,7],[1758,6]]}},"keywords":{}}],["string",{"_index":947,"title":{"96":{"position":[[9,8]]}},"content":{"22":{"position":[[1646,8]]},"30":{"position":[[7665,6]]},"61":{"position":[[1628,6]]},"96":{"position":[[1,7],[88,7],[922,6],[1404,7],[1481,6],[2138,8]]},"97":{"position":[[1486,7],[3595,6]]},"98":{"position":[[224,7]]},"120":{"position":[[947,7]]},"129":{"position":[[1494,6]]},"136":{"position":[[632,7]]},"159":{"position":[[1067,7]]},"165":{"position":[[648,7],[819,6]]}},"keywords":{}}],["string::new",{"_index":4604,"title":{},"content":{"156":{"position":[[1858,14]]}},"keywords":{}}],["strip",{"_index":4443,"title":{},"content":{"143":{"position":[[389,5]]},"152":{"position":[[848,5]]},"153":{"position":[[89,9]]}},"keywords":{}}],["strong",{"_index":4,"title":{"1":{"position":[[9,7]]}},"content":{},"keywords":{}}],["struct",{"_index":3396,"title":{"192":{"position":[[0,8]]}},"content":{"97":{"position":[[2756,6],[3440,6],[3565,6],[3963,7]]},"110":{"position":[[457,6]]},"112":{"position":[[1299,8]]},"129":{"position":[[179,7],[1427,6]]},"152":{"position":[[1245,6]]},"153":{"position":[[527,6],[583,6],[642,6],[702,6],[844,7]]},"156":{"position":[[1328,6]]},"166":{"position":[[490,8]]},"184":{"position":[[113,6],[148,6],[507,6]]},"185":{"position":[[609,6],[653,6]]},"192":{"position":[[54,6],[115,6],[148,6]]},"193":{"position":[[906,6],[2211,6],[3177,6]]},"194":{"position":[[257,6]]},"195":{"position":[[209,6],[280,6],[356,6],[594,6]]},"197":{"position":[[384,6],[530,6]]},"198":{"position":[[442,9],[990,6],[1123,6]]}},"keywords":{}}],["structur",{"_index":143,"title":{"9":{"position":[[19,10]]},"10":{"position":[[22,10]]}},"content":{"3":{"position":[[200,11]]},"6":{"position":[[379,9]]},"7":{"position":[[196,10]]},"9":{"position":[[274,10],[348,10],[368,9],[624,9],[771,9]]},"10":{"position":[[29,10],[183,9]]},"11":{"position":[[27,9]]},"15":{"position":[[25,9]]},"53":{"position":[[2208,9]]},"110":{"position":[[529,9]]},"163":{"position":[[750,10]]},"190":{"position":[[215,11]]}},"keywords":{}}],["structure[1",{"_index":488,"title":{},"content":{"10":{"position":[[153,12]]}},"keywords":{}}],["structurethat",{"_index":4616,"title":{},"content":{"157":{"position":[[695,13]]}},"keywords":{}}],["struggl",{"_index":4690,"title":{},"content":{"160":{"position":[[2342,8],[2446,8]]}},"keywords":{}}],["stuck",{"_index":139,"title":{},"content":{"3":{"position":[[127,5]]},"135":{"position":[[609,5]]}},"keywords":{}}],["studi",{"_index":1292,"title":{"87":{"position":[[6,7]]},"90":{"position":[[6,8]]},"131":{"position":[[7,5]]}},"content":{"28":{"position":[[2742,8]]},"90":{"position":[[69,6]]},"91":{"position":[[35,5],[1635,6],[4346,5],[4964,6],[5151,5],[5528,5]]},"93":{"position":[[3785,8]]}},"keywords":{}}],["study_trend(3",{"_index":3173,"title":{},"content":{"91":{"position":[[5545,14]]},"92":{"position":[[1844,14]]}},"keywords":{}}],["study_trend(5",{"_index":3157,"title":{},"content":{"91":{"position":[[4352,14]]},"92":{"position":[[1127,14]]}},"keywords":{}}],["study_trend(8",{"_index":3169,"title":{},"content":{"91":{"position":[[5162,14]]},"92":{"position":[[1685,14]]}},"keywords":{}}],["study_trend(horizon",{"_index":3140,"title":{},"content":{"91":{"position":[[3319,20]]}},"keywords":{}}],["stuff",{"_index":3311,"title":{},"content":{"95":{"position":[[456,5]]},"106":{"position":[[1172,5]]},"113":{"position":[[1425,5]]},"129":{"position":[[602,5]]}},"keywords":{}}],["stump",{"_index":3367,"title":{},"content":{"97":{"position":[[874,7]]}},"keywords":{}}],["stun",{"_index":4004,"title":{},"content":{"125":{"position":[[33,7]]}},"keywords":{}}],["stunningli",{"_index":4030,"title":{},"content":{"125":{"position":[[860,10]]}},"keywords":{}}],["style",{"_index":3491,"title":{},"content":{"102":{"position":[[389,5]]},"125":{"position":[[1417,8]]}},"keywords":{}}],["sub",{"_index":4259,"title":{},"content":{"128":{"position":[[469,3],[1526,3]]},"129":{"position":[[527,3]]}},"keywords":{}}],["subject",{"_index":793,"title":{},"content":{"20":{"position":[[835,7]]},"176":{"position":[[1333,7]]}},"keywords":{}}],["substant",{"_index":3932,"title":{},"content":{"122":{"position":[[79,11]]}},"keywords":{}}],["subtl",{"_index":2612,"title":{},"content":{"71":{"position":[[1433,6]]},"199":{"position":[[51,6]]}},"keywords":{}}],["subtract",{"_index":2519,"title":{},"content":{"65":{"position":[[1490,8]]},"91":{"position":[[2954,8]]},"92":{"position":[[766,8]]},"193":{"position":[[1121,8]]}},"keywords":{}}],["success",{"_index":4005,"title":{},"content":{"125":{"position":[[48,7]]}},"keywords":{}}],["successfulli",{"_index":862,"title":{},"content":{"20":{"position":[[2796,14]]},"30":{"position":[[306,12]]},"153":{"position":[[984,13]]}},"keywords":{}}],["such",{"_index":3816,"title":{},"content":{"117":{"position":[[281,4]]},"150":{"position":[[697,4]]},"160":{"position":[[3836,5]]}},"keywords":{}}],["suck",{"_index":3854,"title":{},"content":{"120":{"position":[[610,4]]}},"keywords":{}}],["sudden",{"_index":3883,"title":{},"content":{"121":{"position":[[614,6]]}},"keywords":{}}],["suddenli",{"_index":1435,"title":{},"content":{"30":{"position":[[7701,8]]},"172":{"position":[[2438,8]]}},"keywords":{}}],["suffer",{"_index":2653,"title":{},"content":{"74":{"position":[[1423,7]]}},"keywords":{}}],["suffic",{"_index":3787,"title":{},"content":{"115":{"position":[[2539,7]]}},"keywords":{}}],["suffici",{"_index":2577,"title":{},"content":{"69":{"position":[[219,10]]},"152":{"position":[[85,12]]}},"keywords":{}}],["sum",{"_index":2570,"title":{},"content":{"68":{"position":[[864,3]]},"69":{"position":[[330,3],[390,3]]},"72":{"position":[[105,3],[167,3],[315,3],[368,3]]},"74":{"position":[[361,3],[459,3]]},"188":{"position":[[2661,3]]},"199":{"position":[[158,3],[230,3],[255,4],[322,3],[398,3],[417,4]]}},"keywords":{}}],["sum(abs(optimal.x",{"_index":858,"title":{},"content":{"20":{"position":[[2600,18],[2629,19]]}},"keywords":{}}],["sum(abs(x",{"_index":819,"title":{},"content":{"20":{"position":[[1472,10],[1539,11],[1751,10],[1772,11],[1862,11]]}},"keywords":{}}],["sum(invest",{"_index":1640,"title":{},"content":{"34":{"position":[[2278,12],[2327,13],[2524,12],[2654,13]]},"39":{"position":[[2104,13]]}},"keywords":{}}],["sum(investments[1:i",{"_index":1645,"title":{},"content":{"34":{"position":[[2754,22]]}},"keywords":{}}],["sum(purchase_histori",{"_index":1616,"title":{},"content":{"34":{"position":[[1265,20],[1489,20],[1560,21]]},"39":{"position":[[752,21]]}},"keywords":{}}],["sum(x",{"_index":831,"title":{},"content":{"20":{"position":[[1809,6],[1896,5]]}},"keywords":{}}],["sum_enumerate(x",{"_index":5382,"title":{},"content":{"199":{"position":[[1375,16]]}},"keywords":{}}],["sum_for",{"_index":5376,"title":{},"content":{"199":{"position":[[433,7]]}},"keywords":{}}],["sum_for(list<long>",{"_index":5371,"title":{},"content":{"199":{"position":[[120,24]]}},"keywords":{}}],["sum_foreach",{"_index":5377,"title":{},"content":{"199":{"position":[[492,12]]}},"keywords":{}}],["sum_foreach(list<long>",{"_index":5374,"title":{},"content":{"199":{"position":[[280,28]]}},"keywords":{}}],["sum_hm(x",{"_index":5384,"title":{},"content":{"199":{"position":[[1531,9]]}},"keywords":{}}],["sum_vec(x",{"_index":5380,"title":{},"content":{"199":{"position":[[1238,10]]}},"keywords":{}}],["sum_{i=1}^n",{"_index":1530,"title":{},"content":{"32":{"position":[[825,12]]},"74":{"position":[[1706,12]]}},"keywords":{}}],["sum_{i=1}^{n",{"_index":1532,"title":{},"content":{"32":{"position":[[859,14],[1576,13],[1640,13],[1703,13],[1786,13],[1866,13]]}},"keywords":{}}],["summar",{"_index":3187,"title":{},"content":{"93":{"position":[[37,9]]},"122":{"position":[[612,10]]}},"keywords":{}}],["summari",{"_index":1172,"title":{"35":{"position":[[0,8]]},"41":{"position":[[0,7]]},"46":{"position":[[0,7]]},"66":{"position":[[0,8]]},"93":{"position":[[15,8]]},"159":{"position":[[21,7]]}},"content":{"26":{"position":[[412,8]]},"30":{"position":[[7379,7]]},"90":{"position":[[856,7],[2241,7]]}},"keywords":{}}],["sun",{"_index":1336,"title":{},"content":{"30":{"position":[[490,4]]}},"keywords":{}}],["sunni",{"_index":1393,"title":{},"content":{"30":{"position":[[4090,5],[7586,6]]}},"keywords":{}}],["super",{"_index":1463,"title":{},"content":{"30":{"position":[[8729,5]]},"95":{"position":[[431,5]]},"96":{"position":[[96,5]]},"98":{"position":[[1182,5]]},"120":{"position":[[324,5]]},"121":{"position":[[2732,5]]},"130":{"position":[[12,5]]}},"keywords":{}}],["super().__init__(*arg",{"_index":935,"title":{},"content":{"22":{"position":[[1314,23]]},"93":{"position":[[1582,23]]}},"keywords":{}}],["supplier",{"_index":2949,"title":{},"content":{"89":{"position":[[283,9],[358,10]]}},"keywords":{}}],["support",{"_index":1715,"title":{"150":{"position":[[33,9]]}},"content":{"39":{"position":[[356,7]]},"120":{"position":[[137,7]]},"125":{"position":[[11204,7]]},"160":{"position":[[3799,9]]},"164":{"position":[[124,9]]},"165":{"position":[[81,7],[1054,7]]},"166":{"position":[[1,7],[523,10],[813,7]]},"172":{"position":[[2108,7]]}},"keywords":{}}],["supportsprofil",{"_index":4933,"title":{},"content":{"172":{"position":[[2234,15]]}},"keywords":{}}],["suppos",{"_index":5081,"title":{},"content":{"179":{"position":[[1318,8]]}},"keywords":{}}],["sure",{"_index":430,"title":{},"content":{"7":{"position":[[1073,4]]},"22":{"position":[[2710,4]]},"32":{"position":[[2172,4]]},"39":{"position":[[1789,4]]},"46":{"position":[[325,4]]},"61":{"position":[[500,4]]},"76":{"position":[[1372,4]]},"81":{"position":[[47,4]]},"85":{"position":[[499,4]]},"90":{"position":[[491,4]]},"91":{"position":[[3220,4]]},"92":{"position":[[1032,4]]},"108":{"position":[[228,4],[706,4]]},"110":{"position":[[120,4]]},"111":{"position":[[60,4]]},"113":{"position":[[2314,4]]},"116":{"position":[[2775,4]]},"117":{"position":[[542,4]]},"121":{"position":[[1902,4]]},"123":{"position":[[236,4]]},"125":{"position":[[11190,4]]},"156":{"position":[[1821,4]]},"158":{"position":[[453,4]]},"167":{"position":[[271,4]]},"173":{"position":[[1830,4]]},"175":{"position":[[471,4]]},"176":{"position":[[408,4]]}},"keywords":{}}],["surpris",{"_index":1313,"title":{},"content":{"29":{"position":[[29,9]]},"98":{"position":[[485,10]]},"179":{"position":[[1251,9]]}},"keywords":{}}],["surprise.call_onc",{"_index":5082,"title":{},"content":{"179":{"position":[[1338,21],[1539,21]]}},"keywords":{}}],["surprisingli",{"_index":1048,"title":{},"content":{"24":{"position":[[976,12]]},"25":{"position":[[696,12]]},"74":{"position":[[155,12]]},"82":{"position":[[1008,12]]}},"keywords":{}}],["survey",{"_index":1289,"title":{},"content":{"28":{"position":[[2679,8]]},"29":{"position":[[169,9]]},"43":{"position":[[1295,6]]}},"keywords":{}}],["surveyed.averag",{"_index":1310,"title":{},"content":{"28":{"position":[[4308,16]]}},"keywords":{}}],["surviv",{"_index":2695,"title":{},"content":{"76":{"position":[[954,9]]}},"keywords":{}}],["suspect",{"_index":2332,"title":{},"content":{"58":{"position":[[354,7]]}},"keywords":{}}],["sustain",{"_index":3983,"title":{},"content":{"123":{"position":[[745,10]]}},"keywords":{}}],["sveltekit",{"_index":214,"title":{},"content":{"3":{"position":[[1488,10]]}},"keywords":{}}],["swingdanc",{"_index":2219,"title":{},"content":{"53":{"position":[[632,11]]}},"keywords":{}}],["switch",{"_index":910,"title":{},"content":{"22":{"position":[[830,6]]},"75":{"position":[[728,6],[863,9],[1068,7]]},"76":{"position":[[2260,6],[2999,9],[3136,6]]},"97":{"position":[[2257,6]]},"173":{"position":[[1152,6],[1222,6],[1464,6],[1783,6]]},"175":{"position":[[1072,10],[1359,6],[1510,8],[1654,7]]},"176":{"position":[[271,9]]}},"keywords":{}}],["switch_failur",{"_index":2721,"title":{},"content":{"76":{"position":[[1936,15],[2386,15],[2912,15],[3221,15],[3247,15]]}},"keywords":{}}],["sy",{"_index":4175,"title":{},"content":{"125":{"position":[[8830,5],[9594,3],[9606,4],[11161,3],[11349,4],[11377,4]]},"188":{"position":[[1598,4],[1696,4],[2265,4],[2582,4],[3120,4]]},"189":{"position":[[1786,4],[2241,4],[2524,4],[2813,4]]}},"keywords":{}}],["symbol",{"_index":4827,"title":{},"content":{"165":{"position":[[640,7]]}},"keywords":{}}],["symbolsus",{"_index":4142,"title":{},"content":{"125":{"position":[[6633,11]]}},"keywords":{}}],["symmetri",{"_index":2569,"title":{},"content":{"68":{"position":[[811,9]]}},"keywords":{}}],["sync",{"_index":4154,"title":{"185":{"position":[[4,4]]}},"content":{"125":{"position":[[8054,4]]},"184":{"position":[[882,5],[954,5]]},"185":{"position":[[254,4],[327,4],[468,4],[589,4]]}},"keywords":{}}],["synchron",{"_index":4470,"title":{},"content":{"147":{"position":[[49,12]]},"157":{"position":[[552,15]]},"188":{"position":[[4235,11]]}},"keywords":{}}],["syntax",{"_index":3926,"title":{},"content":{"121":{"position":[[2660,6]]},"129":{"position":[[2540,6]]}},"keywords":{}}],["syntax"",{"_index":3898,"title":{},"content":{"121":{"position":[[1382,12]]}},"keywords":{}}],["syntaxerror",{"_index":4331,"title":{},"content":{"129":{"position":[[2519,12]]}},"keywords":{}}],["syscal",{"_index":4959,"title":{},"content":{"173":{"position":[[1103,11],[1364,8]]}},"keywords":{}}],["system",{"_index":266,"title":{"133":{"position":[[15,6]]},"171":{"position":[[29,7]]}},"content":{"4":{"position":[[874,6],[1417,7]]},"34":{"position":[[912,6]]},"59":{"position":[[76,7]]},"91":{"position":[[3905,12]]},"97":{"position":[[6460,6]]},"100":{"position":[[155,6]]},"130":{"position":[[461,7]]},"133":{"position":[[321,6],[330,7]]},"150":{"position":[[370,6],[654,7],[836,7]]},"152":{"position":[[410,8]]},"156":{"position":[[860,8]]},"160":{"position":[[532,7],[1109,6],[1381,6],[1945,6]]},"163":{"position":[[15,6]]},"166":{"position":[[154,8]]},"172":{"position":[[1294,6]]},"173":{"position":[[114,6],[169,6],[941,6],[1615,6],[1991,7]]},"174":{"position":[[415,8],[1142,7]]},"175":{"position":[[771,7]]},"176":{"position":[[18,8],[843,8],[959,6],[1431,7]]}},"keywords":{}}],["system.alloc(layout",{"_index":4534,"title":{},"content":{"152":{"position":[[1455,20]]},"156":{"position":[[1538,20]]}},"keywords":{}}],["system.dealloc(ptr",{"_index":4537,"title":{},"content":{"152":{"position":[[1624,19]]},"156":{"position":[[1707,19]]}},"keywords":{}}],["system.out.println(x.tostr",{"_index":4232,"title":{},"content":{"127":{"position":[[646,33],[777,33]]}},"keywords":{}}],["system.out.println(y.tostr",{"_index":4244,"title":{},"content":{"127":{"position":[[1328,33]]}},"keywords":{}}],["systemd",{"_index":4948,"title":{},"content":{"173":{"position":[[700,8]]}},"keywords":{}}],["t",{"_index":345,"title":{},"content":{"6":{"position":[[652,2],[963,1]]},"7":{"position":[[296,2],[341,1],[345,1],[562,2],[819,2],[842,1],[888,1]]},"9":{"position":[[428,2]]},"11":{"position":[[577,2]]},"12":{"position":[[245,2],[560,2]]},"13":{"position":[[732,1],[1341,2]]},"14":{"position":[[1589,1],[2413,2]]},"15":{"position":[[976,1],[2085,2]]},"93":{"position":[[3467,1],[3473,1]]}},"keywords":{}}],["t1",{"_index":1613,"title":{},"content":{"34":{"position":[[1222,2],[1348,2]]},"39":{"position":[[857,2],[987,2]]},"188":{"position":[[2060,2],[2428,2],[2966,2]]},"189":{"position":[[2091,2],[2372,2],[2661,2]]}},"keywords":{}}],["t1.join",{"_index":5184,"title":{},"content":{"188":{"position":[[2218,10],[2535,10],[3073,10]]},"189":{"position":[[2194,10],[2477,10],[2766,10]]}},"keywords":{}}],["t1.start",{"_index":5182,"title":{},"content":{"188":{"position":[[2162,11],[2512,11],[3050,11]]},"189":{"position":[[2171,11],[2454,11],[2743,11]]}},"keywords":{}}],["t2",{"_index":1615,"title":{},"content":{"34":{"position":[[1260,2],[1343,2]]},"39":{"position":[[895,2],[982,2]]},"188":{"position":[[2101,2],[2471,2],[3007,2]]},"189":{"position":[[2131,2],[2414,2],[2701,2]]}},"keywords":{}}],["t2.join",{"_index":5185,"title":{},"content":{"188":{"position":[[2229,9],[2546,9],[3084,9]]},"189":{"position":[[2205,9],[2488,9],[2777,9]]}},"keywords":{}}],["t2.start",{"_index":5183,"title":{},"content":{"188":{"position":[[2174,10],[2524,10],[3062,10]]},"189":{"position":[[2183,10],[2466,10],[2755,10]]}},"keywords":{}}],["t=.25",{"_index":446,"title":{},"content":{"8":{"position":[[115,5]]}},"keywords":{}}],["tabl",{"_index":3206,"title":{},"content":{"93":{"position":[[1681,8],[2223,8]]},"164":{"position":[[1421,6]]},"165":{"position":[[624,5],[658,5]]}},"keywords":{}}],["tabulasa",{"_index":3501,"title":{},"content":{"103":{"position":[[47,9],[517,8]]}},"keywords":{}}],["tabulasa.flac"",{"_index":3510,"title":{},"content":{"103":{"position":[[308,19]]}},"keywords":{}}],["tabulasa[:,0",{"_index":3538,"title":{},"content":{"103":{"position":[[1716,13]]}},"keywords":{}}],["tabulasa_left",{"_index":3537,"title":{},"content":{"103":{"position":[[1700,13]]}},"keywords":{}}],["tag",{"_index":888,"title":{},"content":{"22":{"position":[[322,4],[339,3],[449,3],[1389,4],[1405,3],[1611,3],[2293,5]]},"93":{"position":[[1658,4],[1674,3],[2207,5],[2216,3]]},"165":{"position":[[1354,3]]}},"keywords":{}}],["tag(enhanced_packet",{"_index":4791,"title":{},"content":{"163":{"position":[[1956,21]]}},"keywords":{}}],["take",{"_index":1185,"title":{},"content":{"26":{"position":[[851,6]]},"28":{"position":[[7,6]]},"30":{"position":[[7768,4]]},"32":{"position":[[1415,4]]},"34":{"position":[[3956,5]]},"38":{"position":[[250,5],[636,6]]},"40":{"position":[[3513,4]]},"41":{"position":[[176,6]]},"43":{"position":[[378,5]]},"44":{"position":[[2007,4]]},"45":{"position":[[589,4],[1027,4],[1337,4],[1391,4]]},"74":{"position":[[381,4]]},"86":{"position":[[404,4]]},"93":{"position":[[594,4]]},"96":{"position":[[235,4]]},"97":{"position":[[2695,4],[4100,4],[4697,4]]},"98":{"position":[[1213,4]]},"101":{"position":[[264,6],[1036,4]]},"106":{"position":[[285,5]]},"108":{"position":[[39,6]]},"120":{"position":[[311,4],[924,5]]},"121":{"position":[[378,4]]},"124":{"position":[[781,4]]},"125":{"position":[[1097,4],[1666,4],[9975,4],[10603,4]]},"128":{"position":[[1051,4]]},"137":{"position":[[237,4]]},"150":{"position":[[265,6]]},"161":{"position":[[464,6]]},"167":{"position":[[69,4]]},"168":{"position":[[56,5]]},"169":{"position":[[56,5]]},"172":{"position":[[871,5],[1130,4],[1557,5]]},"173":{"position":[[1056,6]]},"175":{"position":[[199,5]]},"182":{"position":[[54,4]]},"183":{"position":[[208,4]]},"188":{"position":[[1487,5],[1777,4]]},"189":{"position":[[1590,5],[1708,5],[1877,5],[2044,5]]}},"keywords":{}}],["take(captured_len)(remain",{"_index":4794,"title":{},"content":{"163":{"position":[[2069,31]]}},"keywords":{}}],["taken",{"_index":489,"title":{},"content":{"10":{"position":[[193,5]]},"51":{"position":[[3037,5]]},"52":{"position":[[662,5]]},"76":{"position":[[269,5]]},"93":{"position":[[455,5]]}},"keywords":{}}],["takeov",{"_index":3182,"title":{},"content":{"92":{"position":[[1440,8]]}},"keywords":{}}],["talk",{"_index":1319,"title":{},"content":{"29":{"position":[[437,4]]},"30":{"position":[[401,7]]},"32":{"position":[[52,7]]},"54":{"position":[[22,6]]},"97":{"position":[[2790,6],[2870,7]]},"121":{"position":[[470,7]]},"125":{"position":[[2036,7],[11292,4]]},"161":{"position":[[232,7]]},"166":{"position":[[84,6]]},"178":{"position":[[510,7]]},"184":{"position":[[13,4]]}},"keywords":{}}],["target",{"_index":3713,"title":{},"content":{"112":{"position":[[502,7],[908,6]]},"125":{"position":[[2737,7]]}},"keywords":{}}],["target/debug/build/capnp_cookbook_1",{"_index":3715,"title":{},"content":{"112":{"position":[[797,37]]}},"keywords":{}}],["target=wasm32",{"_index":4114,"title":{},"content":{"125":{"position":[[5227,13],[5775,13]]}},"keywords":{}}],["task",{"_index":1050,"title":{},"content":{"24":{"position":[[999,4]]},"25":{"position":[[719,4]]},"30":{"position":[[681,5]]}},"keywords":{}}],["taskset",{"_index":5043,"title":{},"content":{"176":{"position":[[321,7]]}},"keywords":{}}],["tcp",{"_index":5013,"title":{},"content":{"175":{"position":[[562,3]]}},"keywords":{}}],["td",{"_index":3284,"title":{},"content":{"93":{"position":[[4907,2],[4984,3],[5322,2],[5399,3]]}},"keywords":{}}],["td_back",{"_index":3029,"title":{},"content":{"90":{"position":[[3652,7],[3742,7]]}},"keywords":{}}],["td_back:event+td_forward",{"_index":3037,"title":{},"content":{"90":{"position":[[3876,26]]}},"keywords":{}}],["td_forward",{"_index":3031,"title":{},"content":{"90":{"position":[[3682,10],[3775,10]]}},"keywords":{}}],["teach",{"_index":1539,"title":{},"content":{"32":{"position":[[1367,5]]}},"keywords":{}}],["team",{"_index":4487,"title":{},"content":{"150":{"position":[[35,5],[683,5]]}},"keywords":{}}],["technic",{"_index":3823,"title":{},"content":{"117":{"position":[[730,11]]},"125":{"position":[[2967,11]]},"129":{"position":[[1176,9]]},"160":{"position":[[41,9]]},"161":{"position":[[284,10]]},"197":{"position":[[1566,11]]}},"keywords":{}}],["technician",{"_index":1573,"title":{},"content":{"33":{"position":[[418,11]]}},"keywords":{}}],["techniqu",{"_index":3490,"title":{},"content":{"102":{"position":[[69,9]]},"174":{"position":[[1207,9]]},"176":{"position":[[1483,10]]},"190":{"position":[[84,10]]}},"keywords":{}}],["technolog",{"_index":3195,"title":{},"content":{"93":{"position":[[866,10]]},"125":{"position":[[1779,10]]},"176":{"position":[[814,10]]}},"keywords":{}}],["tediou",{"_index":3738,"title":{},"content":{"113":{"position":[[796,8]]},"146":{"position":[[32,8]]},"163":{"position":[[777,7]]}},"keywords":{}}],["teeter",{"_index":2222,"title":{},"content":{"53":{"position":[[672,6]]}},"keywords":{}}],["tell",{"_index":1223,"title":{},"content":{"28":{"position":[[775,4]]},"32":{"position":[[2286,4]]},"33":{"position":[[50,5]]},"34":{"position":[[209,5],[924,5]]},"35":{"position":[[47,4]]},"44":{"position":[[1810,5]]},"73":{"position":[[778,4]]},"76":{"position":[[52,4]]},"91":{"position":[[4867,4]]},"101":{"position":[[1080,4]]},"111":{"position":[[691,5]]},"116":{"position":[[2471,7]]},"124":{"position":[[713,4]]},"153":{"position":[[343,4]]},"178":{"position":[[148,5]]}},"keywords":{}}],["temperatur",{"_index":4736,"title":{},"content":{"161":{"position":[[584,11],[712,12],[1298,11]]}},"keywords":{}}],["templat",{"_index":3988,"title":{},"content":{"123":{"position":[[1086,10]]}},"keywords":{}}],["tend",{"_index":241,"title":{},"content":{"4":{"position":[[432,4]]},"40":{"position":[[951,4]]},"82":{"position":[[1200,5]]}},"keywords":{}}],["tenth",{"_index":2813,"title":{},"content":{"83":{"position":[[284,5]]}},"keywords":{}}],["tenuou",{"_index":2326,"title":{},"content":{"58":{"position":[[195,7]]}},"keywords":{}}],["term",{"_index":328,"title":{"9":{"position":[[14,4]]},"10":{"position":[[17,4]]}},"content":{"6":{"position":[[373,5],[822,4]]},"7":{"position":[[191,4]]},"9":{"position":[[269,4],[363,4],[619,4]]},"10":{"position":[[24,4],[178,4]]},"11":{"position":[[22,4]]},"12":{"position":[[254,5],[569,5]]},"13":{"position":[[1350,5]]},"14":{"position":[[2422,5]]},"15":{"position":[[2094,5]]},"30":{"position":[[7509,5]]},"40":{"position":[[3322,5]]},"74":{"position":[[1403,6]]},"86":{"position":[[935,5],[1089,6]]},"100":{"position":[[82,4]]},"125":{"position":[[9891,5]]},"139":{"position":[[385,6]]},"155":{"position":[[219,4]]},"164":{"position":[[1580,5]]},"170":{"position":[[219,5]]},"175":{"position":[[1259,6]]}},"keywords":{}}],["term[1",{"_index":487,"title":{},"content":{"10":{"position":[[143,7],[457,7]]}},"keywords":{}}],["term[2",{"_index":486,"title":{},"content":{"10":{"position":[[132,7],[505,8],[514,11],[537,8],[583,8],[611,8]]}},"keywords":{}}],["term[i",{"_index":477,"title":{},"content":{"9":{"position":[[797,8]]}},"keywords":{}}],["term[i+1",{"_index":476,"title":{},"content":{"9":{"position":[[783,11]]}},"keywords":{}}],["termin",{"_index":861,"title":{},"content":{"20":{"position":[[2785,10]]}},"keywords":{}}],["terribl",{"_index":1163,"title":{},"content":{"25":{"position":[[2651,8]]},"40":{"position":[[2322,8]]},"45":{"position":[[2661,9],[2679,8]]},"97":{"position":[[803,8]]},"98":{"position":[[428,8]]},"106":{"position":[[152,8]]},"109":{"position":[[90,8]]},"150":{"position":[[911,8]]},"199":{"position":[[459,8]]}},"keywords":{}}],["territori",{"_index":15,"title":{},"content":{"1":{"position":[[144,10]]}},"keywords":{}}],["test",{"_index":871,"title":{"21":{"position":[[0,7]]}},"content":{"24":{"position":[[24,5]]},"34":{"position":[[3068,5]]},"35":{"position":[[350,5]]},"38":{"position":[[1307,5]]},"40":{"position":[[2567,5]]},"43":{"position":[[137,8]]},"45":{"position":[[1566,4]]},"86":{"position":[[466,7]]},"121":{"position":[[2043,4],[2218,5]]},"132":{"position":[[707,5]]},"158":{"position":[[438,5]]},"160":{"position":[[3622,5],[3710,4]]},"163":{"position":[[241,4]]},"166":{"position":[[838,7]]},"167":{"position":[[18,4]]},"168":{"position":[[6,4]]},"169":{"position":[[6,4]]},"181":{"position":[[820,7]]},"189":{"position":[[1662,5]]}},"keywords":{}}],["testingpackagingupdatesliter",{"_index":4200,"title":{},"content":{"125":{"position":[[10488,32]]}},"keywords":{}}],["text",{"_index":2072,"title":{},"content":{"51":{"position":[[156,4]]},"115":{"position":[[2517,4],[2611,4]]},"125":{"position":[[3446,4]]},"199":{"position":[[1164,5]]}},"keywords":{}}],["text.loc[~repli",{"_index":2077,"title":{},"content":{"51":{"position":[[277,18]]}},"keywords":{}}],["text.str.contain",{"_index":2075,"title":{},"content":{"51":{"position":[[241,22]]}},"keywords":{}}],["text_norep",{"_index":2076,"title":{},"content":{"51":{"position":[[264,10]]}},"keywords":{}}],["text_norep.map(tknzr.token",{"_index":2083,"title":{},"content":{"51":{"position":[[488,30]]}},"keywords":{}}],["text_norep.str.count",{"_index":2109,"title":{},"content":{"51":{"position":[[1687,25]]}},"keywords":{}}],["textual",{"_index":3062,"title":{},"content":{"90":{"position":[[4715,7]]}},"keywords":{}}],["thank",{"_index":2359,"title":{},"content":{"61":{"position":[[866,5]]},"66":{"position":[[798,6]]},"89":{"position":[[912,5]]},"118":{"position":[[329,7]]},"164":{"position":[[139,7]]}},"keywords":{}}],["thanthi",{"_index":3878,"title":{},"content":{"121":{"position":[[309,8]]}},"keywords":{}}],["that'",{"_index":1315,"title":{},"content":{"29":{"position":[[259,6]]},"34":{"position":[[1189,6]]},"40":{"position":[[1127,6]]},"43":{"position":[[985,6]]},"44":{"position":[[1968,6]]},"57":{"position":[[18,6]]},"64":{"position":[[246,6]]},"66":{"position":[[7,6]]},"96":{"position":[[1427,6]]},"101":{"position":[[137,6]]},"105":{"position":[[2858,6]]},"121":{"position":[[142,6]]},"122":{"position":[[798,6]]},"124":{"position":[[86,6],[162,6]]},"125":{"position":[[104,6],[3335,6],[3610,6]]},"128":{"position":[[385,6]]},"129":{"position":[[137,6]]},"133":{"position":[[347,6]]},"134":{"position":[[102,6]]},"160":{"position":[[1312,6],[2009,6],[3770,6]]},"161":{"position":[[1332,6]]},"176":{"position":[[1163,6],[1602,6]]},"180":{"position":[[331,6]]}},"keywords":{}}],["thatdirectli",{"_index":4840,"title":{},"content":{"166":{"position":[[208,12]]}},"keywords":{}}],["thatno",{"_index":5363,"title":{},"content":{"198":{"position":[[786,6]]}},"keywords":{}}],["thatsmp",{"_index":4967,"title":{},"content":{"173":{"position":[[1835,7]]}},"keywords":{}}],["thatstd::marker::send",{"_index":3810,"title":{},"content":{"116":{"position":[[2424,21]]}},"keywords":{}}],["the#[global_alloc",{"_index":4366,"title":{},"content":{"133":{"position":[[180,22]]}},"keywords":{}}],["the@jit",{"_index":5232,"title":{},"content":{"189":{"position":[[626,7]]}},"keywords":{}}],["thealloc",{"_index":4696,"title":{},"content":{"160":{"position":[[2534,8]]}},"keywords":{}}],["thebillion",{"_index":4227,"title":{},"content":{"127":{"position":[[395,10]]}},"keywords":{}}],["theblack_box",{"_index":4541,"title":{},"content":{"153":{"position":[[274,12]]}},"keywords":{}}],["thebox",{"_index":4652,"title":{},"content":{"160":{"position":[[290,6]]}},"keywords":{}}],["thebuild",{"_index":4111,"title":{},"content":{"125":{"position":[[5187,8],[5714,8]]}},"keywords":{}}],["thecompil",{"_index":4269,"title":{},"content":{"128":{"position":[[1221,11]]},"160":{"position":[[3812,11]]}},"keywords":{}}],["theconst",{"_index":5086,"title":{},"content":{"179":{"position":[[1635,8]]}},"keywords":{}}],["thecore::cel",{"_index":4570,"title":{},"content":{"155":{"position":[[861,13]]}},"keywords":{}}],["thecore::mem::size_ofdocument",{"_index":5319,"title":{},"content":{"194":{"position":[[799,35]]}},"keywords":{}}],["theembedonomicon",{"_index":4684,"title":{},"content":{"160":{"position":[[2075,16]]}},"keywords":{}}],["thefin",{"_index":4135,"title":{},"content":{"125":{"position":[[6358,8]]}},"keywords":{}}],["theglob",{"_index":4352,"title":{},"content":{"132":{"position":[[540,9]]}},"keywords":{}}],["theinterpret",{"_index":5201,"title":{},"content":{"188":{"position":[[3455,15]]}},"keywords":{}}],["thelanguag",{"_index":4017,"title":{},"content":{"125":{"position":[[526,11]]}},"keywords":{}}],["thelittleth",{"_index":2268,"title":{},"content":{"53":{"position":[[1367,16]]}},"keywords":{}}],["themain",{"_index":3913,"title":{},"content":{"121":{"position":[[2035,7]]}},"keywords":{}}],["themessag",{"_index":3377,"title":{},"content":{"97":{"position":[[1709,10]]}},"keywords":{}}],["themselv",{"_index":3814,"title":{},"content":{"116":{"position":[[3128,10]]},"185":{"position":[[306,10]]}},"keywords":{}}],["themultipli",{"_index":5101,"title":{},"content":{"181":{"position":[[462,11]]}},"keywords":{}}],["thenomicon",{"_index":5135,"title":{},"content":{"185":{"position":[[346,12]]}},"keywords":{}}],["theoret",{"_index":1683,"title":{"38":{"position":[[0,11]]}},"content":{"102":{"position":[[327,11]]},"129":{"position":[[2394,13]]},"172":{"position":[[2277,13]]}},"keywords":{}}],["thephantomdata",{"_index":3821,"title":{},"content":{"117":{"position":[[571,14]]}},"keywords":{}}],["theprocessor",{"_index":4950,"title":{},"content":{"173":{"position":[[790,12]]}},"keywords":{}}],["there'",{"_index":275,"title":{},"content":{"4":{"position":[[1040,7]]},"7":{"position":[[1081,7]]},"22":{"position":[[2979,7]]},"30":{"position":[[2760,7]]},"32":{"position":[[253,7]]},"41":{"position":[[57,7]]},"43":{"position":[[1152,7]]},"53":{"position":[[561,7],[1580,7]]},"68":{"position":[[48,7],[105,7]]},"101":{"position":[[1085,7]]},"103":{"position":[[2236,7],[2372,7]]},"106":{"position":[[525,7]]},"108":{"position":[[603,7]]},"115":{"position":[[2900,7]]},"118":{"position":[[39,7]]},"120":{"position":[[815,7]]},"122":{"position":[[49,7],[1089,7]]},"125":{"position":[[3368,7],[3476,7],[7572,7],[9900,7],[10383,7],[10725,7],[11284,7]]},"127":{"position":[[146,7],[1045,7]]},"128":{"position":[[1846,7]]},"135":{"position":[[574,7]]},"139":{"position":[[534,7]]},"148":{"position":[[7,7]]},"158":{"position":[[42,7],[244,7]]},"159":{"position":[[6,7]]},"160":{"position":[[0,7],[198,7],[320,7],[1924,7],[2037,7],[2830,7],[4240,7]]},"161":{"position":[[1175,7]]},"164":{"position":[[1243,7]]},"166":{"position":[[538,7]]},"172":{"position":[[1959,7]]},"174":{"position":[[219,7],[543,7]]},"175":{"position":[[10,7],[476,7],[1625,7]]},"184":{"position":[[760,7]]},"194":{"position":[[706,7]]},"199":{"position":[[41,7],[1102,7]]}},"keywords":{}}],["thereof",{"_index":4700,"title":{},"content":{"160":{"position":[[3025,8]]}},"keywords":{}}],["theseto",{"_index":4961,"title":{},"content":{"173":{"position":[[1268,7]]}},"keywords":{}}],["thestandard",{"_index":3939,"title":{},"content":{"122":{"position":[[354,11]]}},"keywords":{}}],["thesub",{"_index":5270,"title":{},"content":{"192":{"position":[[681,6]]}},"keywords":{}}],["thesync",{"_index":5113,"title":{},"content":{"182":{"position":[[606,7]]},"185":{"position":[[74,7]]}},"keywords":{}}],["they'r",{"_index":1334,"title":{},"content":{"30":{"position":[[453,7]]},"66":{"position":[[375,7]]},"121":{"position":[[2691,7]]},"127":{"position":[[1092,7]]},"135":{"position":[[220,7]]},"150":{"position":[[238,7]]},"158":{"position":[[320,7]]},"176":{"position":[[131,7]]},"185":{"position":[[98,7]]},"190":{"position":[[263,7]]}},"keywords":{}}],["they'v",{"_index":3071,"title":{},"content":{"91":{"position":[[68,7]]}},"keywords":{}}],["thing",{"_index":374,"title":{"143":{"position":[[8,6]]}},"content":{"7":{"position":[[9,6]]},"9":{"position":[[64,6]]},"12":{"position":[[324,6]]},"23":{"position":[[204,6]]},"28":{"position":[[2499,6]]},"33":{"position":[[83,7],[300,6]]},"34":{"position":[[76,6],[3624,6]]},"38":{"position":[[624,6],[1218,6],[1344,6]]},"39":{"position":[[388,6]]},"40":{"position":[[3095,7]]},"49":{"position":[[55,7]]},"59":{"position":[[178,7]]},"60":{"position":[[92,6]]},"73":{"position":[[603,5]]},"82":{"position":[[94,6]]},"91":{"position":[[4690,7]]},"93":{"position":[[28,5]]},"96":{"position":[[71,6]]},"97":{"position":[[856,5],[959,5],[1188,6],[4956,6]]},"98":{"position":[[294,6]]},"104":{"position":[[523,6],[1563,7]]},"105":{"position":[[563,6]]},"112":{"position":[[1074,6],[1265,6]]},"116":{"position":[[2446,5],[3095,6]]},"117":{"position":[[586,5],[751,5],[2005,6]]},"118":{"position":[[63,6]]},"120":{"position":[[652,7]]},"121":{"position":[[344,5],[854,6],[1974,6],[2130,6]]},"123":{"position":[[122,6],[875,6]]},"125":{"position":[[79,7],[2025,6],[2473,6],[2898,6],[3636,5],[3911,6],[4064,5],[4661,6],[9944,7],[10463,6],[10955,6],[11029,6]]},"127":{"position":[[854,6],[1540,6]]},"129":{"position":[[1418,7],[1784,5]]},"130":{"position":[[402,6]]},"132":{"position":[[687,6]]},"135":{"position":[[660,5]]},"139":{"position":[[736,6]]},"141":{"position":[[121,6]]},"142":{"position":[[242,6]]},"143":{"position":[[235,6]]},"150":{"position":[[50,6]]},"155":{"position":[[11,5]]},"160":{"position":[[1998,6],[2688,5]]},"179":{"position":[[275,6]]},"180":{"position":[[10,5]]},"184":{"position":[[402,6]]},"193":{"position":[[679,6]]},"195":{"position":[[674,6]]},"196":{"position":[[1662,6]]}},"keywords":{}}],["thing"",{"_index":3949,"title":{},"content":{"122":{"position":[[900,11]]}},"keywords":{}}],["things"",{"_index":4213,"title":{},"content":{"125":{"position":[[11477,12]]}},"keywords":{}}],["think",{"_index":68,"title":{},"content":{"1":{"position":[[754,8]]},"22":{"position":[[2731,5]]},"28":{"position":[[2477,5]]},"29":{"position":[[338,5]]},"30":{"position":[[4614,8]]},"40":{"position":[[564,5]]},"53":{"position":[[611,5]]},"58":{"position":[[79,5]]},"66":{"position":[[369,5],[512,5],[643,5]]},"69":{"position":[[279,5]]},"88":{"position":[[63,8]]},"95":{"position":[[506,5]]},"97":{"position":[[514,6]]},"98":{"position":[[1171,5]]},"104":{"position":[[196,5]]},"105":{"position":[[3358,5]]},"106":{"position":[[15,5],[1088,5]]},"112":{"position":[[269,5]]},"121":{"position":[[1693,5],[1783,5]]},"122":{"position":[[852,8]]},"123":{"position":[[490,5]]},"125":{"position":[[500,5],[3604,5],[6954,5],[10969,5],[11678,5]]},"128":{"position":[[176,6]]},"129":{"position":[[925,8],[2060,5]]},"130":{"position":[[548,8]]}},"keywords":{}}],["thinkfinance,r",{"_index":4423,"title":{},"content":{"139":{"position":[[600,17]]}},"keywords":{}}],["thinkingtoomuch",{"_index":2274,"title":{},"content":{"53":{"position":[[1471,16]]}},"keywords":{}}],["third",{"_index":2133,"title":{},"content":{"51":{"position":[[2685,5]]},"52":{"position":[[234,5],[422,6]]},"125":{"position":[[10043,6]]}},"keywords":{}}],["thirti",{"_index":291,"title":{},"content":{"4":{"position":[[1349,6]]}},"keywords":{}}],["this"virtu",{"_index":4682,"title":{},"content":{"160":{"position":[[1967,17]]}},"keywords":{}}],["this.i'v",{"_index":4718,"title":{},"content":{"160":{"position":[[4123,9]]}},"keywords":{}}],["those",{"_index":416,"title":{},"content":{"7":{"position":[[781,5]]},"11":{"position":[[243,5]]},"32":{"position":[[660,5]]},"44":{"position":[[144,5]]},"61":{"position":[[75,5]]},"74":{"position":[[111,5]]},"88":{"position":[[2148,5]]},"89":{"position":[[347,5]]},"102":{"position":[[550,5]]},"111":{"position":[[728,5]]},"112":{"position":[[1761,6]]},"123":{"position":[[801,5]]},"125":{"position":[[1365,5],[8289,6]]},"128":{"position":[[1551,5]]},"129":{"position":[[330,5]]},"135":{"position":[[283,5]]},"159":{"position":[[1244,6]]},"160":{"position":[[2389,5]]},"188":{"position":[[4525,5]]},"193":{"position":[[161,5]]}},"keywords":{}}],["though",{"_index":135,"title":{},"content":{"3":{"position":[[36,6]]},"24":{"position":[[3259,6]]},"26":{"position":[[550,7]]},"28":{"position":[[556,7]]},"30":{"position":[[2801,6],[4293,7],[5797,7]]},"33":{"position":[[24,7]]},"40":{"position":[[871,6]]},"41":{"position":[[100,6]]},"43":{"position":[[977,7]]},"51":{"position":[[2714,7]]},"53":{"position":[[2196,7]]},"66":{"position":[[66,7],[735,7]]},"68":{"position":[[204,7]]},"73":{"position":[[33,7]]},"82":{"position":[[1165,7]]},"97":{"position":[[1825,7],[4806,7]]},"105":{"position":[[2830,7]]},"108":{"position":[[333,7]]},"112":{"position":[[1104,6]]},"115":{"position":[[2647,7]]},"116":{"position":[[2408,7]]},"121":{"position":[[2588,7]]},"122":{"position":[[125,7]]},"125":{"position":[[9849,6]]},"129":{"position":[[2596,7]]},"145":{"position":[[273,6]]},"155":{"position":[[661,6]]},"160":{"position":[[2313,7]]},"179":{"position":[[441,6],[789,7]]},"181":{"position":[[17,7]]},"184":{"position":[[451,7],[1231,7]]},"185":{"position":[[435,6]]},"188":{"position":[[3169,6]]},"195":{"position":[[465,6]]},"196":{"position":[[1453,6],[1881,7]]},"197":{"position":[[1184,6]]},"198":{"position":[[203,7]]}},"keywords":{}}],["thought",{"_index":1970,"title":{"176":{"position":[[6,9]]}},"content":{"45":{"position":[[632,7]]},"98":{"position":[[1263,8]]},"112":{"position":[[1323,7]]}},"keywords":{}}],["thoughther",{"_index":3961,"title":{},"content":{"122":{"position":[[1301,11]]}},"keywords":{}}],["thread",{"_index":85,"title":{},"content":{"2":{"position":[[150,7],[212,6]]},"115":{"position":[[492,7],[622,6],[1224,7],[1604,7],[1881,7],[2429,7],[2682,7],[2875,6],[2976,6],[3006,6]]},"116":{"position":[[155,8],[698,7],[1176,7],[1509,7],[1786,7],[2287,7],[2587,6],[2720,6],[2806,6],[3021,7],[3143,6],[3182,6],[3269,8]]},"117":{"position":[[369,8],[435,8],[991,8],[1979,7]]},"143":{"position":[[139,6]]},"173":{"position":[[903,9]]},"184":{"position":[[1095,7]]},"185":{"position":[[183,6],[776,7]]},"188":{"position":[[652,7],[1885,8],[1956,6],[2001,9],[2018,6],[2042,7],[2154,7],[2200,7],[2334,6],[2370,6],[2691,8],[2866,7],[3187,6],[3348,8],[3417,6],[3484,6],[3697,6]]},"189":{"position":[[2010,8],[2313,6],[2339,7],[2613,6]]}},"keywords":{}}],["thread'",{"_index":3768,"title":{},"content":{"115":{"position":[[584,8]]}},"keywords":{}}],["thread(target=cython_gil",{"_index":5180,"title":{},"content":{"188":{"position":[[2065,25],[2106,25],[2476,25],[2971,25]]}},"keywords":{}}],["thread(target=cython_nogil",{"_index":5190,"title":{},"content":{"188":{"position":[[2433,27],[3012,27]]}},"keywords":{}}],["thread(target=numba_gil",{"_index":5244,"title":{},"content":{"189":{"position":[[2096,24],[2136,24],[2419,24],[2666,24]]}},"keywords":{}}],["thread(target=numba_nogil",{"_index":5248,"title":{},"content":{"189":{"position":[[2377,26],[2706,26]]}},"keywords":{}}],["thread::current().id",{"_index":4614,"title":{},"content":{"157":{"position":[[652,22]]}},"keywords":{}}],["thread_id",{"_index":4613,"title":{},"content":{"157":{"position":[[581,9]]}},"keywords":{}}],["three",{"_index":148,"title":{},"content":{"3":{"position":[[337,5]]},"90":{"position":[[4934,5]]},"139":{"position":[[88,5]]},"143":{"position":[[512,5]]},"160":{"position":[[840,5]]}},"keywords":{}}],["threshold",{"_index":1959,"title":{},"content":{"45":{"position":[[86,9],[2612,10]]}},"keywords":{}}],["through",{"_index":64,"title":{},"content":{"1":{"position":[[708,7]]},"4":{"position":[[629,7]]},"7":{"position":[[1129,7]]},"11":{"position":[[122,7]]},"45":{"position":[[536,7]]},"58":{"position":[[122,7]]},"61":{"position":[[1317,7]]},"62":{"position":[[150,7],[323,7],[1751,7]]},"65":{"position":[[2151,7]]},"72":{"position":[[442,7]]},"74":{"position":[[413,7]]},"77":{"position":[[10,7]]},"91":{"position":[[4012,8]]},"111":{"position":[[156,7]]},"121":{"position":[[2642,7]]},"122":{"position":[[934,7]]},"152":{"position":[[606,7]]},"160":{"position":[[2157,7]]},"164":{"position":[[621,7]]}},"keywords":{}}],["through"design",{"_index":5034,"title":{},"content":{"175":{"position":[[1488,21]]}},"keywords":{}}],["throughout",{"_index":1444,"title":{},"content":{"30":{"position":[[8169,10]]},"66":{"position":[[299,10]]},"86":{"position":[[441,10]]}},"keywords":{}}],["throw",{"_index":1965,"title":{},"content":{"45":{"position":[[293,5]]},"82":{"position":[[118,7]]}},"keywords":{}}],["thrown",{"_index":1398,"title":{},"content":{"30":{"position":[[4270,6]]},"66":{"position":[[467,6]]}},"keywords":{}}],["thu",{"_index":511,"title":{},"content":{"11":{"position":[[277,5]]},"72":{"position":[[610,4]]},"93":{"position":[[772,4]]},"122":{"position":[[532,4]]},"125":{"position":[[4691,4]]},"160":{"position":[[2554,4]]},"188":{"position":[[3272,5]]},"194":{"position":[[650,5]]},"198":{"position":[[830,5]]}},"keywords":{}}],["thumb",{"_index":3920,"title":{},"content":{"121":{"position":[[2281,5]]}},"keywords":{}}],["thursdaysgohard",{"_index":2199,"title":{},"content":{"53":{"position":[[215,16]]}},"keywords":{}}],["ti",{"_index":3721,"title":{},"content":{"112":{"position":[[1198,4]]},"129":{"position":[[63,4]]}},"keywords":{}}],["tic",{"_index":534,"title":{},"content":{"12":{"position":[[534,5]]},"13":{"position":[[1505,5]]},"14":{"position":[[2577,5]]},"15":{"position":[[2249,5]]}},"keywords":{}}],["tick",{"_index":412,"title":{"56":{"position":[[0,4]]}},"content":{"7":{"position":[[694,5],[789,5]]},"17":{"position":[[259,6],[318,4]]},"18":{"position":[[87,6],[129,4],[186,4]]},"19":{"position":[[366,6],[399,4]]},"20":{"position":[[282,6],[317,4],[1247,5],[1316,5],[1408,5]]}},"keywords":{}}],["tick_width",{"_index":424,"title":{},"content":{"7":{"position":[[927,10]]}},"keywords":{}}],["ticker",{"_index":709,"title":{},"content":{"17":{"position":[[144,7],[326,8]]},"18":{"position":[[37,6],[137,8],[194,9]]},"19":{"position":[[139,6],[407,8]]},"20":{"position":[[325,8],[1268,10],[1339,10],[1436,10]]},"39":{"position":[[3114,6],[3124,8]]},"88":{"position":[[802,7]]},"91":{"position":[[2159,8],[2297,7],[2805,7],[3428,7],[3561,7]]},"92":{"position":[[617,7]]},"93":{"position":[[2312,6],[2960,7],[4217,7],[4618,7],[4696,6],[4783,7],[5112,6],[5198,7],[5528,7]]}},"keywords":{}}],["ticker.replac",{"_index":3280,"title":{},"content":{"93":{"position":[[4799,19],[5214,19]]}},"keywords":{}}],["ticker_d",{"_index":3119,"title":{},"content":{"91":{"position":[[2275,12]]}},"keywords":{}}],["ticker_data",{"_index":2855,"title":{},"content":{"88":{"position":[[766,11],[909,11]]},"91":{"position":[[2761,11],[3517,11]]},"92":{"position":[[573,11]]},"93":{"position":[[4181,11],[4324,11]]}},"keywords":{}}],["ticker_data[ev",{"_index":3130,"title":{},"content":{"91":{"position":[[2820,17],[3582,17]]},"92":{"position":[[632,17]]}},"keywords":{}}],["ticker_dates.append((tick",{"_index":3123,"title":{},"content":{"91":{"position":[[2367,28]]}},"keywords":{}}],["ticker_info",{"_index":1624,"title":{},"content":{"34":{"position":[[1641,11]]},"39":{"position":[[2202,11]]}},"keywords":{}}],["ticker_info.column",{"_index":1753,"title":{},"content":{"39":{"position":[[2372,20]]}},"keywords":{}}],["ticker_info["close"].valu",{"_index":1629,"title":{},"content":{"34":{"position":[[1762,37]]}},"keywords":{}}],["ticker_info["open"].valu",{"_index":1628,"title":{},"content":{"34":{"position":[[1712,36]]}},"keywords":{}}],["ticker_info[:end].index",{"_index":1747,"title":{},"content":{"39":{"position":[[2281,23]]}},"keywords":{}}],["ticker_info[d:][close_column",{"_index":1758,"title":{},"content":{"39":{"position":[[2532,30]]}},"keywords":{}}],["time",{"_index":245,"title":{},"content":{"4":{"position":[[553,4]]},"6":{"position":[[312,4],[395,4],[998,4]]},"7":{"position":[[56,5]]},"11":{"position":[[146,4],[208,5],[249,5]]},"12":{"position":[[575,4],[639,5],[648,4]]},"13":{"position":[[923,4],[1538,4],[1607,5],[1648,5],[1965,5],[2021,5],[2077,5],[2133,5],[2189,5]]},"14":{"position":[[1941,4],[2621,4],[2690,5],[2731,5],[3037,5],[3093,5],[3149,5],[3205,5],[3261,5]]},"15":{"position":[[204,6],[1609,4],[2295,4],[2364,5],[2405,5],[2708,5],[2764,5],[2820,5],[2876,5],[2932,5]]},"20":{"position":[[2311,5]]},"28":{"position":[[19,4],[4406,5]]},"30":{"position":[[2379,5],[4099,4]]},"32":{"position":[[418,4],[1107,5]]},"38":{"position":[[212,5]]},"40":{"position":[[866,4],[1451,5]]},"43":{"position":[[1319,4]]},"45":{"position":[[1349,4]]},"46":{"position":[[629,5],[676,5]]},"49":{"position":[[263,4]]},"51":{"position":[[1499,4],[2612,4],[3540,4]]},"53":{"position":[[1410,4]]},"57":{"position":[[579,4],[703,4]]},"58":{"position":[[299,5]]},"61":{"position":[[447,5],[1207,4]]},"62":{"position":[[70,4],[264,5]]},"64":{"position":[[1999,5]]},"66":{"position":[[313,4],[572,4],[777,4],[886,5]]},"75":{"position":[[1167,5]]},"76":{"position":[[2282,5]]},"78":{"position":[[106,4],[376,5],[972,5]]},"79":{"position":[[176,5]]},"80":{"position":[[198,5]]},"81":{"position":[[177,5]]},"82":{"position":[[976,5]]},"86":{"position":[[1110,4]]},"88":{"position":[[146,4]]},"91":{"position":[[4476,5],[4490,5],[4982,4],[5075,4],[5286,5],[5300,5],[5669,5],[5683,5]]},"92":{"position":[[1249,5],[1263,5],[1807,5],[1821,5],[1966,5],[1980,5]]},"93":{"position":[[305,5],[1176,5]]},"96":{"position":[[1359,4],[1897,4],[2041,5]]},"97":{"position":[[2101,4],[5290,4]]},"100":{"position":[[294,4]]},"102":{"position":[[1535,5]]},"104":{"position":[[1385,5]]},"105":{"position":[[2594,5]]},"109":{"position":[[40,4]]},"111":{"position":[[10,4]]},"113":{"position":[[95,4],[1517,4]]},"116":{"position":[[2403,4]]},"120":{"position":[[149,4],[336,4],[768,4],[937,4]]},"121":{"position":[[882,4],[964,5],[2158,5]]},"123":{"position":[[922,4]]},"124":{"position":[[812,5]]},"125":{"position":[[455,4],[9985,4]]},"127":{"position":[[1448,4]]},"129":{"position":[[10,4]]},"135":{"position":[[166,4]]},"136":{"position":[[613,4],[806,4]]},"139":{"position":[[466,4],[618,4],[725,4]]},"145":{"position":[[5,5]]},"156":{"position":[[311,5]]},"157":{"position":[[64,4]]},"160":{"position":[[310,5],[3887,4]]},"161":{"position":[[100,4],[1221,5],[1704,5]]},"164":{"position":[[10,4]]},"167":{"position":[[52,4]]},"170":{"position":[[386,4]]},"172":{"position":[[877,4],[1135,4],[1739,4],[2125,4]]},"175":{"position":[[1270,4]]},"176":{"position":[[1088,5],[1272,5]]},"178":{"position":[[353,4]]},"179":{"position":[[1494,5]]},"180":{"position":[[202,5]]},"182":{"position":[[526,4]]},"184":{"position":[[991,5]]},"185":{"position":[[197,5]]},"188":{"position":[[1470,4],[1546,6],[1578,6],[1628,5],[1642,6],[1676,6],[1726,5],[1813,4],[1922,4],[1982,5],[1989,6],[2245,6],[2298,5],[2421,6],[2562,6],[2614,5],[2641,4],[2679,4],[2907,6],[3100,6],[3150,5]]},"189":{"position":[[349,4],[934,4],[1549,6],[1736,6],[1766,6],[1818,5],[1893,4],[2084,6],[2221,6],[2274,5],[2365,6],[2504,6],[2557,5],[2654,6],[2793,6],[2843,5]]}},"keywords":{}}],["time"",{"_index":1799,"title":{},"content":{"40":{"position":[[528,11],[2064,11],[3008,11]]},"188":{"position":[[2739,10]]}},"keywords":{}}],["time.perf_count",{"_index":2754,"title":{},"content":{"78":{"position":[[233,19],[324,19]]}},"keywords":{}}],["time.th",{"_index":5061,"title":{},"content":{"178":{"position":[[677,8]]}},"keywords":{}}],["timedelta",{"_index":708,"title":{},"content":{"17":{"position":[[134,9]]},"65":{"position":[[2308,9]]},"90":{"position":[[359,9]]},"93":{"position":[[1331,9],[3918,9]]}},"keywords":{}}],["timedelta(day",{"_index":3217,"title":{},"content":{"93":{"position":[[2164,15]]}},"keywords":{}}],["timedelta(days=0",{"_index":3216,"title":{},"content":{"93":{"position":[[2095,17]]}},"keywords":{}}],["timedelta(days=1",{"_index":3042,"title":{},"content":{"90":{"position":[[4066,17]]}},"keywords":{}}],["timedelta(days=20",{"_index":3285,"title":{},"content":{"93":{"position":[[4912,18],[5327,18]]}},"keywords":{}}],["timedelta(minutes=minutes_left",{"_index":2532,"title":{},"content":{"65":{"position":[[2399,31]]}},"keywords":{}}],["timestamp",{"_index":4772,"title":{},"content":{"163":{"position":[[1253,9],[1343,9]]},"173":{"position":[[1291,9]]}},"keywords":{}}],["timestamp_high",{"_index":4786,"title":{},"content":{"163":{"position":[[1884,15]]}},"keywords":{}}],["timestamp_low",{"_index":4787,"title":{},"content":{"163":{"position":[[1900,14]]}},"keywords":{}}],["timestr",{"_index":4391,"title":{},"content":{"136":{"position":[[400,8]]}},"keywords":{}}],["titl",{"_index":2819,"title":{},"content":{"85":{"position":[[43,5],[101,5]]},"161":{"position":[[322,5]]}},"keywords":{}}],["tknzr",{"_index":2082,"title":{},"content":{"51":{"position":[[454,5]]}},"keywords":{}}],["tlb",{"_index":4987,"title":{},"content":{"174":{"position":[[654,3],[807,3]]},"176":{"position":[[662,4]]}},"keywords":{}}],["tldr",{"_index":3664,"title":{},"content":{"108":{"position":[[328,4]]}},"keywords":{}}],["to:router.get("/"",{"_index":3436,"title":{},"content":{"97":{"position":[[6393,28]]}},"keywords":{}}],["to_str",{"_index":4273,"title":{},"content":{"128":{"position":[[1919,12]]}},"keywords":{}}],["to_string(&self",{"_index":4297,"title":{},"content":{"129":{"position":[[1467,20]]}},"keywords":{}}],["to_string()i",{"_index":4294,"title":{},"content":{"129":{"position":[[1238,13]]}},"keywords":{}}],["tock",{"_index":2304,"title":{"56":{"position":[[5,7]]}},"content":{},"keywords":{}}],["today",{"_index":2253,"title":{},"content":{"53":{"position":[[1174,6],[2117,6]]},"98":{"position":[[330,6]]},"148":{"position":[[342,6]]}},"keywords":{}}],["today'",{"_index":1739,"title":{},"content":{"39":{"position":[[1840,7]]}},"keywords":{}}],["todays_purchas",{"_index":1636,"title":{},"content":{"34":{"position":[[2098,15],[2217,15]]},"39":{"position":[[1311,15],[1437,15]]}},"keywords":{}}],["todo",{"_index":860,"title":{},"content":{"20":{"position":[[2736,5]]}},"keywords":{}}],["togeth",{"_index":514,"title":{"52":{"position":[[15,9]]}},"content":{"11":{"position":[[325,9]]},"40":{"position":[[3135,8]]},"52":{"position":[[538,9]]},"74":{"position":[[1360,8]]},"76":{"position":[[1876,9]]},"95":{"position":[[462,9]]},"125":{"position":[[10179,8]]},"129":{"position":[[77,9]]},"130":{"position":[[355,9]]}},"keywords":{}}],["token",{"_index":2079,"title":{},"content":{"51":{"position":[[357,8],[479,6],[1152,7]]},"61":{"position":[[1674,8],[2269,5]]}},"keywords":{}}],["token_typ",{"_index":2405,"title":{},"content":{"62":{"position":[[520,13]]}},"keywords":{}}],["tokens.map(lambda",{"_index":2085,"title":{},"content":{"51":{"position":[[533,17]]}},"keywords":{}}],["told",{"_index":1205,"title":{},"content":{"28":{"position":[[219,4]]},"34":{"position":[[831,4]]},"43":{"position":[[1245,4]]},"121":{"position":[[1342,4]]},"125":{"position":[[2572,5]]}},"keywords":{}}],["tomak",{"_index":4400,"title":{},"content":{"136":{"position":[[814,6]]}},"keywords":{}}],["tomorrow",{"_index":1587,"title":{},"content":{"33":{"position":[[1124,8]]},"34":{"position":[[614,9]]}},"keywords":{}}],["tomorrow'",{"_index":1740,"title":{},"content":{"39":{"position":[[1857,10]]}},"keywords":{}}],["ton",{"_index":4799,"title":{},"content":{"163":{"position":[[2481,4]]},"164":{"position":[[219,3]]},"188":{"position":[[261,4]]}},"keywords":{}}],["tongu",{"_index":4026,"title":{},"content":{"125":{"position":[[780,6]]}},"keywords":{}}],["too.mi",{"_index":2337,"title":{},"content":{"58":{"position":[[650,6]]}},"keywords":{}}],["took",{"_index":2808,"title":{},"content":{"82":{"position":[[1065,4]]},"97":{"position":[[2387,4],[5162,4],[6159,4]]},"121":{"position":[[2089,4]]},"132":{"position":[[1013,4]]}},"keywords":{}}],["tool",{"_index":149,"title":{},"content":{"3":{"position":[[357,5]]},"4":{"position":[[142,4],[252,8],[674,6],[1123,5],[1448,5]]},"125":{"position":[[2364,4],[6470,5],[7070,4],[7220,5],[7279,7],[9338,5],[9503,5],[10645,5]]},"137":{"position":[[91,5]]},"139":{"position":[[270,5]]},"158":{"position":[[467,5]]},"160":{"position":[[123,5],[4195,5]]},"165":{"position":[[364,7]]},"174":{"position":[[720,5]]},"176":{"position":[[203,5],[1188,5]]},"190":{"position":[[919,5]]}},"keywords":{}}],["toolchain",{"_index":4084,"title":{},"content":{"125":{"position":[[3683,10]]}},"keywords":{}}],["toolchainlook",{"_index":4136,"title":{},"content":{"125":{"position":[[6367,14]]}},"keywords":{}}],["toopen",{"_index":4107,"title":{},"content":{"125":{"position":[[5105,6]]}},"keywords":{}}],["top",{"_index":2541,"title":{},"content":{"66":{"position":[[62,3]]},"105":{"position":[[948,3]]},"110":{"position":[[214,3]]},"125":{"position":[[11338,3]]}},"keywords":{}}],["topic",{"_index":4486,"title":{},"content":{"148":{"position":[[534,6]]},"160":{"position":[[51,6]]}},"keywords":{}}],["toq",{"_index":536,"title":{},"content":{"12":{"position":[[582,5]]},"13":{"position":[[1545,5]]},"14":{"position":[[2628,5]]},"15":{"position":[[2302,5]]}},"keywords":{}}],["tostr",{"_index":4245,"title":{},"content":{"127":{"position":[[1484,10]]}},"keywords":{}}],["total",{"_index":512,"title":{},"content":{"11":{"position":[[299,5]]},"57":{"position":[[29,5]]},"66":{"position":[[89,7]]},"85":{"position":[[336,5]]},"97":{"position":[[231,7]]},"100":{"position":[[205,5]]},"125":{"position":[[1800,5],[1893,7]]},"129":{"position":[[1656,7]]},"136":{"position":[[88,7],[929,6]]},"163":{"position":[[171,5],[1082,5]]},"188":{"position":[[1609,6],[1707,6],[2279,6],[2595,6],[3131,6]]},"189":{"position":[[1799,6],[2255,6],[2538,6],[2824,6]]},"193":{"position":[[2324,5]]},"196":{"position":[[1217,5],[1628,5],[1830,5]]}},"keywords":{}}],["total_coupon",{"_index":567,"title":{},"content":{"13":{"position":[[714,13]]},"14":{"position":[[1571,13],[1788,13],[1804,13],[1862,13],[2035,13]]},"15":{"position":[[958,13],[1379,13],[1395,13],[1530,13],[1703,13]]}},"keywords":{}}],["total_coupons)*exp((prod(forward_structure[i:end",{"_index":647,"title":{},"content":{"14":{"position":[[1697,50]]},"15":{"position":[[1087,50]]}},"keywords":{}}],["total_data",{"_index":3034,"title":{},"content":{"90":{"position":[[3786,10]]}},"keywords":{}}],["total_data.ix[ev",{"_index":3036,"title":{},"content":{"90":{"position":[[3855,20]]}},"keywords":{}}],["total_dist",{"_index":5291,"title":{},"content":{"193":{"position":[[1745,16],[2700,16]]}},"keywords":{}}],["total_heartbeat",{"_index":2309,"title":{},"content":{"57":{"position":[[148,16]]},"64":{"position":[[1700,16]]}},"keywords":{}}],["totalcap'n",{"_index":4860,"title":{},"content":{"168":{"position":[[189,10]]},"169":{"position":[[303,10]]}},"keywords":{}}],["touch",{"_index":4193,"title":{},"content":{"125":{"position":[[9820,5]]}},"keywords":{}}],["toward",{"_index":2780,"title":{"100":{"position":[[0,7]]}},"content":{"79":{"position":[[47,7]]},"80":{"position":[[40,7],[69,7]]}},"keywords":{}}],["trace",{"_index":4617,"title":{"158":{"position":[[0,7]]}},"content":{},"keywords":{}}],["track",{"_index":2728,"title":{},"content":{"76":{"position":[[2104,5]]},"132":{"position":[[638,5]]},"158":{"position":[[306,5],[373,8]]},"175":{"position":[[1005,5]]}},"keywords":{}}],["tracker",{"_index":3244,"title":{},"content":{"93":{"position":[[2952,7]]}},"keywords":{}}],["trade",{"_index":698,"title":{"17":{"position":[[0,7]]}},"content":{"40":{"position":[[806,5]]},"41":{"position":[[212,6]]},"163":{"position":[[191,6]]}},"keywords":{}}],["trade_calendar",{"_index":2970,"title":{},"content":{"90":{"position":[[521,14]]}},"keywords":{}}],["trade_calendar.rules.pop(6",{"_index":2971,"title":{},"content":{"90":{"position":[[565,27]]}},"keywords":{}}],["trade_calendar.rules.pop(7",{"_index":2973,"title":{},"content":{"90":{"position":[[615,27]]}},"keywords":{}}],["tradeday",{"_index":2975,"title":{},"content":{"90":{"position":[[666,8]]}},"keywords":{}}],["tradeday(horizon):ev",{"_index":3131,"title":{},"content":{"91":{"position":[[2838,24]]},"92":{"position":[[650,24]]}},"keywords":{}}],["tradeday(horizon):event+tradeday(horizon)]['clos",{"_index":3148,"title":{},"content":{"91":{"position":[[3600,51]]}},"keywords":{}}],["tradeday(horizon+1",{"_index":3030,"title":{},"content":{"90":{"position":[[3662,19],[3695,19]]}},"keywords":{}}],["tradeday(x*20",{"_index":3043,"title":{},"content":{"90":{"position":[[4086,14]]}},"keywords":{}}],["tradeoff",{"_index":3482,"title":{},"content":{"101":{"position":[[643,9],[780,8],[1006,9]]},"104":{"position":[[1420,8]]},"166":{"position":[[309,10]]},"198":{"position":[[319,9]]}},"keywords":{}}],["traffic",{"_index":5038,"title":{},"content":{"175":{"position":[[1674,8]]}},"keywords":{}}],["trail",{"_index":1840,"title":{},"content":{"40":{"position":[[3581,6]]}},"keywords":{}}],["train",{"_index":2039,"title":{},"content":{"47":{"position":[[32,8]]}},"keywords":{}}],["train_size=.7",{"_index":2047,"title":{},"content":{"47":{"position":[[207,14]]}},"keywords":{}}],["train_test_split",{"_index":2041,"title":{},"content":{"47":{"position":[[85,16],[183,17]]}},"keywords":{}}],["trait",{"_index":3379,"title":{},"content":{"97":{"position":[[1853,5],[3240,5]]},"115":{"position":[[945,5],[1259,5],[1639,5],[1916,5]]},"116":{"position":[[944,5],[1211,5],[1544,5],[1821,5],[3067,6]]},"129":{"position":[[191,7]]},"132":{"position":[[560,6]]},"185":{"position":[[259,5]]},"197":{"position":[[1,6],[81,6],[109,6],[129,7],[185,5],[293,5]]},"198":{"position":[[676,6],[1050,5]]}},"keywords":{}}],["trait.interior",{"_index":5115,"title":{},"content":{"182":{"position":[[621,14]]}},"keywords":{}}],["transcrib",{"_index":3880,"title":{},"content":{"121":{"position":[[396,12]]}},"keywords":{}}],["transfer",{"_index":3428,"title":{},"content":{"97":{"position":[[5715,12]]},"116":{"position":[[2568,11],[3223,8]]},"117":{"position":[[403,8]]}},"keywords":{}}],["transform",{"_index":3533,"title":{},"content":{"103":{"position":[[1348,11],[1472,12]]},"105":{"position":[[1392,12]]}},"keywords":{}}],["transformed.tobyt",{"_index":3583,"title":{},"content":{"105":{"position":[[631,21],[782,21],[1024,21]]}},"keywords":{}}],["transient",{"_index":4672,"title":{},"content":{"160":{"position":[[1226,10]]},"199":{"position":[[645,9]]}},"keywords":{}}],["transit",{"_index":2674,"title":{},"content":{"75":{"position":[[1152,10]]}},"keywords":{}}],["translat",{"_index":3868,"title":{"121":{"position":[[8,12]]}},"content":{"128":{"position":[[1078,10]]},"150":{"position":[[1,12]]},"172":{"position":[[2035,11]]}},"keywords":{}}],["transpar",{"_index":4969,"title":{},"content":{"173":{"position":[[1999,12]]}},"keywords":{}}],["transpil",{"_index":5146,"title":{},"content":{"188":{"position":[[81,10]]}},"keywords":{}}],["trap",{"_index":2828,"title":{},"content":{"86":{"position":[[254,4]]},"129":{"position":[[28,4]]}},"keywords":{}}],["treat",{"_index":1179,"title":{},"content":{"26":{"position":[[749,5]]},"49":{"position":[[166,5],[662,5]]},"98":{"position":[[211,7]]},"178":{"position":[[185,5]]},"179":{"position":[[1737,5]]}},"keywords":{}}],["treatment",{"_index":2839,"title":{},"content":{"88":{"position":[[192,9]]}},"keywords":{}}],["trebl",{"_index":3550,"title":{"104":{"position":[[9,9]]}},"content":{"103":{"position":[[2395,7]]}},"keywords":{}}],["trend",{"_index":1293,"title":{"91":{"position":[[14,8]]},"92":{"position":[[14,8]]}},"content":{"28":{"position":[[2782,5],[4142,6],[4387,8]]},"30":{"position":[[2360,8],[2681,6],[4029,5]]},"38":{"position":[[469,5],[608,6]]},"40":{"position":[[2483,5]]},"88":{"position":[[2415,5],[2761,5],[3164,5],[3609,5],[3737,5]]},"89":{"position":[[570,8],[702,8],[856,5]]},"91":{"position":[[81,8],[1433,8],[1510,8],[2984,5],[3176,8],[4530,8],[5355,7]]},"92":{"position":[[126,8],[209,8],[796,5],[988,8]]},"93":{"position":[[285,8]]}},"keywords":{}}],["trend_funct",{"_index":3141,"title":{},"content":{"91":{"position":[[3340,16]]}},"keywords":{}}],["trend_function(tick",{"_index":3147,"title":{},"content":{"91":{"position":[[3477,22]]}},"keywords":{}}],["tri",{"_index":141,"title":{},"content":{"3":{"position":[[176,5],[331,5],[702,5],[1049,5]]},"6":{"position":[[177,6]]},"13":{"position":[[66,3]]},"22":{"position":[[1655,4]]},"26":{"position":[[333,6]]},"28":{"position":[[441,3],[581,6]]},"30":{"position":[[7054,6],[9828,4]]},"34":{"position":[[604,3],[3611,3]]},"38":{"position":[[287,6]]},"39":{"position":[[399,6]]},"40":{"position":[[2579,3]]},"45":{"position":[[878,3],[928,3],[2739,3]]},"52":{"position":[[93,3]]},"53":{"position":[[332,6]]},"54":{"position":[[56,6]]},"57":{"position":[[271,6]]},"64":{"position":[[104,3]]},"73":{"position":[[721,6]]},"75":{"position":[[179,6],[218,6]]},"76":{"position":[[1224,6]]},"77":{"position":[[176,3]]},"85":{"position":[[183,3],[375,6],[453,6]]},"86":{"position":[[898,6]]},"91":{"position":[[2756,4],[3652,4]]},"92":{"position":[[568,4]]},"93":{"position":[[4738,4],[5153,4]]},"95":{"position":[[553,6]]},"96":{"position":[[278,6],[1046,3],[1587,3],[2123,3]]},"97":{"position":[[905,6],[1267,4],[2106,6],[2593,6],[4283,3],[4368,3],[5426,6]]},"102":{"position":[[16,3],[436,3]]},"103":{"position":[[1548,3]]},"104":{"position":[[48,6],[116,5],[754,6]]},"105":{"position":[[2844,3],[3036,3]]},"112":{"position":[[1086,3]]},"113":{"position":[[1327,6]]},"115":{"position":[[36,3]]},"120":{"position":[[568,3],[676,3]]},"121":{"position":[[65,3],[149,6],[1185,6],[1372,3],[1563,3]]},"123":{"position":[[85,3],[851,3]]},"125":{"position":[[172,6],[277,6],[1934,3],[2378,5],[3028,3],[3556,3],[4461,3],[10268,6]]},"129":{"position":[[2042,5]]},"160":{"position":[[2960,6],[4133,5]]},"161":{"position":[[1382,6]]},"164":{"position":[[91,5]]}},"keywords":{}}],["trial",{"_index":3964,"title":{"123":{"position":[[0,5]]}},"content":{},"keywords":{}}],["triangl",{"_index":2573,"title":{},"content":{"68":{"position":[[911,8]]}},"keywords":{}}],["trick",{"_index":4935,"title":{},"content":{"172":{"position":[[2505,7]]}},"keywords":{}}],["tricki",{"_index":2500,"title":{},"content":{"65":{"position":[[15,6]]},"190":{"position":[[760,6]]}},"keywords":{}}],["triedan",{"_index":4176,"title":{},"content":{"125":{"position":[[8880,7]]}},"keywords":{}}],["trigger",{"_index":4137,"title":{},"content":{"125":{"position":[[6414,8]]},"127":{"position":[[683,8]]},"143":{"position":[[128,8]]},"144":{"position":[[223,8],[342,7],[391,7]]},"145":{"position":[[310,7],[401,8]]},"146":{"position":[[186,8],[300,7],[387,8]]},"147":{"position":[[342,7]]},"166":{"position":[[858,7]]},"172":{"position":[[74,10]]},"173":{"position":[[1073,7],[1446,7]]},"176":{"position":[[486,8]]},"180":{"position":[[227,7]]}},"keywords":{}}],["trim",{"_index":4281,"title":{},"content":{"129":{"position":[[498,7]]}},"keywords":{}}],["trim_start=start",{"_index":1745,"title":{},"content":{"39":{"position":[[2227,17]]}},"keywords":{}}],["trim_start=start_d",{"_index":1006,"title":{},"content":{"23":{"position":[[408,22],[475,22],[543,22],[612,22]]}},"keywords":{}}],["triumph",{"_index":2817,"title":{},"content":{"83":{"position":[[611,9]]}},"keywords":{}}],["trivia",{"_index":4429,"title":{},"content":{"139":{"position":[[944,6]]}},"keywords":{}}],["trivial",{"_index":2555,"title":{},"content":{"68":{"position":[[65,7]]},"72":{"position":[[16,7]]},"74":{"position":[[1035,8]]},"96":{"position":[[615,7]]},"97":{"position":[[1054,7],[2817,7]]},"110":{"position":[[44,7]]},"163":{"position":[[557,7]]},"190":{"position":[[202,7]]}},"keywords":{}}],["true",{"_index":894,"title":{},"content":{"22":{"position":[[441,4],[1851,4]]},"32":{"position":[[997,5]]},"75":{"position":[[1264,4]]},"93":{"position":[[1709,4]]},"121":{"position":[[1038,5],[1095,6]]},"190":{"position":[[983,4]]}},"keywords":{}}],["truli",{"_index":3361,"title":{},"content":{"97":{"position":[[180,5]]},"150":{"position":[[178,5]]}},"keywords":{}}],["truth",{"_index":4052,"title":{},"content":{"125":{"position":[[1736,5],[2563,5]]}},"keywords":{}}],["tsconfig",{"_index":103,"title":{},"content":{"2":{"position":[[416,9]]}},"keywords":{}}],["tstate",{"_index":5207,"title":{},"content":{"188":{"position":[[3690,6]]}},"keywords":{}}],["tune",{"_index":4993,"title":{},"content":{"174":{"position":[[1083,6]]}},"keywords":{}}],["tupl",{"_index":4790,"title":{},"content":{"163":{"position":[[1948,7]]}},"keywords":{}}],["turn",{"_index":744,"title":{"133":{"position":[[0,7]]}},"content":{"19":{"position":[[207,5]]},"33":{"position":[[295,4]]},"34":{"position":[[297,4],[3223,6],[3973,4]]},"51":{"position":[[2557,5]]},"53":{"position":[[239,5]]},"90":{"position":[[3541,4]]},"96":{"position":[[1808,5]]},"108":{"position":[[77,7]]},"118":{"position":[[281,7]]},"120":{"position":[[373,4],[438,5]]},"121":{"position":[[1419,5],[2192,5]]},"125":{"position":[[11313,6]]},"127":{"position":[[1152,4]]},"129":{"position":[[324,5]]},"150":{"position":[[338,7]]},"152":{"position":[[490,4],[989,4]]},"156":{"position":[[931,4],[1095,4]]},"161":{"position":[[1563,6]]},"170":{"position":[[22,6]]},"173":{"position":[[885,7]]},"181":{"position":[[412,6]]}},"keywords":{}}],["tweak",{"_index":102,"title":{},"content":{"2":{"position":[[403,8]]},"34":{"position":[[61,5]]},"35":{"position":[[140,5]]}},"keywords":{}}],["tweet",{"_index":2050,"title":{"48":{"position":[[0,5]]}},"content":{"49":{"position":[[24,7],[711,6]]},"50":{"position":[[23,5],[222,6]]},"51":{"position":[[121,6],[191,6],[1473,5],[1574,6],[1954,5],[2200,6],[2691,6],[2789,7],[2930,6],[3051,7]]},"52":{"position":[[912,5],[1085,5],[1108,5],[1116,7],[1129,6]]},"53":{"position":[[59,6],[1810,6]]}},"keywords":{}}],["tweets.text",{"_index":2073,"title":{},"content":{"51":{"position":[[163,11]]}},"keywords":{}}],["tweettoken",{"_index":2081,"title":{},"content":{"51":{"position":[[439,14],[462,16]]}},"keywords":{}}],["twenti",{"_index":2195,"title":{},"content":{"53":{"position":[[45,6]]}},"keywords":{}}],["twice",{"_index":1599,"title":{},"content":{"34":{"position":[[847,5]]},"189":{"position":[[2057,5]]}},"keywords":{}}],["twice!"",{"_index":5144,"title":{},"content":{"186":{"position":[[648,15]]}},"keywords":{}}],["twitter",{"_index":2063,"title":{},"content":{"50":{"position":[[57,7],[193,7]]},"51":{"position":[[2620,8]]},"53":{"position":[[99,7],[2163,7]]}},"keywords":{}}],["two",{"_index":877,"title":{},"content":{"22":{"position":[[23,3]]},"24":{"position":[[11,3]]},"28":{"position":[[2495,3]]},"34":{"position":[[160,3]]},"38":{"position":[[428,3]]},"40":{"position":[[997,3]]},"43":{"position":[[698,3]]},"49":{"position":[[517,4]]},"68":{"position":[[871,3]]},"69":{"position":[[45,3]]},"71":{"position":[[103,3]]},"72":{"position":[[112,3],[174,3],[518,3]]},"74":{"position":[[368,3]]},"75":{"position":[[254,3]]},"78":{"position":[[21,3]]},"82":{"position":[[143,3]]},"83":{"position":[[125,3]]},"86":{"position":[[36,3]]},"88":{"position":[[16,3],[2035,3],[2058,3]]},"89":{"position":[[17,3]]},"91":{"position":[[4676,3]]},"93":{"position":[[4571,3]]},"97":{"position":[[2392,3],[5606,3],[5835,3]]},"98":{"position":[[280,3],[514,3]]},"101":{"position":[[307,3]]},"105":{"position":[[595,3]]},"106":{"position":[[577,3]]},"113":{"position":[[2032,3]]},"116":{"position":[[2657,3]]},"117":{"position":[[104,3]]},"121":{"position":[[2094,3]]},"122":{"position":[[1230,3]]},"123":{"position":[[382,3]]},"125":{"position":[[2237,3],[7970,3],[8030,3],[8200,3],[9538,3]]},"127":{"position":[[336,3]]},"135":{"position":[[506,3]]},"161":{"position":[[539,3],[923,3]]},"164":{"position":[[816,3]]},"175":{"position":[[1303,3]]},"176":{"position":[[733,3]]},"188":{"position":[[321,3],[2038,3],[3333,3]]},"189":{"position":[[1995,3]]},"193":{"position":[[3480,3]]},"197":{"position":[[24,3]]},"199":{"position":[[83,3]]}},"keywords":{}}],["twoexampl",{"_index":4161,"title":{},"content":{"125":{"position":[[8313,11]]}},"keywords":{}}],["twofiftysix",{"_index":4547,"title":{},"content":{"153":{"position":[[534,11],[603,13]]},"195":{"position":[[216,11],[300,13]]}},"keywords":{}}],["twofiftysixk",{"_index":4551,"title":{},"content":{"153":{"position":[[649,12],[722,14]]},"195":{"position":[[363,12],[614,14]]}},"keywords":{}}],["type",{"_index":131,"title":{"91":{"position":[[6,4]]},"92":{"position":[[6,4]]},"198":{"position":[[5,6]]}},"content":{"2":{"position":[[869,5]]},"3":{"position":[[1385,5]]},"20":{"position":[[2032,7],[2071,7],[2118,7],[2161,7]]},"24":{"position":[[15,5]]},"91":{"position":[[11,4]]},"96":{"position":[[1307,4]]},"97":{"position":[[4133,4],[6455,4]]},"111":{"position":[[642,5]]},"116":{"position":[[9,4],[2550,5],[2982,4]]},"117":{"position":[[456,4],[644,4]]},"121":{"position":[[2716,7]]},"122":{"position":[[331,6]]},"125":{"position":[[4335,5],[4503,4],[4597,5],[4719,5]]},"127":{"position":[[187,5],[1021,5],[1399,4]]},"129":{"position":[[130,6]]},"130":{"position":[[456,4]]},"140":{"position":[[90,4]]},"141":{"position":[[356,4]]},"145":{"position":[[379,5]]},"153":{"position":[[156,4]]},"155":{"position":[[59,6],[207,6],[1237,5]]},"156":{"position":[[12,5],[324,5],[1784,5]]},"159":{"position":[[385,5],[719,5]]},"160":{"position":[[297,4]]},"163":{"position":[[986,4]]},"165":{"position":[[826,6]]},"166":{"position":[[555,5],[691,6]]},"170":{"position":[[108,4]]},"172":{"position":[[1481,5]]},"184":{"position":[[857,5]]},"185":{"position":[[53,5]]},"189":{"position":[[400,5],[983,4]]},"190":{"position":[[370,5]]},"194":{"position":[[43,5],[185,5]]},"195":{"position":[[11,4]]},"197":{"position":[[897,4]]},"198":{"position":[[249,4],[808,5],[863,5],[1095,4]]},"199":{"position":[[1618,5]]}},"keywords":{}}],["typecan",{"_index":5361,"title":{},"content":{"198":{"position":[[712,7]]}},"keywords":{}}],["typecopi",{"_index":5305,"title":{},"content":{"193":{"position":[[2984,9]]}},"keywords":{}}],["typedread",{"_index":3815,"title":{"117":{"position":[[15,12]]}},"content":{"117":{"position":[[5,11],[314,11]]}},"keywords":{}}],["typedreaderi",{"_index":3819,"title":{},"content":{"117":{"position":[[474,13]]}},"keywords":{}}],["typeerror",{"_index":4096,"title":{},"content":{"125":{"position":[[4386,10]]}},"keywords":{}}],["typeiteratori",{"_index":5378,"title":{},"content":{"199":{"position":[[518,14]]}},"keywords":{}}],["types(lik",{"_index":4567,"title":{},"content":{"155":{"position":[[779,10]]}},"keywords":{}}],["typescript",{"_index":9,"title":{},"content":{"1":{"position":[[58,11],[272,11]]},"2":{"position":[[278,10]]},"3":{"position":[[149,10]]},"125":{"position":[[5363,10],[5911,10]]}},"keywords":{}}],["typescript/javascript",{"_index":36,"title":{},"content":{"1":{"position":[[398,21]]}},"keywords":{}}],["typescriptthan",{"_index":4196,"title":{},"content":{"125":{"position":[[10248,14]]}},"keywords":{}}],["typic",{"_index":1477,"title":{},"content":{"30":{"position":[[9251,9]]},"74":{"position":[[1169,9]]},"93":{"position":[[645,9]]},"104":{"position":[[1730,9],[1801,9]]},"111":{"position":[[141,9]]},"135":{"position":[[134,9]]},"157":{"position":[[284,9]]},"160":{"position":[[1761,9]]},"161":{"position":[[1099,9]]},"173":{"position":[[277,9]]},"174":{"position":[[1244,9]]},"176":{"position":[[552,9]]},"179":{"position":[[216,9]]},"182":{"position":[[324,7]]},"195":{"position":[[428,9]]},"196":{"position":[[63,9]]}},"keywords":{}}],["typo",{"_index":3882,"title":{},"content":{"121":{"position":[[594,6],[820,6]]}},"keywords":{}}],["tz",{"_index":3959,"title":{},"content":{"122":{"position":[[1261,2]]}},"keywords":{}}],["u.",{"_index":1443,"title":{},"content":{"30":{"position":[[8078,5]]}},"keywords":{}}],["u.get_int",{"_index":5349,"title":{},"content":{"197":{"position":[[1132,12]]}},"keywords":{}}],["u32",{"_index":4292,"title":{},"content":{"129":{"position":[[967,3],[1445,3]]},"152":{"position":[[480,4]]},"165":{"position":[[1229,3]]},"180":{"position":[[441,4],[452,3]]},"181":{"position":[[86,3],[121,4],[132,3],[243,4],[254,3]]},"183":{"position":[[311,3],[346,4],[357,3],[492,4],[503,3]]},"184":{"position":[[169,3],[301,3],[528,3]]},"185":{"position":[[674,4]]}},"keywords":{}}],["u32>",{"_index":5386,"title":{},"content":{"199":{"position":[[1562,8]]}},"keywords":{}}],["u64",{"_index":4549,"title":{},"content":{"153":{"position":[[552,5]]},"192":{"position":[[133,4],[141,4]]},"195":{"position":[[234,5]]},"197":{"position":[[336,4],[465,3],[481,3],[552,3],[614,3]]}},"keywords":{}}],["u8",{"_index":3773,"title":{},"content":{"115":{"position":[[965,3],[1197,3]]},"116":{"position":[[964,3],[1149,3],[2688,3]]},"152":{"position":[[1367,2],[1517,3]]},"156":{"position":[[1450,2],[1600,3]]},"163":{"position":[[1701,4]]},"197":{"position":[[405,2]]}},"keywords":{}}],["ubuntu",{"_index":3666,"title":{},"content":{"108":{"position":[[418,7]]}},"keywords":{}}],["udp",{"_index":5020,"title":{},"content":{"175":{"position":[[910,3]]}},"keywords":{}}],["ulimit",{"_index":5322,"title":{},"content":{"195":{"position":[[563,7]]}},"keywords":{}}],["ultim",{"_index":2940,"title":{},"content":{"88":{"position":[[3649,10]]},"95":{"position":[[261,10]]},"97":{"position":[[2447,10]]},"121":{"position":[[2577,10]]},"124":{"position":[[123,11]]},"125":{"position":[[3868,10]]},"163":{"position":[[2249,11]]},"165":{"position":[[1382,11]]}},"keywords":{}}],["ultimatelygot",{"_index":4063,"title":{},"content":{"125":{"position":[[2401,13]]}},"keywords":{}}],["umbrella",{"_index":4592,"title":{},"content":{"156":{"position":[[351,8]]}},"keywords":{}}],["un",{"_index":2611,"title":{},"content":{"71":{"position":[[1430,2]]}},"keywords":{}}],["un/satisfi",{"_index":1934,"title":{},"content":{"44":{"position":[[1305,12]]}},"keywords":{}}],["unabl",{"_index":4162,"title":{},"content":{"125":{"position":[[8354,6],[8915,6]]},"133":{"position":[[98,6]]},"181":{"position":[[780,6]]}},"keywords":{}}],["unaccept",{"_index":4428,"title":{},"content":{"139":{"position":[[695,12]]}},"keywords":{}}],["unawar",{"_index":4055,"title":{},"content":{"125":{"position":[[1901,7]]}},"keywords":{}}],["unblock",{"_index":5158,"title":{},"content":{"188":{"position":[[686,9]]}},"keywords":{}}],["unbound",{"_index":4295,"title":{},"content":{"129":{"position":[[1290,7],[1867,7]]}},"keywords":{}}],["uncc",{"_index":2210,"title":{},"content":{"53":{"position":[[415,5]]}},"keywords":{}}],["unchang",{"_index":5056,"title":{},"content":{"178":{"position":[[34,10]]}},"keywords":{}}],["uncommon",{"_index":2811,"title":{},"content":{"83":{"position":[[233,8]]}},"keywords":{}}],["uncompress",{"_index":3463,"title":{},"content":{"101":{"position":[[18,12],[474,10]]},"105":{"position":[[2633,12]]}},"keywords":{}}],["under",{"_index":3546,"title":{},"content":{"103":{"position":[[2290,5]]},"125":{"position":[[6734,5]]},"127":{"position":[[895,5]]},"156":{"position":[[340,5]]}},"keywords":{}}],["undergradu",{"_index":2202,"title":{},"content":{"53":{"position":[[288,13]]}},"keywords":{}}],["underli",{"_index":303,"title":{"6":{"position":[[0,10]]},"11":{"position":[[9,10]]}},"content":{"6":{"position":[[67,10]]},"7":{"position":[[211,10]]},"13":{"position":[[28,10],[167,10],[249,10]]},"14":{"position":[[183,10],[322,10],[392,10]]},"15":{"position":[[236,10],[360,10],[421,10]]},"82":{"position":[[1264,10]]},"97":{"position":[[5756,10]]},"117":{"position":[[177,10],[678,10]]}},"keywords":{}}],["understand",{"_index":137,"title":{},"content":{"3":{"position":[[52,10]]},"4":{"position":[[558,13]]},"41":{"position":[[88,11]]},"69":{"position":[[15,10]]},"90":{"position":[[150,10]]},"97":{"position":[[2603,10]]},"98":{"position":[[767,10]]},"104":{"position":[[17,10],[1661,10]]},"112":{"position":[[386,10]]},"113":{"position":[[1144,10],[1958,11]]},"128":{"position":[[53,13]]},"137":{"position":[[123,10]]},"160":{"position":[[463,10],[971,11],[3220,13]]},"170":{"position":[[459,10]]},"172":{"position":[[919,13],[1143,10],[1674,13]]},"173":{"position":[[1335,13]]},"182":{"position":[[370,10]]},"193":{"position":[[1008,13]]},"198":{"position":[[1,13]]}},"keywords":{}}],["understood",{"_index":42,"title":{},"content":{"1":{"position":[[493,10]]}},"keywords":{}}],["unfair",{"_index":2552,"title":{"67":{"position":[[4,6]]}},"content":{"72":{"position":[[522,6]]}},"keywords":{}}],["unfair_die(d1",{"_index":2600,"title":{},"content":{"70":{"position":[[1112,14]]},"71":{"position":[[1263,14]]}},"keywords":{}}],["unfair_die(d1_dist",{"_index":2751,"title":{},"content":{"78":{"position":[[169,19]]}},"keywords":{}}],["unfair_die(d2",{"_index":2602,"title":{},"content":{"70":{"position":[[1139,14]]},"71":{"position":[[1290,14]]}},"keywords":{}}],["unfair_die(d2_dist",{"_index":2753,"title":{},"content":{"78":{"position":[[202,19]]}},"keywords":{}}],["unfair_die(p_v",{"_index":2593,"title":{},"content":{"70":{"position":[[938,18]]}},"keywords":{}}],["unfamiliar",{"_index":14,"title":{},"content":{"1":{"position":[[133,10]]}},"keywords":{}}],["unfortun",{"_index":1886,"title":{},"content":{"43":{"position":[[1090,13]]},"97":{"position":[[947,11]]},"194":{"position":[[714,13]]}},"keywords":{}}],["unicast",{"_index":5021,"title":{},"content":{"175":{"position":[[914,8]]}},"keywords":{}}],["union",{"_index":4843,"title":{},"content":{"166":{"position":[[405,7],[549,5],[685,5]]},"194":{"position":[[179,5],[666,6]]}},"keywords":{}}],["uniqu",{"_index":211,"title":{"183":{"position":[[7,11]]}},"content":{"3":{"position":[[1452,6]]},"51":{"position":[[885,6],[2654,6]]},"127":{"position":[[340,6]]},"159":{"position":[[548,7]]},"181":{"position":[[717,6],[798,6]]},"182":{"position":[[126,6],[447,6]]},"183":{"position":[[89,11],[194,7]]},"185":{"position":[[115,7]]}},"keywords":{}}],["unique_hashtag",{"_index":2125,"title":{},"content":{"51":{"position":[[2333,15],[2444,16],[2511,18]]}},"keywords":{}}],["unique_word",{"_index":2098,"title":{},"content":{"51":{"position":[[1164,12],[1250,14],[2372,12]]}},"keywords":{}}],["unit",{"_index":366,"title":{},"content":{"6":{"position":[[990,4]]}},"keywords":{}}],["unix",{"_index":4955,"title":{},"content":{"173":{"position":[[970,4]]}},"keywords":{}}],["unknown",{"_index":4069,"title":{},"content":{"125":{"position":[[2721,7],[2729,7],[5241,7],[5249,7],[5789,7],[5797,7],[10056,8],[10397,7]]},"141":{"position":[[140,7]]},"155":{"position":[[157,7]]}},"keywords":{}}],["unless",{"_index":1672,"title":{},"content":{"35":{"position":[[373,7]]},"65":{"position":[[1429,7]]},"97":{"position":[[5535,6]]},"189":{"position":[[380,6]]}},"keywords":{}}],["unlik",{"_index":1809,"title":{},"content":{"40":{"position":[[1346,6]]},"160":{"position":[[997,6]]},"165":{"position":[[385,6]]},"189":{"position":[[2866,6]]}},"keywords":{}}],["unlock",{"_index":5156,"title":{},"content":{"188":{"position":[[548,7],[3395,6],[3506,7],[4465,9],[4502,6]]},"189":{"position":[[644,7],[2303,9],[2892,6]]},"190":{"position":[[827,9]]}},"keywords":{}}],["unmaintain",{"_index":4847,"title":{},"content":{"166":{"position":[[644,13]]}},"keywords":{}}],["unmodifi",{"_index":4364,"title":{},"content":{"133":{"position":[[124,10]]}},"keywords":{}}],["unnecessari",{"_index":263,"title":{},"content":{"4":{"position":[[833,11],[1016,11]]},"141":{"position":[[203,11]]},"153":{"position":[[426,11]]}},"keywords":{}}],["unpack",{"_index":4814,"title":{},"content":{"164":{"position":[[975,6],[1076,7],[1152,8]]},"168":{"position":[[252,8]]},"169":{"position":[[366,8]]}},"keywords":{}}],["unpredict",{"_index":1123,"title":{},"content":{"24":{"position":[[3044,14]]}},"keywords":{}}],["unrel",{"_index":5107,"title":{},"content":{"182":{"position":[[187,10]]}},"keywords":{}}],["unsaf",{"_index":3359,"title":{},"content":{"97":{"position":[[114,6]]},"115":{"position":[[2806,6]]},"152":{"position":[[937,6],[1268,6],[1313,6],[1478,6]]},"156":{"position":[[1351,6],[1396,6],[1561,6]]},"160":{"position":[[3449,6]]},"186":{"position":[[70,6]]},"188":{"position":[[495,6]]}},"keywords":{}}],["unsafenev",{"_index":4679,"title":{},"content":{"160":{"position":[[1627,11]]}},"keywords":{}}],["unsat",{"_index":1935,"title":{},"content":{"44":{"position":[[1330,5],[1441,6],[1448,7]]}},"keywords":{}}],["unsatisfi",{"_index":1879,"title":{},"content":{"43":{"position":[[734,11]]},"44":{"position":[[1393,11],[1596,11]]}},"keywords":{}}],["unsign",{"_index":5162,"title":{},"content":{"188":{"position":[[975,8],[1051,8]]}},"keywords":{}}],["unstabl",{"_index":4153,"title":{},"content":{"125":{"position":[[7943,8]]}},"keywords":{}}],["unsuccessfulli",{"_index":101,"title":{},"content":{"2":{"position":[[386,16]]}},"keywords":{}}],["until",{"_index":48,"title":{},"content":{"1":{"position":[[553,5]]},"13":{"position":[[414,5]]},"14":{"position":[[467,5],[1311,5]]},"38":{"position":[[716,5]]},"40":{"position":[[356,5],[1890,5],[2213,5],[2833,5]]},"52":{"position":[[643,5]]},"65":{"position":[[2159,5],[2515,5]]},"75":{"position":[[295,5]]},"93":{"position":[[1165,5]]},"120":{"position":[[558,5]]},"160":{"position":[[2944,5]]},"188":{"position":[[3241,5]]},"190":{"position":[[796,5]]}},"keywords":{}}],["untyp",{"_index":3824,"title":{},"content":{"117":{"position":[[778,7]]}},"keywords":{}}],["unus",{"_index":4698,"title":{},"content":{"160":{"position":[[2594,8]]}},"keywords":{}}],["unwrap",{"_index":3760,"title":{},"content":{"113":{"position":[[1894,11]]},"115":{"position":[[349,11]]},"116":{"position":[[449,11]]},"117":{"position":[[1238,11]]},"147":{"position":[[558,8]]}},"keywords":{}}],["up",{"_index":145,"title":{"92":{"position":[[23,2]]},"111":{"position":[[16,2]]},"143":{"position":[[15,3]]}},"content":{"3":{"position":[[281,2],[1042,3]]},"4":{"position":[[9,2]]},"6":{"position":[[109,2]]},"9":{"position":[[41,3]]},"11":{"position":[[41,3]]},"13":{"position":[[411,2]]},"14":{"position":[[464,2]]},"15":{"position":[[576,2],[669,2]]},"22":{"position":[[2839,2]]},"24":{"position":[[1025,2]]},"25":{"position":[[745,2]]},"28":{"position":[[77,2],[171,2]]},"30":{"position":[[971,3]]},"32":{"position":[[298,3],[1158,2],[1285,2]]},"33":{"position":[[854,2],[916,2],[943,2],[1159,2]]},"34":{"position":[[3145,2],[3665,2],[3915,2]]},"38":{"position":[[201,2],[391,3]]},"39":{"position":[[112,2]]},"40":{"position":[[706,2],[1590,2],[2373,3]]},"43":{"position":[[7,3]]},"44":{"position":[[1153,2]]},"45":{"position":[[957,2],[2647,2]]},"49":{"position":[[38,2]]},"52":{"position":[[668,2]]},"53":{"position":[[74,2],[1141,2],[1332,2],[1633,2],[2086,3]]},"54":{"position":[[280,2]]},"57":{"position":[[480,2]]},"58":{"position":[[603,3],[647,2]]},"61":{"position":[[1450,2]]},"62":{"position":[[29,2]]},"65":{"position":[[124,2]]},"66":{"position":[[428,2],[690,3]]},"69":{"position":[[131,3]]},"73":{"position":[[440,2]]},"76":{"position":[[1462,3]]},"83":{"position":[[62,2]]},"88":{"position":[[2767,2],[3179,2]]},"89":{"position":[[711,3]]},"90":{"position":[[4286,2]]},"91":{"position":[[3260,2],[5829,3]]},"92":{"position":[[218,3],[1072,2],[1585,2]]},"93":{"position":[[2309,2],[4563,2]]},"95":{"position":[[529,2]]},"96":{"position":[[955,2],[1838,2]]},"97":{"position":[[1367,2],[1650,2],[2587,2],[3796,2]]},"98":{"position":[[73,2]]},"100":{"position":[[366,2]]},"101":{"position":[[271,2],[1041,2]]},"103":{"position":[[1538,3],[1658,2]]},"104":{"position":[[1945,2]]},"106":{"position":[[291,2],[765,2]]},"109":{"position":[[31,3],[482,3]]},"111":{"position":[[31,2],[508,2]]},"112":{"position":[[1272,2]]},"113":{"position":[[52,3],[1299,2],[1568,2],[2522,2]]},"116":{"position":[[921,3],[3112,2]]},"118":{"position":[[278,2]]},"120":{"position":[[361,2]]},"121":{"position":[[637,2],[1025,2],[2060,2]]},"122":{"position":[[1461,2]]},"124":{"position":[[484,2]]},"125":{"position":[[1028,3],[9542,2],[10433,2],[11568,2]]},"128":{"position":[[571,2]]},"134":{"position":[[125,2],[329,2]]},"153":{"position":[[456,2],[782,2]]},"160":{"position":[[379,2]]},"172":{"position":[[2453,2]]},"174":{"position":[[1066,2]]},"178":{"position":[[461,2]]},"190":{"position":[[72,2]]},"192":{"position":[[341,2]]},"196":{"position":[[1445,2]]},"197":{"position":[[783,2],[1076,2]]}},"keywords":{}}],["up?i",{"_index":2954,"title":{},"content":{"89":{"position":[[743,5]]}},"keywords":{}}],["upcom",{"_index":4710,"title":{},"content":{"160":{"position":[[3854,8]]}},"keywords":{}}],["updat",{"_index":384,"title":{},"content":{"7":{"position":[[145,6]]},"123":{"position":[[196,7]]},"125":{"position":[[2415,8],[8069,8],[11061,8]]}},"keywords":{}}],["upon",{"_index":2325,"title":{},"content":{"58":{"position":[[180,4]]}},"keywords":{}}],["upper",{"_index":810,"title":{},"content":{"20":{"position":[[1197,5]]},"45":{"position":[[1699,5]]}},"keywords":{}}],["upstream",{"_index":4061,"title":{},"content":{"125":{"position":[[2335,8]]}},"keywords":{}}],["uptick",{"_index":1811,"title":{},"content":{"40":{"position":[[1415,6]]}},"keywords":{}}],["uptrend",{"_index":3177,"title":{},"content":{"92":{"position":[[55,8],[306,7]]}},"keywords":{}}],["upward",{"_index":1692,"title":{},"content":{"38":{"position":[[475,6]]}},"keywords":{}}],["url",{"_index":968,"title":{},"content":{"22":{"position":[[2422,4],[2585,5],[2953,3]]},"30":{"position":[[8869,3],[8963,3]]},"61":{"position":[[1457,3],[1875,4],[1910,3],[2197,3]]},"62":{"position":[[678,3]]},"96":{"position":[[373,4],[998,3],[1196,4],[1496,4],[1734,4],[2280,4]]},"125":{"position":[[4683,3]]}},"keywords":{}}],["url'",{"_index":882,"title":{},"content":{"22":{"position":[[73,5]]}},"keywords":{}}],["url(<loc",{"_index":121,"title":{},"content":{"2":{"position":[[716,13]]}},"keywords":{}}],["urllib",{"_index":2372,"title":{},"content":{"61":{"position":[[1507,6]]}},"keywords":{}}],["urllib.parse.urlencode(param",{"_index":2383,"title":{},"content":{"61":{"position":[[1800,30]]}},"keywords":{}}],["us",{"_index":86,"title":{"37":{"position":[[14,5]]},"122":{"position":[[0,5]]},"144":{"position":[[0,5]]},"145":{"position":[[0,5]]},"146":{"position":[[0,5]]}},"content":{"2":{"position":[[166,3],[522,5],[708,3]]},"3":{"position":[[108,3],[744,5],[1312,4]]},"4":{"position":[[12,5]]},"6":{"position":[[206,3],[971,5]]},"7":{"position":[[222,4],[715,4],[1036,3]]},"8":{"position":[[104,5],[136,3]]},"10":{"position":[[334,4]]},"11":{"position":[[218,3]]},"12":{"position":[[66,3],[167,3]]},"14":{"position":[[1188,3]]},"19":{"position":[[48,3]]},"20":{"position":[[1114,3]]},"25":{"position":[[98,3]]},"30":{"position":[[779,3],[944,4],[8164,4],[8252,3],[8298,4],[9499,3],[9515,3]]},"32":{"position":[[443,3]]},"33":{"position":[[430,3]]},"34":{"position":[[1011,5]]},"43":{"position":[[92,5]]},"45":{"position":[[675,3],[1226,3],[1469,5],[1645,5],[2766,5]]},"46":{"position":[[279,4]]},"47":{"position":[[6,4]]},"49":{"position":[[270,3],[503,3]]},"50":{"position":[[5,5],[53,3],[98,3],[201,5]]},"51":{"position":[[9,5],[2250,5],[2574,4],[2646,5]]},"53":{"position":[[1817,3]]},"58":{"position":[[375,5],[841,6]]},"61":{"position":[[277,3],[787,3],[1350,5]]},"62":{"position":[[118,5],[298,5]]},"63":{"position":[[65,5]]},"64":{"position":[[76,4],[1130,4],[1271,3],[1423,6]]},"65":{"position":[[60,4],[302,3],[2195,5]]},"73":{"position":[[265,5]]},"76":{"position":[[600,3]]},"78":{"position":[[15,5]]},"79":{"position":[[16,4]]},"80":{"position":[[21,3]]},"85":{"position":[[13,3]]},"86":{"position":[[79,4],[178,3],[377,3],[751,4],[1179,5]]},"88":{"position":[[979,4]]},"90":{"position":[[3226,3],[3393,5]]},"91":{"position":[[240,3],[1623,3],[1798,5]]},"93":{"position":[[2929,3]]},"95":{"position":[[10,5]]},"97":{"position":[[110,3],[1072,5],[2751,4],[3090,3],[4760,3],[5345,3],[6503,3]]},"98":{"position":[[551,4],[782,3],[851,6],[941,3],[1118,3],[1152,5]]},"101":{"position":[[799,5]]},"102":{"position":[[120,4],[574,5],[1234,3],[1277,5],[1309,3]]},"103":{"position":[[21,5],[126,5],[744,5],[1593,3]]},"104":{"position":[[166,5],[1432,5]]},"105":{"position":[[38,5],[122,5],[276,3],[311,3]]},"106":{"position":[[45,5],[622,4],[1011,4]]},"108":{"position":[[116,4],[472,3],[585,5]]},"111":{"position":[[126,6],[638,3]]},"113":{"position":[[303,3]]},"115":{"position":[[456,5],[637,3]]},"116":{"position":[[2533,4],[2922,5]]},"117":{"position":[[326,5],[1654,3],[2001,3]]},"120":{"position":[[232,6],[407,7]]},"121":{"position":[[484,5],[840,3],[1685,4],[1911,3],[2074,5]]},"122":{"position":[[297,3],[423,4]]},"125":{"position":[[1190,3],[2387,4],[2705,4],[2813,3],[3961,5],[5047,5],[5134,3],[5397,3],[6248,4],[6511,4],[6723,4],[7765,4],[8333,5],[10557,3]]},"127":{"position":[[16,5],[992,5]]},"128":{"position":[[862,3],[970,5]]},"133":{"position":[[173,3],[262,3]]},"135":{"position":[[144,4],[228,4]]},"136":{"position":[[246,5],[711,5],[861,3]]},"137":{"position":[[163,3]]},"139":{"position":[[220,5]]},"140":{"position":[[213,6]]},"144":{"position":[[73,3],[95,3]]},"145":{"position":[[42,3],[71,3]]},"146":{"position":[[42,3],[71,3],[99,3]]},"147":{"position":[[123,3],[152,3]]},"148":{"position":[[128,3]]},"152":{"position":[[372,3],[419,3]]},"155":{"position":[[194,3],[372,3],[1243,3],[1280,3],[1297,3],[1317,3]]},"156":{"position":[[18,3],[822,3],[869,3]]},"157":{"position":[[675,4]]},"159":{"position":[[589,5],[1240,3]]},"160":{"position":[[286,3],[488,5],[1092,4],[1251,3],[1623,3],[1639,3],[1718,3],[1747,4],[2873,4],[2996,4],[3060,5],[3465,3],[3750,5],[4185,5]]},"161":{"position":[[830,4]]},"163":{"position":[[423,5]]},"164":{"position":[[262,5],[312,4],[450,5],[581,3],[1013,3],[1566,5]]},"165":{"position":[[341,5],[1404,5]]},"166":{"position":[[354,3],[762,6]]},"172":{"position":[[914,4],[1894,5],[1944,5],[2563,6]]},"174":{"position":[[779,5]]},"175":{"position":[[904,5],[1120,5]]},"176":{"position":[[188,5],[395,4],[667,3],[1112,5]]},"179":{"position":[[111,5],[363,3],[833,3],[1211,5],[1224,3],[1333,4]]},"180":{"position":[[343,3],[581,4]]},"181":{"position":[[834,5]]},"182":{"position":[[675,5]]},"183":{"position":[[441,4],[587,4]]},"184":{"position":[[436,5],[810,3],[998,3]]},"185":{"position":[[629,3]]},"186":{"position":[[128,3],[182,3]]},"188":{"position":[[414,3],[4227,4],[4373,3]]},"189":{"position":[[357,4],[939,5],[1217,5]]},"190":{"position":[[99,4],[253,6],[497,3]]},"192":{"position":[[73,3],[635,4]]},"193":{"position":[[308,5],[881,5],[945,3],[1253,4],[1711,4],[2032,5],[2084,5],[3130,3]]},"194":{"position":[[125,3],[197,3],[575,4]]},"195":{"position":[[133,4],[557,5]]},"196":{"position":[[1073,3]]},"197":{"position":[[249,4],[670,3],[818,4],[1514,4]]},"199":{"position":[[361,4],[962,3],[1046,3],[1068,3]]}},"keywords":{}}],["usabl",{"_index":4083,"title":{},"content":{"125":{"position":[[3498,9]]},"148":{"position":[[222,6]]}},"keywords":{}}],["usag",{"_index":3765,"title":{"114":{"position":[[30,5]]}},"content":{"115":{"position":[[593,6]]},"132":{"position":[[200,5],[757,6],[1045,6]]},"135":{"position":[[29,6]]},"148":{"position":[[78,5]]},"160":{"position":[[990,6],[2787,5]]}},"keywords":{}}],["usedstd::mem::transmut",{"_index":4809,"title":{},"content":{"164":{"position":[[676,23]]}},"keywords":{}}],["usedthi",{"_index":4853,"title":{},"content":{"167":{"position":[[93,8]]}},"keywords":{}}],["useful.stat",{"_index":4631,"title":{},"content":{"159":{"position":[[478,13]]}},"keywords":{}}],["useinterior",{"_index":5066,"title":{},"content":{"179":{"position":[[242,11]]}},"keywords":{}}],["useless",{"_index":2542,"title":{},"content":{"66":{"position":[[97,7]]}},"keywords":{}}],["useno_hz",{"_index":4952,"title":{},"content":{"173":{"position":[[835,8]]}},"keywords":{}}],["usenumactl",{"_index":4971,"title":{},"content":{"173":{"position":[[2163,10]]}},"keywords":{}}],["user",{"_index":274,"title":{},"content":{"4":{"position":[[1005,5],[1171,5],[1491,5]]},"22":{"position":[[841,4]]},"44":{"position":[[436,5]]},"61":{"position":[[254,4],[487,4],[542,5],[607,5],[1127,4],[1465,4]]},"93":{"position":[[2447,6]]},"97":{"position":[[358,5]]},"108":{"position":[[348,5],[462,5],[541,5]]},"125":{"position":[[978,4]]},"188":{"position":[[1585,4],[1683,4],[2252,4],[2569,4],[2636,4],[3107,4]]},"189":{"position":[[1773,4],[2228,4],[2511,4],[2800,4]]}},"keywords":{}}],["user'",{"_index":1611,"title":{},"content":{"34":{"position":[[1200,6]]},"61":{"position":[[774,6],[965,6],[1010,6],[1082,6]]}},"keywords":{}}],["user_ag",{"_index":3221,"title":{},"content":{"93":{"position":[[2344,10],[2462,11]]}},"keywords":{}}],["usesdynam",{"_index":4675,"title":{},"content":{"160":{"position":[[1338,11]]}},"keywords":{}}],["usesit",{"_index":4362,"title":{},"content":{"133":{"position":[[52,7]]}},"keywords":{}}],["usetempl",{"_index":4936,"title":{},"content":{"172":{"position":[[2618,12]]}},"keywords":{}}],["usfederalholidaycalendar",{"_index":2964,"title":{},"content":{"90":{"position":[[250,24],[538,26]]}},"keywords":{}}],["usinghyp",{"_index":3392,"title":{},"content":{"97":{"position":[[2294,10]]}},"keywords":{}}],["usingresearch",{"_index":5007,"title":{},"content":{"175":{"position":[[404,13]]}},"keywords":{}}],["usingtaskset",{"_index":4951,"title":{},"content":{"173":{"position":[[812,13]]}},"keywords":{}}],["v",{"_index":4430,"title":{},"content":{"140":{"position":[[24,2],[158,1]]},"141":{"position":[[24,2]]},"144":{"position":[[296,1]]},"145":{"position":[[154,1]]},"146":{"position":[[237,1]]}},"keywords":{}}],["v.capac",{"_index":4453,"title":{},"content":{"144":{"position":[[254,12]]}},"keywords":{}}],["v.len",{"_index":4452,"title":{},"content":{"144":{"position":[[243,7]]}},"keywords":{}}],["v.pop().unwrap",{"_index":4463,"title":{},"content":{"145":{"position":[[429,17]]}},"keywords":{}}],["v.push(0",{"_index":4467,"title":{},"content":{"146":{"position":[[350,10]]}},"keywords":{}}],["v.push(1",{"_index":4469,"title":{},"content":{"146":{"position":[[494,10]]}},"keywords":{}}],["v.push(5",{"_index":4440,"title":{},"content":{"142":{"position":[[36,10]]},"144":{"position":[[267,10]]}},"keywords":{}}],["val",{"_index":2150,"title":{},"content":{"51":{"position":[[3626,5],[3710,4]]},"88":{"position":[[1094,4],[1183,5]]},"199":{"position":[[145,5],[309,5],[390,5]]}},"keywords":{}}],["valid",{"_index":480,"title":{},"content":{"10":{"position":[[46,8]]},"97":{"position":[[524,6]]},"130":{"position":[[495,5]]},"167":{"position":[[253,9]]},"175":{"position":[[1193,8]]}},"keywords":{}}],["vals.length",{"_index":5372,"title":{},"content":{"199":{"position":[[210,12]]}},"keywords":{}}],["vals[i",{"_index":5373,"title":{},"content":{"199":{"position":[[237,8]]}},"keywords":{}}],["valu",{"_index":449,"title":{"178":{"position":[[6,7]]},"182":{"position":[[7,7]]}},"content":{"8":{"position":[[151,6]]},"13":{"position":[[1851,5],[2253,5]]},"14":{"position":[[787,5],[1124,5],[2934,5],[3325,5]]},"15":{"position":[[655,5],[2608,5],[2996,5]]},"28":{"position":[[1592,7],[3378,7]]},"30":{"position":[[7141,5],[7185,5],[7267,5],[7334,6]]},"40":{"position":[[2268,6]]},"41":{"position":[[534,6]]},"44":{"position":[[118,7],[1107,6]]},"51":{"position":[[3221,6]]},"61":{"position":[[804,5]]},"68":{"position":[[754,6]]},"69":{"position":[[317,5],[377,5]]},"70":{"position":[[1290,5]]},"71":{"position":[[1068,5],[1472,6]]},"72":{"position":[[92,5],[153,5],[302,5],[355,5]]},"74":{"position":[[402,6]]},"75":{"position":[[561,5],[645,5],[1237,5]]},"76":{"position":[[610,6],[1609,6]]},"85":{"position":[[235,5]]},"91":{"position":[[3788,6]]},"96":{"position":[[2007,6]]},"97":{"position":[[4105,5],[5767,5]]},"113":{"position":[[2045,7],[2292,6]]},"116":{"position":[[110,6]]},"120":{"position":[[1073,6]]},"127":{"position":[[196,7],[1036,6]]},"128":{"position":[[211,6],[497,5]]},"129":{"position":[[941,5],[1144,5]]},"159":{"position":[[427,6]]},"172":{"position":[[1475,5]]},"178":{"position":[[8,5],[195,5],[321,5],[435,5],[542,6],[723,6]]},"179":{"position":[[538,6],[1431,6]]},"180":{"position":[[41,6],[130,6],[319,7],[495,5]]},"181":{"position":[[63,7],[197,5],[325,5],[403,5],[525,5],[673,5],[765,8],[932,6],[1003,6]]},"183":{"position":[[446,5],[592,5],[867,5]]},"188":{"position":[[1251,5],[1279,5]]},"193":{"position":[[2962,5],[3220,6],[3469,6]]},"196":{"position":[[348,6],[914,6],[1310,6]]}},"keywords":{}}],["valuabl",{"_index":2814,"title":{},"content":{"83":{"position":[[497,8]]}},"keywords":{}}],["valueerror",{"_index":949,"title":{},"content":{"22":{"position":[[1699,11]]},"91":{"position":[[3723,11]]}},"keywords":{}}],["vanilla",{"_index":5266,"title":{},"content":{"190":{"position":[[1044,7]]},"192":{"position":[[46,7]]}},"keywords":{}}],["vari",{"_index":155,"title":{},"content":{"3":{"position":[[448,7]]}},"keywords":{}}],["variabl",{"_index":2026,"title":{},"content":{"45":{"position":[[3383,9]]},"61":{"position":[[2170,8]]},"85":{"position":[[358,9]]},"91":{"position":[[4636,11]]},"93":{"position":[[206,11]]},"97":{"position":[[4748,11]]},"108":{"position":[[767,8]]},"113":{"position":[[481,8]]},"121":{"position":[[499,8]]},"127":{"position":[[1385,8]]},"166":{"position":[[383,8],[499,8]]},"182":{"position":[[8,9],[39,10],[178,8],[292,9],[351,10],[424,9],[493,9],[581,9],[688,10]]},"183":{"position":[[113,9],[164,9]]},"184":{"position":[[81,9],[844,9]]},"185":{"position":[[44,8],[164,9]]},"186":{"position":[[27,9]]},"193":{"position":[[82,9],[167,9]]},"194":{"position":[[640,9]]},"196":{"position":[[1674,8]]}},"keywords":{}}],["varianc",{"_index":4838,"title":{},"content":{"166":{"position":[[122,8]]},"172":{"position":[[1969,8]]},"173":{"position":[[2022,8]]},"174":{"position":[[227,8],[553,8],[1050,8]]},"175":{"position":[[1250,8]]},"176":{"position":[[1282,8],[1512,8]]}},"keywords":{}}],["variant",{"_index":5318,"title":{},"content":{"194":{"position":[[596,7]]}},"keywords":{}}],["variat",{"_index":2625,"title":{},"content":{"73":{"position":[[537,9]]}},"keywords":{}}],["variou",{"_index":4844,"title":{},"content":{"166":{"position":[[417,7]]}},"keywords":{}}],["vcat(color",{"_index":434,"title":{},"content":{"7":{"position":[[1181,12]]}},"keywords":{}}],["vcat(term[1",{"_index":517,"title":{},"content":{"11":{"position":[[375,13]]},"12":{"position":[[270,13]]}},"keywords":{}}],["vcat(x_tick",{"_index":427,"title":{},"content":{"7":{"position":[[1002,13]]}},"keywords":{}}],["vec",{"_index":4431,"title":{},"content":{"140":{"position":[[86,3]]},"159":{"position":[[1062,4]]},"199":{"position":[[1609,4]]}},"keywords":{}}],["vec<u8>",{"_index":3766,"title":{},"content":{"115":{"position":[[157,14]]},"116":{"position":[[257,14]]},"117":{"position":[[1049,14]]},"140":{"position":[[27,13]]},"142":{"position":[[19,14]]},"144":{"position":[[198,14]]},"156":{"position":[[1055,13]]}},"keywords":{}}],["vec,hashmap",{"_index":4593,"title":{},"content":{"156":{"position":[[364,12]]}},"keywords":{}}],["vec::<u8>::new",{"_index":4600,"title":{},"content":{"156":{"position":[[670,23]]}},"keywords":{}}],["vec::new",{"_index":3753,"title":{},"content":{"113":{"position":[[1607,11]]},"140":{"position":[[43,11]]},"156":{"position":[[547,11],[1071,11]]}},"keywords":{}}],["vec::with_capac",{"_index":4433,"title":{},"content":{"140":{"position":[[220,19]]}},"keywords":{}}],["vec::with_capacity(1",{"_index":4454,"title":{},"content":{"144":{"position":[[300,22]]},"145":{"position":[[158,22]]},"146":{"position":[[241,22]]}},"keywords":{}}],["vector",{"_index":3831,"title":{},"content":{"117":{"position":[[1491,8]]},"140":{"position":[[160,7]]},"142":{"position":[[83,6]]},"156":{"position":[[736,6]]},"164":{"position":[[1384,6]]},"165":{"position":[[564,8],[753,6],[807,6]]},"199":{"position":[[1311,7]]}},"keywords":{}}],["vec{",{"_index":782,"title":{},"content":{"20":{"position":[[656,7]]}},"keywords":{}}],["vec{1",{"_index":781,"title":{},"content":{"20":{"position":[[629,7]]}},"keywords":{}}],["vec{d",{"_index":785,"title":{},"content":{"20":{"position":[[685,7]]}},"keywords":{}}],["vein",{"_index":4656,"title":{},"content":{"160":{"position":[[416,5]]}},"keywords":{}}],["ventur",{"_index":4100,"title":{},"content":{"125":{"position":[[4808,8]]}},"keywords":{}}],["verbatim",{"_index":3884,"title":{},"content":{"121":{"position":[[696,8]]}},"keywords":{}}],["verbos",{"_index":1027,"title":{},"content":{"24":{"position":[[522,7]]},"25":{"position":[[247,7]]}},"keywords":{}}],["veri",{"_index":625,"title":{},"content":{"14":{"position":[[56,4]]},"15":{"position":[[38,4]]},"24":{"position":[[2899,4],[3088,4],[3425,4]]},"26":{"position":[[20,4],[564,4]]},"28":{"position":[[231,4],[295,4]]},"46":{"position":[[105,4]]},"61":{"position":[[1235,4],[1957,4]]},"68":{"position":[[765,4]]},"71":{"position":[[1425,4]]},"74":{"position":[[296,4]]},"82":{"position":[[1136,4]]},"83":{"position":[[72,4],[210,4]]},"86":{"position":[[868,4]]},"88":{"position":[[2062,4]]},"92":{"position":[[1303,4],[1661,4]]},"103":{"position":[[766,4],[802,4],[2259,4],[2352,4]]},"104":{"position":[[1231,4],[1582,4]]},"105":{"position":[[90,4]]},"106":{"position":[[329,4],[447,4]]},"121":{"position":[[1632,4]]},"125":{"position":[[133,6]]},"132":{"position":[[178,4],[793,4]]},"160":{"position":[[1260,4],[1825,4]]}},"keywords":{}}],["verifi",{"_index":2836,"title":{},"content":{"86":{"position":[[1137,6]]},"121":{"position":[[1595,7]]},"139":{"position":[[279,6]]},"142":{"position":[[230,6]]},"148":{"position":[[169,6]]}},"keywords":{}}],["versa",{"_index":1568,"title":{},"content":{"33":{"position":[[208,5]]}},"keywords":{}}],["version",{"_index":159,"title":{},"content":{"3":{"position":[[496,9]]},"96":{"position":[[875,8]]},"109":{"position":[[286,7]]},"112":{"position":[[1402,8],[1454,9]]},"122":{"position":[[1211,7]]},"125":{"position":[[675,8],[709,8],[7552,7],[7607,7],[7826,7],[7974,7],[8034,7]]},"136":{"position":[[1023,7]]},"148":{"position":[[254,7],[317,7]]},"163":{"position":[[451,7]]},"164":{"position":[[904,8]]},"172":{"position":[[2165,8]]},"188":{"position":[[1745,8],[2941,7]]}},"keywords":{}}],["veteran'",{"_index":2974,"title":{},"content":{"90":{"position":[[652,9]]}},"keywords":{}}],["via",{"_index":2393,"title":{},"content":{"62":{"position":[[43,3]]},"125":{"position":[[4168,3]]}},"keywords":{}}],["viawasm",{"_index":4130,"title":{},"content":{"125":{"position":[[6159,8]]}},"keywords":{}}],["vice",{"_index":1567,"title":{},"content":{"33":{"position":[[203,4]]}},"keywords":{}}],["video",{"_index":4647,"title":{},"content":{"160":{"position":[[76,6]]}},"keywords":{}}],["video/mp2t",{"_index":132,"title":{},"content":{"2":{"position":[[875,11]]}},"keywords":{}}],["view",{"_index":1396,"title":{},"content":{"30":{"position":[[4159,4]]},"125":{"position":[[376,6],[9522,5]]}},"keywords":{}}],["villag",{"_index":2033,"title":{},"content":{"46":{"position":[[467,7]]}},"keywords":{}}],["violent",{"_index":3167,"title":{},"content":{"91":{"position":[[4898,9],[5505,8]]},"93":{"position":[[573,10]]}},"keywords":{}}],["virtual",{"_index":4983,"title":{},"content":{"174":{"position":[[424,7],[903,7]]}},"keywords":{}}],["visit",{"_index":2371,"title":{},"content":{"61":{"position":[[1476,5],[1883,5]]},"96":{"position":[[507,9]]}},"keywords":{}}],["vite",{"_index":220,"title":{},"content":{"4":{"position":[[18,4],[27,4]]}},"keywords":{}}],["vix",{"_index":341,"title":{},"content":{"6":{"position":[[571,3]]}},"keywords":{}}],["vm",{"_index":4928,"title":{},"content":{"172":{"position":[[2052,2]]}},"keywords":{}}],["voic",{"_index":3458,"title":{},"content":{"100":{"position":[[177,6]]}},"keywords":{}}],["void",{"_index":4230,"title":{},"content":{"127":{"position":[[608,4],[1258,4]]},"128":{"position":[[230,4]]}},"keywords":{}}],["volatil",{"_index":342,"title":{},"content":{"6":{"position":[[583,11]]},"38":{"position":[[316,8]]},"40":{"position":[[937,8],[1546,11],[2536,8],[3241,8],[3460,8]]},"41":{"position":[[203,8],[306,8]]},"93":{"position":[[893,8]]},"152":{"position":[[815,8],[892,8]]}},"keywords":{}}],["vs",{"_index":1749,"title":{},"content":{"39":{"position":[[2321,3]]},"40":{"position":[[1619,3]]},"198":{"position":[[397,3],[424,3]]}},"keywords":{}}],["vtabl",{"_index":5341,"title":{},"content":{"197":{"position":[[346,6],[492,6],[1195,6]]}},"keywords":{}}],["vulner",{"_index":4975,"title":{},"content":{"174":{"position":[[80,15]]}},"keywords":{}}],["w",{"_index":3258,"title":{},"content":{"93":{"position":[[3336,4]]},"105":{"position":[[1854,2],[1960,2]]}},"keywords":{}}],["w.p",{"_index":2582,"title":{},"content":{"70":{"position":[[315,4],[334,4],[353,4],[373,4],[393,4],[413,4],[489,4],[509,4],[529,4],[549,4],[569,4],[588,4]]},"71":{"position":[[415,4],[434,4],[454,4],[474,4],[494,4],[514,4],[589,4],[608,4],[628,4],[648,4],[668,4],[688,4]]}},"keywords":{}}],["wait",{"_index":3791,"title":{},"content":{"115":{"position":[[2856,4]]},"116":{"position":[[2788,4]]},"139":{"position":[[471,7],[774,7]]},"172":{"position":[[2023,7]]},"173":{"position":[[2117,4]]},"174":{"position":[[684,4]]},"175":{"position":[[1166,4]]},"188":{"position":[[2187,4]]}},"keywords":{}}],["wake",{"_index":2248,"title":{},"content":{"53":{"position":[[1134,6],[2078,7]]}},"keywords":{}}],["walk",{"_index":4988,"title":{},"content":{"174":{"position":[[702,5]]}},"keywords":{}}],["wall",{"_index":5175,"title":{},"content":{"188":{"position":[[1623,4],[1721,4],[2293,4],[2609,4],[3145,4]]},"189":{"position":[[1813,4],[2269,4],[2552,4],[2838,4]]}},"keywords":{}}],["wanew",{"_index":1211,"title":{},"content":{"28":{"position":[[399,5]]}},"keywords":{}}],["want",{"_index":725,"title":{},"content":{"18":{"position":[[10,4]]},"20":{"position":[[803,4]]},"24":{"position":[[32,4]]},"28":{"position":[[346,4],[640,4]]},"30":{"position":[[2787,4],[4461,6],[5814,4],[9589,4]]},"32":{"position":[[187,4],[611,4]]},"33":{"position":[[801,4]]},"34":{"position":[[243,4],[289,4]]},"38":{"position":[[89,4],[170,4],[673,4],[1025,4],[1283,4]]},"39":{"position":[[55,4]]},"40":{"position":[[2354,4]]},"41":{"position":[[421,4]]},"44":{"position":[[1999,4]]},"45":{"position":[[1412,4]]},"51":{"position":[[1583,4]]},"53":{"position":[[277,4],[963,4]]},"61":{"position":[[517,4],[562,4],[1217,5]]},"65":{"position":[[384,4]]},"73":{"position":[[462,4],[753,4]]},"74":{"position":[[39,4]]},"89":{"position":[[495,4],[893,4]]},"90":{"position":[[34,4],[469,4]]},"91":{"position":[[27,4],[2656,4]]},"92":{"position":[[468,4]]},"93":{"position":[[586,4],[978,4],[1984,4]]},"96":{"position":[[341,4],[1034,5],[1442,4]]},"97":{"position":[[695,4],[1106,4],[4331,4],[6495,4]]},"100":{"position":[[400,4]]},"102":{"position":[[8,4],[745,4]]},"122":{"position":[[318,4],[444,6]]},"123":{"position":[[223,4],[843,4]]},"125":{"position":[[308,4],[3043,5],[8725,4],[10362,4],[10547,6]]},"127":{"position":[[1139,5]]},"129":{"position":[[1031,4]]},"139":{"position":[[59,4],[255,4]]},"140":{"position":[[183,6]]},"143":{"position":[[162,4],[230,4],[274,4]]},"157":{"position":[[248,4]]},"165":{"position":[[706,4]]},"172":{"position":[[2420,4]]},"176":{"position":[[610,4]]},"186":{"position":[[94,4]]},"189":{"position":[[1538,4]]},"197":{"position":[[662,4]]}},"keywords":{}}],["warm",{"_index":4741,"title":{},"content":{"161":{"position":[[842,4]]}},"keywords":{}}],["warnings.catch_warn",{"_index":1252,"title":{},"content":{"28":{"position":[[1642,26],[3428,26]]}},"keywords":{}}],["warnings.simplefilter('ignor",{"_index":1253,"title":{},"content":{"28":{"position":[[1669,31],[3455,31]]}},"keywords":{}}],["wasm",{"_index":4051,"title":{},"content":{"125":{"position":[[1600,5],[3573,4],[3721,4],[3892,4],[4199,4],[4476,4],[4931,4],[5053,4],[5270,4],[5818,4],[6126,4],[6140,4],[6476,5],[6561,4],[6586,4],[6764,4],[7142,4],[7215,4],[7618,4],[7662,4],[7785,4],[7837,4],[7873,4],[8082,4],[9352,4],[10705,4]]}},"keywords":{}}],["wasm/webassembl",{"_index":4053,"title":{},"content":{"125":{"position":[[1746,16]]}},"keywords":{}}],["wasm32",{"_index":4068,"title":{},"content":{"125":{"position":[[2714,6]]}},"keywords":{}}],["wasmus",{"_index":4141,"title":{},"content":{"125":{"position":[[6552,8]]}},"keywords":{}}],["wasn't",{"_index":113,"title":{},"content":{"2":{"position":[[598,6]]},"3":{"position":[[512,6]]},"104":{"position":[[1998,6]]},"132":{"position":[[243,6]]},"147":{"position":[[392,6]]},"161":{"position":[[679,6],[835,6],[1528,6]]},"164":{"position":[[1090,6]]}},"keywords":{}}],["wast",{"_index":3499,"title":{},"content":{"102":{"position":[[1524,7]]},"127":{"position":[[1220,9]]}},"keywords":{}}],["watch",{"_index":3871,"title":{},"content":{"121":{"position":[[39,8]]},"144":{"position":[[21,5]]},"173":{"position":[[205,5]]}},"keywords":{}}],["water",{"_index":3960,"title":{},"content":{"122":{"position":[[1290,5]]},"161":{"position":[[822,5],[1166,5],[1247,5],[1310,5]]}},"keywords":{}}],["wav",{"_index":3464,"title":{},"content":{"101":{"position":[[50,5]]},"103":{"position":[[232,4],[356,3]]},"105":{"position":[[580,4]]}},"keywords":{}}],["wave",{"_index":60,"title":{},"content":{"1":{"position":[[678,4]]}},"keywords":{}}],["wavfil",{"_index":3513,"title":{},"content":{"103":{"position":[[497,7]]}},"keywords":{}}],["wavfile.read('tabulasa.wav",{"_index":3515,"title":{},"content":{"103":{"position":[[528,28]]}},"keywords":{}}],["way",{"_index":212,"title":{},"content":{"3":{"position":[[1470,3]]},"4":{"position":[[404,3]]},"7":{"position":[[1100,3]]},"26":{"position":[[892,4]]},"34":{"position":[[1375,3]]},"40":{"position":[[1001,4],[1314,3]]},"43":{"position":[[1163,3]]},"45":{"position":[[519,3]]},"51":{"position":[[3136,3]]},"53":{"position":[[1115,3]]},"55":{"position":[[62,3]]},"61":{"position":[[1032,4]]},"65":{"position":[[1264,3]]},"68":{"position":[[709,4],[774,4]]},"71":{"position":[[1440,4]]},"73":{"position":[[64,3]]},"75":{"position":[[98,3]]},"89":{"position":[[94,3],[535,5]]},"91":{"position":[[4056,3]]},"97":{"position":[[5610,4]]},"101":{"position":[[311,4]]},"102":{"position":[[244,3],[531,3],[760,3]]},"104":{"position":[[132,3]]},"108":{"position":[[781,3]]},"112":{"position":[[1343,3]]},"117":{"position":[[919,4]]},"121":{"position":[[561,3],[660,5],[1810,3],[2686,4]]},"128":{"position":[[342,3]]},"129":{"position":[[2752,3]]},"130":{"position":[[29,3],[62,3]]},"132":{"position":[[671,4]]},"136":{"position":[[1002,3]]},"143":{"position":[[518,4]]},"152":{"position":[[216,3]]},"156":{"position":[[253,4]]},"160":{"position":[[99,3]]},"161":{"position":[[403,4]]},"164":{"position":[[1118,3]]},"172":{"position":[[739,3]]},"173":{"position":[[95,4]]},"176":{"position":[[1159,3],[1564,4]]},"194":{"position":[[740,3]]}},"keywords":{}}],["wb",{"_index":1499,"title":{},"content":{"30":{"position":[[10121,6]]}},"keywords":{}}],["we'd",{"_index":413,"title":{},"content":{"7":{"position":[[720,4]]},"45":{"position":[[523,4]]},"96":{"position":[[552,4]]},"101":{"position":[[215,4]]},"136":{"position":[[659,4]]},"173":{"position":[[1251,4]]}},"keywords":{}}],["we'll",{"_index":447,"title":{},"content":{"8":{"position":[[130,5]]},"12":{"position":[[60,5]]},"28":{"position":[[564,5],[1600,5],[3386,5]]},"30":{"position":[[773,5],[2691,5],[5892,5]]},"32":{"position":[[437,5]]},"33":{"position":[[950,5]]},"34":{"position":[[3075,5],[3162,5],[3635,5]]},"45":{"position":[[1220,5],[1833,5]]},"51":{"position":[[1026,5]]},"61":{"position":[[1341,5]]},"65":{"position":[[207,5]]},"81":{"position":[[1,5]]},"82":{"position":[[126,5]]},"88":{"position":[[719,5]]},"91":{"position":[[234,5]]},"92":{"position":[[1543,5]]},"93":{"position":[[4134,5]]},"95":{"position":[[1,5]]},"103":{"position":[[711,5],[1587,5]]},"105":{"position":[[305,5],[546,5],[700,5]]},"109":{"position":[[190,5]]},"110":{"position":[[553,5]]},"111":{"position":[[106,5]]},"113":{"position":[[889,5]]},"120":{"position":[[670,5]]},"133":{"position":[[162,5]]},"155":{"position":[[366,5]]},"160":{"position":[[3406,5],[3518,5],[3842,5],[4020,5]]},"182":{"position":[[401,5]]},"188":{"position":[[736,5]]},"189":{"position":[[1639,5]]},"198":{"position":[[694,5]]}},"keywords":{}}],["we'r",{"_index":312,"title":{},"content":{"6":{"position":[[171,5],[191,5]]},"7":{"position":[[700,5]]},"9":{"position":[[111,5],[246,5]]},"10":{"position":[[60,5]]},"12":{"position":[[1,5]]},"14":{"position":[[1170,5]]},"20":{"position":[[1930,5]]},"22":{"position":[[1,5]]},"23":{"position":[[36,5]]},"30":{"position":[[1083,5],[9150,5],[9189,5]]},"32":{"position":[[5,5]]},"34":{"position":[[1138,5]]},"40":{"position":[[2312,5]]},"43":{"position":[[74,5],[710,5],[1006,5],[1230,5],[1476,5]]},"45":{"position":[[1551,5],[2545,5]]},"52":{"position":[[548,5]]},"64":{"position":[[89,5],[482,5]]},"88":{"position":[[2204,5]]},"92":{"position":[[1,5]]},"97":{"position":[[1225,5],[2421,5],[4785,5]]},"103":{"position":[[1958,5]]},"110":{"position":[[1,5],[190,5],[279,5],[378,5]]},"111":{"position":[[776,5]]},"112":{"position":[[626,5]]},"113":{"position":[[1321,5]]},"115":{"position":[[21,5],[500,5]]},"116":{"position":[[2745,5],[2912,5]]},"117":{"position":[[72,5],[757,5],[2068,5]]},"124":{"position":[[52,5]]},"125":{"position":[[2520,5],[6079,5]]},"128":{"position":[[944,5],[1307,5],[1732,5]]},"129":{"position":[[814,5]]},"135":{"position":[[36,5]]},"146":{"position":[[467,5]]},"150":{"position":[[14,5]]},"160":{"position":[[745,5]]},"163":{"position":[[2329,5]]},"179":{"position":[[448,5]]},"186":{"position":[[395,5]]},"192":{"position":[[718,5]]}},"keywords":{}}],["we'v",{"_index":454,"title":{},"content":{"9":{"position":[[10,5]]},"10":{"position":[[10,5],[98,5]]},"13":{"position":[[10,5],[899,5]]},"14":{"position":[[1917,5]]},"15":{"position":[[1585,5]]},"34":{"position":[[13,5],[707,5],[895,5],[1846,5],[3268,5]]},"35":{"position":[[1,5]]},"44":{"position":[[927,5]]},"51":{"position":[[311,5],[1459,5]]},"52":{"position":[[649,5]]},"62":{"position":[[10,5],[1685,5]]},"71":{"position":[[53,5]]},"76":{"position":[[504,5],[1800,5]]},"82":{"position":[[1,5]]},"91":{"position":[[5944,5]]},"97":{"position":[[1633,5],[3361,5]]},"103":{"position":[[1510,5]]},"105":{"position":[[4,5]]},"109":{"position":[[584,5]]},"110":{"position":[[515,5]]},"111":{"position":[[577,5]]},"113":{"position":[[4,5],[2425,5]]},"116":{"position":[[628,5]]},"117":{"position":[[1893,5]]},"137":{"position":[[205,5]]},"146":{"position":[[330,5]]}},"keywords":{}}],["weather",{"_index":1195,"title":{"30":{"position":[[22,7]]}},"content":{"28":{"position":[[43,7]]},"29":{"position":[[274,7],[393,7]]},"30":{"position":[[67,7],[7518,7],[9131,7],[9269,7]]}},"keywords":{}}],["web",{"_index":885,"title":{},"content":{"22":{"position":[[206,3]]},"97":{"position":[[752,3]]},"125":{"position":[[4422,3],[4541,3],[8826,3],[9602,3],[11156,4],[11345,3],[11373,3]]},"139":{"position":[[410,3]]}},"keywords":{}}],["webapi",{"_index":4173,"title":{},"content":{"125":{"position":[[8793,7]]}},"keywords":{}}],["webassembl",{"_index":4097,"title":{},"content":{"125":{"position":[[4397,11]]}},"keywords":{}}],["webpack",{"_index":0,"title":{"0":{"position":[[4,7]]}},"content":{"3":{"position":[[721,7],[802,7],[945,7],[1151,7]]},"4":{"position":[[1184,8],[1300,8]]},"125":{"position":[[3967,7],[4172,7],[5122,7],[6180,9],[6645,7],[8457,7],[11036,7]]}},"keywords":{}}],["websit",{"_index":4104,"title":{},"content":{"125":{"position":[[4946,7]]}},"keywords":{}}],["week",{"_index":288,"title":{},"content":{"4":{"position":[[1284,4]]},"123":{"position":[[386,6]]},"125":{"position":[[166,5],[2467,5]]}},"keywords":{}}],["weekdayloc",{"_index":2848,"title":{},"content":{"88":{"position":[[444,16]]}},"keywords":{}}],["weekdaylocator(monday",{"_index":2868,"title":{},"content":{"88":{"position":[[1199,22]]}},"keywords":{}}],["weekend",{"_index":4356,"title":{},"content":{"132":{"position":[[862,7]]}},"keywords":{}}],["weekformatt",{"_index":2870,"title":{},"content":{"88":{"position":[[1245,13]]}},"keywords":{}}],["weekli",{"_index":3972,"title":{},"content":{"123":{"position":[[213,7]]}},"keywords":{}}],["weird",{"_index":2706,"title":{"126":{"position":[[23,5]]}},"content":{"76":{"position":[[1400,5]]},"97":{"position":[[2514,5]]},"120":{"position":[[330,5]]},"121":{"position":[[1870,5]]},"156":{"position":[[529,6]]},"196":{"position":[[536,5]]},"198":{"position":[[60,5]]}},"keywords":{}}],["weirder",{"_index":5124,"title":{},"content":{"184":{"position":[[423,7]]}},"keywords":{}}],["welcom",{"_index":696,"title":{"16":{"position":[[0,8]]}},"content":{},"keywords":{}}],["well",{"_index":125,"title":{},"content":{"2":{"position":[[772,5]]},"3":{"position":[[693,5]]},"25":{"position":[[82,5],[2609,5]]},"28":{"position":[[2324,5],[2469,5],[4101,5]]},"29":{"position":[[254,4]]},"30":{"position":[[4499,4]]},"34":{"position":[[975,5]]},"40":{"position":[[2142,5],[2528,4]]},"44":{"position":[[1753,4]]},"45":{"position":[[42,4]]},"46":{"position":[[315,5]]},"53":{"position":[[1905,5]]},"66":{"position":[[1,5]]},"76":{"position":[[64,4]]},"78":{"position":[[60,4]]},"82":{"position":[[1288,5]]},"89":{"position":[[402,4]]},"90":{"position":[[4738,5]]},"91":{"position":[[1693,4]]},"98":{"position":[[135,4],[786,4]]},"102":{"position":[[273,4],[408,5]]},"103":{"position":[[2357,5]]},"104":{"position":[[1786,5]]},"106":{"position":[[100,4]]},"115":{"position":[[842,5]]},"121":{"position":[[1500,4]]},"122":{"position":[[1127,4]]},"123":{"position":[[1069,4]]},"125":{"position":[[9245,5]]},"132":{"position":[[356,4]]},"156":{"position":[[1162,5]]},"165":{"position":[[1480,5]]},"166":{"position":[[620,5]]},"176":{"position":[[1294,5]]},"185":{"position":[[13,4]]},"188":{"position":[[117,4]]},"197":{"position":[[286,5]]}},"keywords":{}}],["went",{"_index":1803,"title":{},"content":{"40":{"position":[[701,4]]},"125":{"position":[[3410,4]]},"132":{"position":[[842,4]]},"136":{"position":[[939,4]]}},"keywords":{}}],["weren't",{"_index":1397,"title":{},"content":{"30":{"position":[[4192,7]]}},"keywords":{}}],["what'",{"_index":1810,"title":{},"content":{"40":{"position":[[1353,6]]},"44":{"position":[[1041,6]]},"61":{"position":[[51,6]]},"96":{"position":[[1337,6]]},"97":{"position":[[2127,6]]},"160":{"position":[[1906,6]]}},"keywords":{}}],["whatsoev",{"_index":3657,"title":{},"content":{"106":{"position":[[924,11]]}},"keywords":{}}],["wheel",{"_index":2296,"title":{},"content":{"55":{"position":[[45,6]]},"190":{"position":[[664,6]]}},"keywords":{}}],["whena",{"_index":4622,"title":{},"content":{"158":{"position":[[198,5]]}},"keywords":{}}],["whendtpars",{"_index":4344,"title":{},"content":{"132":{"position":[[276,11]]}},"keywords":{}}],["whenev",{"_index":2358,"title":{},"content":{"61":{"position":[[810,8]]},"72":{"position":[[70,8]]},"90":{"position":[[4897,8]]},"143":{"position":[[51,8]]},"172":{"position":[[263,8]]},"188":{"position":[[586,8]]}},"keywords":{}}],["wherenom",{"_index":4797,"title":{},"content":{"163":{"position":[[2224,8]]}},"keywords":{}}],["wherev",{"_index":4630,"title":{},"content":{"159":{"position":[[469,8]]},"178":{"position":[[730,8]]}},"keywords":{}}],["whether",{"_index":1224,"title":{},"content":{"28":{"position":[[783,7]]},"30":{"position":[[13,7]]},"41":{"position":[[360,7]]},"72":{"position":[[721,7]]},"73":{"position":[[786,7]]},"102":{"position":[[1437,7],[1512,7]]},"142":{"position":[[71,7]]},"159":{"position":[[239,7]]},"160":{"position":[[2624,7]]},"175":{"position":[[391,7]]}},"keywords":{}}],["whiledateutil",{"_index":3901,"title":{},"content":{"121":{"position":[[1476,13]]}},"keywords":{}}],["whileon",{"_index":3887,"title":{},"content":{"121":{"position":[[873,8]]}},"keywords":{}}],["whine",{"_index":3398,"title":{},"content":{"97":{"position":[[3166,8]]}},"keywords":{}}],["whip",{"_index":4038,"title":{},"content":{"125":{"position":[[1249,4]]}},"keywords":{}}],["whitacr",{"_index":2258,"title":{},"content":{"53":{"position":[[1233,8]]}},"keywords":{}}],["whitespac",{"_index":3909,"title":{},"content":{"121":{"position":[[1713,10]]}},"keywords":{}}],["whole",{"_index":1369,"title":{},"content":{"30":{"position":[[2303,5],[3975,6]]},"40":{"position":[[3070,5]]},"53":{"position":[[1644,5],[2190,5]]},"93":{"position":[[537,5]]},"117":{"position":[[556,5]]},"121":{"position":[[541,5]]},"165":{"position":[[324,6]]},"175":{"position":[[1179,5]]}},"keywords":{}}],["whop",{"_index":3100,"title":{},"content":{"91":{"position":[[1530,8]]}},"keywords":{}}],["whose",{"_index":4252,"title":{},"content":{"128":{"position":[[403,5]]},"190":{"position":[[314,5]]}},"keywords":{}}],["whynotu8",{"_index":5342,"title":{},"content":{"197":{"position":[[391,8],[426,8],[1206,10],[1323,8]]}},"keywords":{}}],["whyw",{"_index":3855,"title":{},"content":{"120":{"position":[[627,5]]}},"keywords":{}}],["wide",{"_index":3183,"title":{},"content":{"92":{"position":[[1506,4]]}},"keywords":{}}],["wider",{"_index":1377,"title":{},"content":{"30":{"position":[[2675,5]]}},"keywords":{}}],["width",{"_index":3165,"title":{},"content":{"91":{"position":[[4813,5],[5860,5]]}},"keywords":{}}],["width=1",{"_index":2765,"title":{},"content":{"78":{"position":[[522,8],[719,8]]}},"keywords":{}}],["wild",{"_index":2447,"title":{"63":{"position":[[0,4]]}},"content":{},"keywords":{}}],["wildli",{"_index":2396,"title":{},"content":{"62":{"position":[[192,6]]}},"keywords":{}}],["will",{"_index":5001,"title":{},"content":{"175":{"position":[[47,7]]}},"keywords":{}}],["willchang",{"_index":5133,"title":{},"content":{"184":{"position":[[1206,10]]}},"keywords":{}}],["win",{"_index":1582,"title":{},"content":{"33":{"position":[[991,7],[1168,7]]}},"keywords":{}}],["window",{"_index":3223,"title":{},"content":{"93":{"position":[[2370,8]]},"125":{"position":[[3430,6]]},"134":{"position":[[88,9]]},"173":{"position":[[264,7]]}},"keywords":{}}],["winner",{"_index":2247,"title":{},"content":{"53":{"position":[[1125,8]]}},"keywords":{}}],["wire",{"_index":4825,"title":{},"content":{"165":{"position":[[283,4]]}},"keywords":{}}],["wise",{"_index":2259,"title":{},"content":{"53":{"position":[[1249,4]]}},"keywords":{}}],["wish",{"_index":2485,"title":{},"content":{"64":{"position":[[1525,4]]}},"keywords":{}}],["wishlist",{"_index":4203,"title":{},"content":{"125":{"position":[[10926,8]]}},"keywords":{}}],["with"cut",{"_index":5033,"title":{},"content":{"175":{"position":[[1474,13]]}},"keywords":{}}],["with/without",{"_index":679,"title":{},"content":{"15":{"position":[[1280,12]]}},"keywords":{}}],["with:parse(timestr",{"_index":3864,"title":{},"content":{"120":{"position":[[900,20]]}},"keywords":{}}],["withconst/stat",{"_index":5109,"title":{},"content":{"182":{"position":[[267,17]]}},"keywords":{}}],["within",{"_index":1410,"title":{},"content":{"30":{"position":[[5622,6]]},"45":{"position":[[477,6],[602,6]]},"83":{"position":[[275,6]]},"125":{"position":[[2230,6],[2446,6]]},"135":{"position":[[398,6],[469,6]]}},"keywords":{}}],["within_leverag",{"_index":840,"title":{},"content":{"20":{"position":[[2094,15]]}},"keywords":{}}],["within_leverage(x",{"_index":832,"title":{},"content":{"20":{"position":[[1824,19]]}},"keywords":{}}],["without",{"_index":381,"title":{"14":{"position":[[8,7]]}},"content":{"7":{"position":[[112,7],[1115,7]]},"14":{"position":[[35,7],[2951,7],[3342,7]]},"29":{"position":[[406,7]]},"33":{"position":[[122,7]]},"45":{"position":[[1168,7]]},"61":{"position":[[152,7],[977,7]]},"64":{"position":[[1434,7]]},"97":{"position":[[6336,7]]},"104":{"position":[[1911,7]]},"106":{"position":[[358,7]]},"123":{"position":[[413,7]]},"125":{"position":[[4486,7]]},"160":{"position":[[2351,7]]},"163":{"position":[[761,7]]},"165":{"position":[[1341,7]]},"188":{"position":[[418,7],[1764,7]]}},"keywords":{}}],["withoutstd::vec",{"_index":4694,"title":{},"content":{"160":{"position":[[2455,16]]}},"keywords":{}}],["wmt",{"_index":3212,"title":{},"content":{"93":{"position":[[1952,3]]}},"keywords":{}}],["won't",{"_index":1705,"title":{},"content":{"39":{"position":[[6,5]]},"51":{"position":[[3078,5]]},"97":{"position":[[827,5],[5911,5]]},"101":{"position":[[737,5]]},"102":{"position":[[928,5]]},"111":{"position":[[893,5]]},"172":{"position":[[2519,5]]},"176":{"position":[[1010,5]]},"186":{"position":[[512,5]]},"195":{"position":[[988,5]]},"198":{"position":[[921,5]]}},"keywords":{}}],["wonder",{"_index":4347,"title":{},"content":{"132":{"position":[[449,9]]},"193":{"position":[[15,8]]}},"keywords":{}}],["woodchuck",{"_index":2056,"title":{},"content":{"49":{"position":[[283,9]]}},"keywords":{}}],["word",{"_index":2053,"title":{},"content":{"49":{"position":[[93,6],[137,5],[215,5],[238,5],[278,4]]},"51":{"position":[[406,5],[800,4],[823,4],[892,6],[918,5],[1109,5],[1284,4],[1366,5],[2869,4],[3031,5],[3477,5]]},"52":{"position":[[124,5],[580,5]]}},"keywords":{}}],["word_dist",{"_index":2102,"title":{},"content":{"51":{"position":[[1265,9],[4105,11]]},"52":{"position":[[223,10],[264,10],[305,10],[346,10],[1074,10]]}},"keywords":{}}],["word_dist[word",{"_index":2108,"title":{},"content":{"51":{"position":[[1419,15]]}},"keywords":{}}],["words.th",{"_index":2059,"title":{},"content":{"49":{"position":[[439,9]]}},"keywords":{}}],["work",{"_index":124,"title":{},"content":{"2":{"position":[[764,7]]},"3":{"position":[[1542,5]]},"34":{"position":[[139,4]]},"35":{"position":[[197,4]]},"39":{"position":[[89,4]]},"41":{"position":[[388,4]]},"43":{"position":[[60,5],[217,5],[1012,7]]},"54":{"position":[[263,4]]},"55":{"position":[[164,6]]},"57":{"position":[[281,4]]},"58":{"position":[[23,4],[910,4]]},"64":{"position":[[112,4]]},"73":{"position":[[329,5]]},"74":{"position":[[283,7],[1194,4]]},"75":{"position":[[105,5]]},"76":{"position":[[3393,5]]},"82":{"position":[[19,7]]},"91":{"position":[[2201,4]]},"93":{"position":[[1028,4]]},"95":{"position":[[308,4],[347,7]]},"96":{"position":[[2332,6]]},"97":{"position":[[651,5],[1177,7],[3372,7],[3859,7]]},"98":{"position":[[25,5]]},"100":{"position":[[17,7],[118,7],[310,4],[408,4]]},"102":{"position":[[461,5]]},"104":{"position":[[861,4]]},"106":{"position":[[87,5]]},"108":{"position":[[648,4],[849,5]]},"116":{"position":[[892,5]]},"117":{"position":[[1447,7],[1925,4]]},"121":{"position":[[8,6],[890,6]]},"123":{"position":[[635,7]]},"125":{"position":[[3258,4],[4081,6],[6965,4],[8733,4],[10009,5],[11084,4]]},"128":{"position":[[1707,7]]},"132":{"position":[[350,5]]},"141":{"position":[[111,4]]},"150":{"position":[[667,8]]},"158":{"position":[[258,4]]},"164":{"position":[[529,4],[1462,4]]},"165":{"position":[[847,4],[1456,4]]},"166":{"position":[[614,5]]},"172":{"position":[[677,4]]},"174":{"position":[[954,4]]},"183":{"position":[[803,4]]},"184":{"position":[[482,6]]},"188":{"position":[[720,4]]},"189":{"position":[[67,5],[427,5]]},"192":{"position":[[730,7]]},"193":{"position":[[1408,4]]}},"keywords":{}}],["work"",{"_index":296,"title":{},"content":{"4":{"position":[[1470,10]]},"188":{"position":[[762,10]]}},"keywords":{}}],["work?"",{"_index":4059,"title":{},"content":{"125":{"position":[[2170,11]]}},"keywords":{}}],["workaround",{"_index":4106,"title":{},"content":{"125":{"position":[[5090,10]]}},"keywords":{}}],["worker",{"_index":175,"title":{},"content":{"3":{"position":[[818,6]]},"121":{"position":[[1335,6]]}},"keywords":{}}],["workflow",{"_index":2369,"title":{},"content":{"61":{"position":[[1375,9]]}},"keywords":{}}],["worki",{"_index":240,"title":{},"content":{"4":{"position":[[426,5]]}},"keywords":{}}],["worklet",{"_index":87,"title":{},"content":{"2":{"position":[[176,8],[323,7],[537,8],[632,7]]},"3":{"position":[[223,7],[994,7],[1377,7]]}},"keywords":{}}],["worklets,"",{"_index":227,"title":{},"content":{"4":{"position":[[109,15]]}},"keywords":{}}],["world",{"_index":2548,"title":{},"content":{"66":{"position":[[597,6]]},"104":{"position":[[724,6]]},"160":{"position":[[774,5]]},"174":{"position":[[485,7]]}},"keywords":{}}],["world"",{"_index":4686,"title":{},"content":{"160":{"position":[[2145,11]]},"172":{"position":[[632,11]]}},"keywords":{}}],["worldwid",{"_index":1213,"title":{},"content":{"28":{"position":[[459,9]]}},"keywords":{}}],["worri",{"_index":77,"title":{},"content":{"2":{"position":[[41,5]]},"38":{"position":[[1329,8]]},"40":{"position":[[731,5]]},"45":{"position":[[1176,8],[1457,5]]},"98":{"position":[[696,5]]},"111":{"position":[[899,5]]},"122":{"position":[[827,5]]},"127":{"position":[[383,5]]},"160":{"position":[[1569,5]]},"194":{"position":[[16,7]]}},"keywords":{}}],["wors",{"_index":2668,"title":{},"content":{"75":{"position":[[829,6]]}},"keywords":{}}],["worse.typ",{"_index":4636,"title":{},"content":{"159":{"position":[[858,11]]}},"keywords":{}}],["worst",{"_index":1430,"title":{},"content":{"30":{"position":[[7534,5]]},"124":{"position":[[292,7]]},"170":{"position":[[244,5],[272,5]]}},"keywords":{}}],["worth",{"_index":2338,"title":{},"content":{"58":{"position":[[735,5]]},"66":{"position":[[250,5]]},"157":{"position":[[89,5]]},"160":{"position":[[4441,5]]},"161":{"position":[[458,5]]},"163":{"position":[[2386,5]]},"166":{"position":[[756,5]]},"174":{"position":[[981,6]]}},"keywords":{}}],["worthless",{"_index":1964,"title":{},"content":{"45":{"position":[[262,9]]}},"keywords":{}}],["wouldn't",{"_index":3451,"title":{},"content":{"98":{"position":[[957,8]]},"125":{"position":[[3177,8]]},"150":{"position":[[433,8]]}},"keywords":{}}],["wow",{"_index":1931,"title":{},"content":{"44":{"position":[[911,4]]}},"keywords":{}}],["wow64",{"_index":3226,"title":{},"content":{"93":{"position":[[2388,6]]}},"keywords":{}}],["wrangl",{"_index":1713,"title":{},"content":{"39":{"position":[[320,9]]}},"keywords":{}}],["wrap",{"_index":4654,"title":{},"content":{"160":{"position":[[371,7]]},"194":{"position":[[29,8]]}},"keywords":{}}],["wrapper",{"_index":5149,"title":{},"content":{"188":{"position":[[175,8]]}},"keywords":{}}],["write",{"_index":7,"title":{"110":{"position":[[8,7]]}},"content":{"1":{"position":[[38,5]]},"4":{"position":[[790,7]]},"6":{"position":[[403,8]]},"20":{"position":[[1188,5]]},"53":{"position":[[473,7]]},"76":{"position":[[845,5]]},"86":{"position":[[658,5]]},"95":{"position":[[563,5]]},"96":{"position":[[288,6]]},"97":{"position":[[263,5]]},"108":{"position":[[67,5]]},"109":{"position":[[635,7]]},"110":{"position":[[27,7]]},"121":{"position":[[1114,7]]},"122":{"position":[[638,7],[668,7]]},"125":{"position":[[2273,7],[9396,7]]},"132":{"position":[[699,7],[813,5]]},"137":{"position":[[31,5]]},"139":{"position":[[67,5],[402,7]]},"148":{"position":[[29,7],[420,5]]},"158":{"position":[[6,7],[103,5],[432,5]]},"160":{"position":[[2214,7],[2632,7],[4115,7]]},"161":{"position":[[1600,7]]},"163":{"position":[[769,7],[2475,5]]},"168":{"position":[[119,5]]},"173":{"position":[[983,7]]},"188":{"position":[[208,7]]}},"keywords":{}}],["writei",{"_index":4415,"title":{},"content":{"139":{"position":[[248,6]]}},"keywords":{}}],["writing)qqq",{"_index":321,"title":{},"content":{"6":{"position":[[320,11]]}},"keywords":{}}],["written",{"_index":2169,"title":{},"content":{"52":{"position":[[72,7]]},"173":{"position":[[226,7]]}},"keywords":{}}],["wrong",{"_index":3163,"title":{},"content":{"91":{"position":[[4727,5]]},"121":{"position":[[2555,6]]},"136":{"position":[[96,5]]}},"keywords":{}}],["wrote",{"_index":3719,"title":{},"content":{"112":{"position":[[1155,5]]},"121":{"position":[[2546,5]]},"173":{"position":[[10,5]]}},"keywords":{}}],["wxwdidget",{"_index":4047,"title":{},"content":{"125":{"position":[[1341,10]]}},"keywords":{}}],["wxwidget",{"_index":4040,"title":{},"content":{"125":{"position":[[1267,10]]}},"keywords":{}}],["x",{"_index":409,"title":{},"content":{"7":{"position":[[659,1]]},"20":{"position":[[1469,2],[1806,2],[1893,2],[1987,1],[2227,2]]},"22":{"position":[[536,2],[1496,2]]},"28":{"position":[[1402,2],[1506,2],[1509,1],[2246,1],[3197,2],[3297,2],[3300,1],[3919,1]]},"30":{"position":[[1768,2],[1867,2],[1870,1],[2147,1],[3117,2],[3216,2],[3219,1],[3633,1],[3852,1],[5036,2],[5131,2],[5134,1],[5406,1],[6185,2],[6285,2],[6288,1],[6706,1],[6931,1],[9428,2]]},"39":{"position":[[2710,2],[2769,2],[2834,2],[2900,2],[3013,2]]},"40":{"position":[[2168,3]]},"43":{"position":[[540,1]]},"51":{"position":[[551,2],[1141,2],[1245,1],[2268,2],[2275,1],[2367,1],[3294,2],[3332,1]]},"62":{"position":[[1064,2],[1102,2]]},"70":{"position":[[961,1]]},"74":{"position":[[608,1],[626,1],[663,1],[685,1]]},"76":{"position":[[608,1]]},"90":{"position":[[4105,1]]},"91":{"position":[[2030,2],[2044,2]]},"93":{"position":[[2776,2],[2846,2],[2849,1],[4443,2],[4457,2]]},"108":{"position":[[460,1]]},"110":{"position":[[472,1]]},"112":{"position":[[1708,1]]},"113":{"position":[[2284,1]]},"127":{"position":[[639,1],[1289,1]]},"128":{"position":[[276,1],[510,3],[574,3],[1148,1],[1400,3]]},"129":{"position":[[1442,2],[1563,2],[1932,1],[2617,1]]},"152":{"position":[[657,3],[721,1]]},"156":{"position":[[1052,2]]},"184":{"position":[[166,2],[273,2],[525,2],[593,2]]},"185":{"position":[[671,2],[831,2]]},"192":{"position":[[130,2],[310,2],[392,2]]},"193":{"position":[[921,2],[1784,2],[1819,2],[1851,2],[2226,2],[2739,2],[2774,2],[2806,2],[3192,2]]},"194":{"position":[[275,2],[327,1],[394,2]]},"196":{"position":[[976,1],[1134,2],[1555,1],[1594,4],[1757,1],[1791,4]]},"197":{"position":[[402,2],[549,2],[1128,1],[1334,2],[1362,2]]},"198":{"position":[[1009,2],[1144,2]]},"199":{"position":[[1352,1]]}},"keywords":{}}],["x+i",{"_index":2097,"title":{},"content":{"51":{"position":[[1147,4]]}},"keywords":{}}],["x.__str__",{"_index":4332,"title":{},"content":{"129":{"position":[[2636,11]]}},"keywords":{}}],["x.column",{"_index":1901,"title":{},"content":{"44":{"position":[[212,9]]}},"keywords":{}}],["x.drop(b_class",{"_index":1993,"title":{},"content":{"45":{"position":[[1993,15]]}},"keywords":{}}],["x.iter().enumer",{"_index":5383,"title":{},"content":{"199":{"position":[[1489,20]]}},"keywords":{}}],["x.nonzero()[1",{"_index":2596,"title":{},"content":{"70":{"position":[[1008,14]]}},"keywords":{}}],["x.union(i",{"_index":1482,"title":{},"content":{"30":{"position":[[9434,11]]}},"keywords":{}}],["x.valu",{"_index":5387,"title":{},"content":{"199":{"position":[[1679,10]]}},"keywords":{}}],["x1",{"_index":2599,"title":{},"content":{"70":{"position":[[1107,2]]},"71":{"position":[[1258,2]]},"193":{"position":[[1334,2],[1425,3],[1437,3],[2514,2],[3285,2],[3349,3],[3361,3],[3599,2],[3663,3],[3675,3]]}},"keywords":{}}],["x2",{"_index":2601,"title":{},"content":{"70":{"position":[[1134,2]]},"71":{"position":[[1285,2]]},"193":{"position":[[1348,2],[1431,3],[1443,4],[2528,2],[3299,2],[3355,3],[3367,4],[3613,2],[3669,3],[3681,4]]}},"keywords":{}}],["x2).plot(kind='hist",{"_index":2604,"title":{},"content":{"70":{"position":[[1176,21]]},"71":{"position":[[1327,21]]}},"keywords":{}}],["x[0",{"_index":898,"title":{},"content":{"22":{"position":[[539,4],[1499,4]]},"28":{"position":[[2236,5],[3909,5]]},"39":{"position":[[3016,5]]},"51":{"position":[[554,5],[1219,4],[2293,4],[2388,4]]}},"keywords":{}}],["x[0][0",{"_index":1771,"title":{},"content":{"39":{"position":[[2923,8]]}},"keywords":{}}],["x[1",{"_index":1764,"title":{},"content":{"39":{"position":[[2713,5]]}},"keywords":{}}],["x_axis_label='year",{"_index":1272,"title":{},"content":{"28":{"position":[[2142,20],[3806,20]]},"30":{"position":[[2122,20],[3608,20],[3815,20],[5381,20],[6681,20],[6894,20]]}},"keywords":{}}],["x_bin",{"_index":1913,"title":{},"content":{"44":{"position":[[602,5]]}},"keywords":{}}],["x_no_bin",{"_index":1992,"title":{},"content":{"45":{"position":[[1982,8]]}},"keywords":{}}],["x_pow",{"_index":5288,"title":{},"content":{"193":{"position":[[1417,5],[1497,5],[2570,5],[2658,5],[3341,5],[3421,5],[3655,5],[3735,5]]}},"keywords":{}}],["x_range=(1990",{"_index":1363,"title":{},"content":{"30":{"position":[[2100,14],[3586,14],[3793,14],[5359,14],[6659,14],[6872,14]]}},"keywords":{}}],["x_tick",{"_index":425,"title":{},"content":{"7":{"position":[[954,7],[992,7]]}},"keywords":{}}],["x_xform",{"_index":1996,"title":{},"content":{"45":{"position":[[2065,7],[2852,7]]}},"keywords":{}}],["xlabel",{"_index":420,"title":{},"content":{"7":{"position":[[844,6],[895,6]]}},"keywords":{}}],["xml",{"_index":4848,"title":{},"content":{"166":{"position":[[730,3]]}},"keywords":{}}],["xom",{"_index":710,"title":{},"content":{"17":{"position":[[154,7]]},"18":{"position":[[331,6]]},"19":{"position":[[553,6]]},"20":{"position":[[473,6],[2827,8]]}},"keywords":{}}],["xtick",{"_index":414,"title":{},"content":{"7":{"position":[[743,5]]}},"keywords":{}}],["xxx",{"_index":2091,"title":{},"content":{"51":{"position":[[831,4]]}},"keywords":{}}],["xyz",{"_index":3790,"title":{},"content":{"115":{"position":[[2655,3]]}},"keywords":{}}],["y",{"_index":1258,"title":{},"content":{"28":{"position":[[1853,2],[1867,1],[3601,2],[3615,1]]},"30":{"position":[[2023,1],[3429,1],[3517,1],[5273,1],[6503,1],[6591,1],[9431,2]]},"43":{"position":[[586,1]]},"44":{"position":[[665,2]]},"45":{"position":[[2139,2],[2168,2],[2919,2],[2948,2]]},"51":{"position":[[1144,2],[3301,2],[3356,1]]},"62":{"position":[[559,3],[1105,3]]},"88":{"position":[[755,3]]},"93":{"position":[[4170,3]]},"110":{"position":[[485,1]]},"112":{"position":[[1714,1]]},"113":{"position":[[2290,1]]},"127":{"position":[[1304,1],[1394,1],[1468,1]]},"152":{"position":[[690,1],[726,3],[875,3]]},"185":{"position":[[679,2],[837,2]]},"192":{"position":[[138,2],[316,2],[398,2]]},"193":{"position":[[929,2],[1790,2],[1825,2],[1857,2],[2234,2],[2745,2],[2780,2],[2812,2],[3200,2]]},"194":{"position":[[286,2],[353,1],[397,1]]},"196":{"position":[[1574,1],[1589,4],[1776,1],[1796,4]]},"199":{"position":[[1347,1],[1361,2],[1483,2],[1517,2],[1674,1],[1697,2]]}},"keywords":{}}],["y.uniqu",{"_index":1873,"title":{},"content":{"43":{"position":[[607,10]]}},"keywords":{}}],["y1",{"_index":5284,"title":{},"content":{"193":{"position":[[1362,2],[1460,3],[1472,3],[2542,2],[3313,2],[3384,3],[3396,3],[3627,2],[3698,3],[3710,3]]}},"keywords":{}}],["y2",{"_index":5286,"title":{},"content":{"193":{"position":[[1376,2],[1466,3],[1478,4],[2556,2],[3327,2],[3390,3],[3402,4],[3641,2],[3704,3],[3716,4]]}},"keywords":{}}],["y=motion",{"_index":437,"title":{},"content":{"7":{"position":[[1219,10]]}},"keywords":{}}],["y[i",{"_index":1936,"title":{},"content":{"44":{"position":[[1338,3]]}},"keywords":{}}],["y_axis_label='cloud",{"_index":1273,"title":{},"content":{"28":{"position":[[2163,19]]}},"keywords":{}}],["y_axis_label='precipit",{"_index":1305,"title":{},"content":{"28":{"position":[[3827,27]]}},"keywords":{}}],["y_pow",{"_index":5289,"title":{},"content":{"193":{"position":[[1452,5],[1505,6],[2609,5],[2666,6],[3376,5],[3429,6],[3690,5],[3743,6]]}},"keywords":{}}],["yahoo/celg",{"_index":1827,"title":{},"content":{"40":{"position":[[2652,13]]}},"keywords":{}}],["yaml",{"_index":3103,"title":{},"content":{"91":{"position":[[1848,4]]},"93":{"position":[[1452,4],[3858,4]]}},"keywords":{}}],["yaml.load('\\n'.join(filt",{"_index":3114,"title":{},"content":{"91":{"position":[[2085,30]]},"93":{"position":[[4498,30]]}},"keywords":{}}],["yarn",{"_index":4077,"title":{},"content":{"125":{"position":[[3133,4],[3157,4],[6403,4]]}},"keywords":{}}],["ye",{"_index":4436,"title":{},"content":{"141":{"position":[[80,4]]}},"keywords":{}}],["year",{"_index":347,"title":{},"content":{"6":{"position":[[669,5],[760,4],[977,5],[1029,4]]},"7":{"position":[[46,4],[173,4],[254,6]]},"9":{"position":[[659,4],[718,5],[724,5]]},"10":{"position":[[339,5]]},"11":{"position":[[141,4],[198,4]]},"13":{"position":[[360,5]]},"14":{"position":[[703,4],[847,4],[958,4],[1040,4],[1161,4]]},"15":{"position":[[348,4],[409,4],[463,4]]},"28":{"position":[[94,6],[724,5],[1229,5],[1760,5],[1872,6],[3029,5],[3620,6]]},"30":{"position":[[629,6],[1346,5],[2028,6],[2440,4],[3434,6],[3522,6],[4236,6],[4415,6],[5278,6],[5670,6],[5769,6],[6508,6],[6596,6],[7501,4],[7558,6],[9063,5],[9388,4],[9396,6]]},"40":{"position":[[76,5],[1106,4]]},"41":{"position":[[328,4]]},"64":{"position":[[356,6]]},"65":{"position":[[313,4],[791,5],[952,4],[1053,4],[1106,4],[1162,4],[1216,4]]},"66":{"position":[[490,6]]}},"keywords":{}}],["year_index",{"_index":580,"title":{},"content":{"13":{"position":[[1281,12],[1392,14]]},"14":{"position":[[2353,12],[2464,14]]},"15":{"position":[[2025,12],[2136,14]]}},"keywords":{}}],["year_mot",{"_index":520,"title":{},"content":{"11":{"position":[[441,11],[532,12]]},"12":{"position":[[399,11],[493,12]]}},"keywords":{}}],["year_pric",{"_index":565,"title":{},"content":{"13":{"position":[[640,12],[1150,13],[1187,12]]},"14":{"position":[[1481,12],[2184,13],[2232,12]]},"15":{"position":[[852,12],[1852,13],[1902,12]]}},"keywords":{}}],["year_prices[end",{"_index":576,"title":{},"content":{"13":{"position":[[959,16],[1036,17]]},"14":{"position":[[1977,16],[2070,17]]},"15":{"position":[[1645,16],[1738,17]]}},"keywords":{}}],["year_prices[i",{"_index":569,"title":{},"content":{"13":{"position":[[774,14]]},"14":{"position":[[1631,14]]},"15":{"position":[[1018,14]]}},"keywords":{}}],["yearli",{"_index":463,"title":{},"content":{"9":{"position":[[262,6],[612,6]]},"13":{"position":[[511,6]]},"14":{"position":[[564,6]]}},"keywords":{}}],["yeast",{"_index":4738,"title":{},"content":{"161":{"position":[[626,5]]}},"keywords":{}}],["yep",{"_index":2279,"title":{},"content":{"53":{"position":[[1570,3]]}},"keywords":{}}],["yerr=[min_err",{"_index":3007,"title":{},"content":{"90":{"position":[[1934,14],[3073,14]]}},"keywords":{}}],["yet?"",{"_index":3406,"title":{},"content":{"97":{"position":[[3867,10]]}},"keywords":{}}],["yew",{"_index":4160,"title":{},"content":{"125":{"position":[[8276,4],[8391,3],[9238,3]]}},"keywords":{}}],["yfinanc",{"_index":1750,"title":{},"content":{"39":{"position":[[2325,8]]}},"keywords":{}}],["yield",{"_index":3337,"title":{},"content":{"96":{"position":[[1231,6]]}},"keywords":{}}],["york",{"_index":1212,"title":{},"content":{"28":{"position":[[405,4]]},"93":{"position":[[3267,4]]}},"keywords":{}}],["you'd",{"_index":976,"title":{},"content":{"22":{"position":[[2725,5]]},"160":{"position":[[1549,5]]}},"keywords":{}}],["you'll",{"_index":1558,"title":{},"content":{"32":{"position":[[2133,6]]},"125":{"position":[[4513,6]]},"134":{"position":[[218,6],[350,6]]},"139":{"position":[[428,6]]},"155":{"position":[[182,6]]},"174":{"position":[[669,6]]},"184":{"position":[[960,6]]}},"keywords":{}}],["you'r",{"_index":1571,"title":{},"content":{"33":{"position":[[366,6]]},"59":{"position":[[189,6]]},"93":{"position":[[311,6]]},"97":{"position":[[139,6]]},"108":{"position":[[578,6],[794,6]]},"112":{"position":[[194,6],[402,6],[546,6]]},"118":{"position":[[108,6]]},"121":{"position":[[796,6],[1173,6]]},"125":{"position":[[4644,6],[7675,6],[9706,6]]},"139":{"position":[[395,6]]},"148":{"position":[[541,6]]},"150":{"position":[[711,6]]},"153":{"position":[[194,6]]},"157":{"position":[[534,6],[611,6]]},"176":{"position":[[1105,6]]},"184":{"position":[[778,6]]}},"keywords":{}}],["you'v",{"_index":1182,"title":{},"content":{"26":{"position":[[814,6]]},"39":{"position":[[188,6]]},"112":{"position":[[4,6]]},"125":{"position":[[3810,6]]},"134":{"position":[[10,6]]},"194":{"position":[[4,6]]}},"keywords":{}}],["young",{"_index":3930,"title":{"122":{"position":[[8,5]]}},"content":{},"keywords":{}}],["z",{"_index":2145,"title":{},"content":{"51":{"position":[[3307,2]]},"194":{"position":[[379,1]]}},"keywords":{}}],["zero",{"_index":2656,"title":{},"content":{"74":{"position":[[1596,4]]},"91":{"position":[[4120,4]]},"102":{"position":[[1054,5]]},"103":{"position":[[937,4]]},"155":{"position":[[1182,6]]},"164":{"position":[[1292,4]]},"165":{"position":[[435,4],[449,4]]}},"keywords":{}}],["zeros(m",{"_index":393,"title":{},"content":{"7":{"position":[[360,8]]}},"keywords":{}}],["zeros(num_simul",{"_index":587,"title":{},"content":{"13":{"position":[[1458,22]]},"14":{"position":[[2530,22]]},"15":{"position":[[2202,22]]}},"keywords":{}}],["zgc",{"_index":4909,"title":{},"content":{"172":{"position":[[576,4]]}},"keywords":{}}],["zip",{"_index":3674,"title":{},"content":{"108":{"position":[[693,3]]}},"keywords":{}}],["zombi",{"_index":4496,"title":{},"content":{"150":{"position":[[474,6]]}},"keywords":{}}]],"pipeline":["stemmer"]} \ No newline at end of file diff --git a/page/2/index.html b/page/2/index.html new file mode 100644 index 0000000..6ea911b --- /dev/null +++ b/page/2/index.html @@ -0,0 +1,44 @@ +Blog | The Old Speice Guy

Allocations in Rust: Foreword

· 4 min read
Bradlee Speice

There's an alchemy of distilling complex technical topics into articles and videos that change the +way programmers see the tools they interact with on a regular basis. I knew what a linker was, but +there's a staggering amount of complexity in between +the OS and main(). Rust programmers use the +Box type all the time, but there's a +rich history of the Rust language itself wrapped up in +how special it is.

+

In a similar vein, this series attempts to look at code and understand how memory is used; the +complex choreography of operating system, compiler, and program that frees you to focus on +functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the +cognitive burden associated with memory management, but we're going to step into its world for a +while.

+

Let's learn a bit about memory in Rust.

QADAPT - debug_assert! for allocations

· 5 min read
Bradlee Speice

I think it's part of the human condition to ignore perfectly good advice when it comes our way. A +bit over a month ago, I was dispensing sage wisdom for the ages:

+
+

I had a really great idea: build a custom allocator that allows you to track your own allocations. +I gave it a shot, but learned very quickly: never write your own allocator.

+

-- me

+
+

I proceeded to ignore it, because we never really learn from our mistakes.

More "what companies really mean"

· 2 min read
Bradlee Speice

I recently stumbled across a phenomenal small article entitled +What Startups Really Mean By "Why Should We Hire You?". +Having been interviewed by smaller companies (though not exactly startups), the questions and +subtexts are the same. There's often a question behind the question that you're actually trying to +answer, and I wish I spotted the nuance earlier in my career.

+

Let me also make note of one more question/euphemism I've come across:

A case study in heaptrack

· 5 min read
Bradlee Speice

I remember early in my career someone joking that:

+
+

Programmers have it too easy these days. They should learn to develop in low memory environments +and be more efficient.

+
+

...though it's not like the first code I wrote was for a +graphing calculator +packing a whole 24KB of RAM.

+

But the principle remains: be efficient with the resources you have, because +what Intel giveth, Microsoft taketh away.

Isomorphic desktop apps with Rust

· 10 min read
Bradlee Speice

I both despise Javascript and am stunned by its success doing some really cool things. It's +this duality that's +led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I +bootstrap a simple desktop application.

Primitives in Rust are weird (and cool)

· 7 min read
Bradlee Speice

I wrote a really small Rust program a while back because I was curious. I was 100% convinced it +couldn't possibly run:

+
fn main() {
println!("{}", 8.to_string())
}
+

And to my complete befuddlement, it compiled, ran, and produced a completely sensible output.

What I learned porting dateutil to Rust

· 7 min read
Bradlee Speice

I've mostly been a lurker in Rust for a while, making a couple small contributions here and there. +So launching dtparse feels like nice step towards becoming a +functioning member of society. But not too much, because then you know people start asking you to +pay bills, and ain't nobody got time for that.

Hello!

· One min read
Bradlee Speice

I'll do what I can to keep this short, there's plenty of other things we both should be doing right +now.

\ No newline at end of file diff --git a/page/3/index.html b/page/3/index.html new file mode 100644 index 0000000..dadc28f --- /dev/null +++ b/page/3/index.html @@ -0,0 +1,2 @@ +Blog | The Old Speice Guy

PCA audio compression

· 11 min read
Bradlee Speice

In which I apply Machine Learning techniques to Digital Signal Processing to astounding failure.

The unfair casino

· 15 min read
Bradlee Speice

Trying to figure out how exactly two dice are loaded in a cheating casino.

Tick tock...

· 11 min read
Bradlee Speice

If all we have is a finite number of heartbeats left, what about me?

Tweet like me

· 9 min read
Bradlee Speice

In which I try to create a robot that will tweet like I tweet.

Guaranteed money maker

· 8 min read
Bradlee Speice

Developing an investment strategy based on the Martingale betting strategy

+

If you can see into the future, that is.

Cloudy in Seattle

· 4 min read
Bradlee Speice

Building on prior analysis, is Seattle's reputation as a depressing city actually well-earned?

\ No newline at end of file diff --git a/page/4/index.html b/page/4/index.html new file mode 100644 index 0000000..cc7eaa9 --- /dev/null +++ b/page/4/index.html @@ -0,0 +1 @@ +Blog | The Old Speice Guy

Testing Cramer

· 9 min read
Bradlee Speice

Pursuant to attending a graduate school studying Financial Engineering, I've been a fan of the [Mad Money][1] TV show featuring the bombastic Jim Cramer. One of the things that he's said is that you shouldn't use the futures to predict where the stock market is going to go. But he says it often enough, I've begun to wonder - who is he trying to convince?

Autocallable Bonds

· 12 min read
Bradlee Speice

For a final project, my group was tasked with understanding three exotic derivatives: The Athena, Phoenix without memory, and Phoenix with memory autocallable products.

Welcome, and an algorithm

· 5 min read
Bradlee Speice

Hello! Glad to meet you. I'm currently a student at Columbia University studying Financial Engineering, and want to give an overview of the projects I'm working on!

\ No newline at end of file diff --git a/rss.css b/rss.css new file mode 100644 index 0000000..d2fc20b --- /dev/null +++ b/rss.css @@ -0,0 +1,75 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +main { + flex: 1 0 auto; + width: 100%; + margin: 2rem auto; + max-width: 800px; + /* stylelint-disable-next-line font-family-name-quotes */ + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell; +} + +.info { + display: block; + margin: 2rem 0; + padding: 1.6rem 2.4rem; + border: 1px solid dodgerblue; + border-left-width: 0.5rem; + border-radius: 0.4rem; + background-color: #edf5ff; +} + +a { + color: #005aff; + text-decoration: none; +} + +h1 { + text-wrap: balance; + font-size: 3.4rem; + font-weight: 800; + margin-bottom: 2rem; + display: flex; + align-items: center; +} + +h1 .rss-icon { + height: 3.2rem; + width: 3.2rem; + margin-right: 1rem; +} + +h2 { + font-size: 2.2rem; + font-weight: 700; + margin-bottom: 0.2rem; +} + +h3 { + font-size: 1.8rem; + font-weight: 700; + margin-bottom: 0.1rem; +} + +.blog-description { + font-size: 1.4rem; + margin-bottom: 0.6rem; +} + +.blog-post-date { + font-size: 1rem; + line-height: 1.4rem; + font-style: italic; + color: #797b7e; +} + +.blog-post-description { + font-size: 1rem; + line-height: 1.4rem; + color: #434349; +} diff --git a/rss.xml b/rss.xml new file mode 100644 index 0000000..9a1bf60 --- /dev/null +++ b/rss.xml @@ -0,0 +1,2187 @@ + + + + The Old Speice Guy Blog + https://speice.io/ + The Old Speice Guy Blog + Sun, 20 Nov 2022 12:00:00 GMT + https://validator.w3.org/feed/docs/rss2.html + https://github.com/jpmonette/feed + en + + <![CDATA[The webpack industrial complex]]> + https://speice.io/2011/11/webpack-industrial-complex + https://speice.io/2011/11/webpack-industrial-complex + Sun, 20 Nov 2022 12:00:00 GMT + + This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).

+

The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.

+

Starting strong

+

The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser."

+

Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an onEvent handler and a function easy.

+

Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical."

+

Continuing on

+

Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?

+

The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API was missing. After searching out Github issues and (unsuccessfully) tweaking the .tsconfig settings, I settled on installing a package and moving on.

+

The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use new URL(<local path>, import.meta.url) and it worked! Well, kind of:

+

Browser error

+

That file has the audio processor code, so why does it get served with Content-Type: video/mp2t?

+

Floundering about

+

Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to just use JavaScript and stuck by the original TypeScript requirement.

+

I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package.

+

I tried three different CRA tools - react-app-rewired, craco, customize-react-app - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well.

+

I tried changing the webpack configuration: using new loaders, setting asset rules, even changing how webpack detects worker resources. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up.

+

I tried so many application frameworks. Next.js looked like a good candidate, but added its own bespoke webpack complexity to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work.

+

Learning and reflecting

+

I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned.

+

For myself:

+
    +
  • I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work
  • +
  • I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts
  • +
+

For the tools:

+
    +
  • Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity
  • +
  • Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaks
  • +
  • There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it
  • +
+

In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down.

]]>
+
+ + <![CDATA[Release the GIL]]> + https://speice.io/2019/12/release-the-gil + https://speice.io/2019/12/release-the-gil + Sat, 14 Dec 2019 12:00:00 GMT + + Complaining about the Global Interpreter Lock +(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision +made before multi-core CPU's were widely available, but the fact that it's still around indicates +that it generally works Good +Enough. Besides, there are simple and effective +workarounds; it's not hard to start a +new process and use message passing to +synchronize code running in parallel.

+

Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of +asynchronicity and M:N threading, Python seems lacking. The ideal scenario is to take advantage of +both Python's productivity and the modern CPU's parallel capabilities.

+

Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes +Python a nice language to start with. Bear in mind: these are just the tools, no claim is made about +whether it's a good idea to use them. Very often, unlocking the GIL is an +XY problem; you want application performance, and the +GIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at +the expense of project complexity; messing with the GIL is ultimately messing with Python's memory +model.

+
%load_ext Cython
from numba import jit

N = 1_000_000_000
+

Cython

+

Put simply, Cython is a programming language that looks a lot like Python, +gets transpiled to C/C++, and integrates +well with the CPython API. It's great for building Python +wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And +when it comes to managing the GIL, there are two special features:

+
    +
  • The nogil +function annotation +asserts that a Cython function is safe to use without the GIL, and compilation will fail if it +interacts with Python in an unsafe manner
  • +
  • The with nogil +context manager +explicitly unlocks the CPython GIL while active
  • +
+

Whenever Cython code runs inside a with nogil block on a separate thread, the Python interpreter +is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that +demonstrates this principle in action:

+
%%cython

# Annotating a function with `nogil` indicates only that it is safe
# to call in a `with nogil` block. It *does not* release the GIL.
cdef unsigned long fibonacci(unsigned long n) nogil:
if n <= 1:
return n

cdef unsigned long a = 0, b = 1, c = 0

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


def cython_nogil(unsigned long n):
# Explicitly release the GIL while running `fibonacci`
with nogil:
value = fibonacci(n)

return value


def cython_gil(unsigned long n):
# Because the GIL is not explicitly released, it implicitly
# remains acquired when running the `fibonacci` function
return fibonacci(n)
+

First, let's time how long it takes Cython to calculate the billionth Fibonacci number:

+
%%time
_ = cython_gil(N);
+
+

CPU times: user 365 ms, sys: 0 ns, total: 365 ms +Wall time: 372 ms

+
+
%%time
_ = cython_nogil(N);
+
+

CPU times: user 381 ms, sys: 0 ns, total: 381 ms +Wall time: 388 ms

+
+

Both versions (with and without GIL) take effectively the same amount of time to run. Even when +running this calculation in parallel on separate threads, it is expected that the run time will +double because only one thread can be active at a time:

+
%%time
from threading import Thread

# Create the two threads to run on
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
# Start the threads
t1.start(); t2.start()
# Wait for the threads to finish
t1.join(); t2.join()
+
+

CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms +Wall time: 645 ms

+
+

However, if the first thread releases the GIL, the second thread is free to acquire it and run in +parallel:

+
%%time

t1 = Thread(target=cython_nogil, args=[N])
t2 = Thread(target=cython_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 717 ms, sys: 372 µs, total: 718 ms +Wall time: 358 ms

+
+

Because user time represents the sum of processing time on all threads, it doesn't change much. +The "wall time" has been cut roughly in half +because each function is running simultaneously.

+

Keep in mind that the order in which threads are started makes a difference!

+
%%time

# Note that the GIL-locked version is started first
t1 = Thread(target=cython_gil, args=[N])
t2 = Thread(target=cython_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 667 ms, sys: 0 ns, total: 667 ms +Wall time: 672 ms

+
+

Even though the second thread releases the GIL while running, it can't start until the first has +completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads.

+

Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the +interpreter, not just the thread attempting the unlock:

+
%%cython

cdef int cython_recurse(int n) nogil:
if n <= 0:
return 0

with nogil:
return cython_recurse(n - 1)

cython_recurse(2)
+
+

Fatal Python error: PyEval_SaveThread: NULL tstate

Thread 0x00007f499effd700 (most recent call first): +File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run +File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner +File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap

+
+

In practice, avoiding this issue is simple. First, nogil functions probably shouldn't contain +with nogil blocks. Second, Cython can +conditionally acquire/release +the GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for +external C code +contains more detail on how to safely manage the GIL.

+

To conclude: use Cython's nogil annotation to assert that functions are safe for calling when the +GIL is unlocked, and with nogil to actually unlock the GIL and run those functions.

+

Numba

+

Like Cython, Numba is a "compiled Python." Where Cython works by +compiling a Python-like language to C/C++, Numba compiles Python bytecode directly to machine code +at runtime. Behavior is controlled with a special @jit decorator; calling a decorated function +first compiles it to machine code before running. Calling the function a second time re-uses that +machine code unless the argument types have changed.

+

Numba works best when a nopython=True argument is added to the @jit decorator; functions +compiled in nopython mode +avoid the CPython API and have performance comparable to C. Further, adding nogil=True to the +@jit decorator unlocks the GIL while that function is running. Note that nogil and nopython +are separate arguments; while it is necessary for code to be compiled in nopython mode in order to +release the lock, the GIL will remain locked if nogil=False (the default).

+

Let's repeat the same experiment, this time using Numba instead of Cython:

+
# The `int` type annotation is only for humans and is ignored
# by Numba.
@jit(nopython=True, nogil=True)
def numba_nogil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Run using `nopython` mode to receive a performance boost,
# but GIL remains locked due to `nogil=False` by default.
@jit(nopython=True)
def numba_gil(n: int) -> int:
if n <= 1:
return n

a = 0
b = 1

c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b

return c


# Call each function once to force compilation; we don't want
# the timing statistics to include how long it takes to compile.
numba_nogil(N)
numba_gil(N);
+

We'll perform the same tests as above; first, figure out how long it takes the function to run:

+
%%time
_ = numba_gil(N)
+
+

CPU times: user 253 ms, sys: 258 µs, total: 253 ms +Wall time: 251 ms

+
+

Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be +effectively identical after compilation. +

When running two GIL-locked threads, the result (as expected) takes around twice as long to compute:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms +Wall time: 541 ms

+
+

But if the GIL-unlocking thread starts first, both threads run in parallel:

+
%%time
t1 = Thread(target=numba_nogil, args=[N])
t2 = Thread(target=numba_gil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms +Wall time: 279 ms

+
+

Just like Cython, starting the GIL-locked thread first leads to poor performance:

+
%%time
t1 = Thread(target=numba_gil, args=[N])
t2 = Thread(target=numba_nogil, args=[N])
t1.start(); t2.start()
t1.join(); t2.join()
+
+

CPU times: user 524 ms, sys: 0 ns, total: 524 ms +Wall time: 522 ms

+
+

Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; +recursively calling @jit(nogil=True) functions is perfectly safe:

+
from numba import jit

@jit(nopython=True, nogil=True)
def numba_recurse(n: int) -> int:
if n <= 0:
return 0

return numba_recurse(n - 1)

numba_recurse(2);
+

Conclusion

+

Before finishing, it's important to address pain points that will show up if these techniques are +used in a more realistic project:

+

First, code running in a GIL-free context will likely also need non-trivial data structures; +GIL-free functions aren't useful if they're constantly interacting with Python objects whose access +requires the GIL. Cython provides +extension types and Numba +provides a @jitclass decorator to +address this need.

+

Second, building and distributing applications that make use of Cython/Numba can be complicated. +Cython packages require running the compiler, (potentially) linking/packaging external dependencies, +and distributing a binary wheel. Numba is generally simpler because the code being distributed is +pure Python, but can be tricky since errors aren't detected until runtime.

+

Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba +provide tools to directly manage the GIL when appropriate. This enables true parallelism (not just +concurrency) that is impossible in vanilla Python.

]]>
+
+ + <![CDATA[Binary format shootout]]> + https://speice.io/2019/09/binary-format-shootout + https://speice.io/2019/09/binary-format-shootout + Sat, 28 Sep 2019 12:00:00 GMT + + I've found that in many personal projects, +analysis paralysis is particularly deadly. +Making good decisions in the beginning avoids pain and suffering later; if extra research prevents +future problems, I'm happy to continue procrastinating researching indefinitely.

+

So let's say you're in need of a binary serialization format. Data will be going over the network, +not just in memory, so having a schema document and code generation is a must. Performance is +crucial, so formats that support zero-copy de/serialization are given priority. And the more +languages supported, the better; I use Rust, but can't predict what other languages this could +interact with.

+

Given these requirements, the candidates I could find were:

+
    +
  1. Cap'n Proto has been around the longest, and is the most established
  2. +
  3. Flatbuffers is the newest, and claims to have a simpler +encoding
  4. +
  5. Simple Binary Encoding has the simplest +encoding, but the Rust implementation is unmaintained
  6. +
+

Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably +fast, and polyglot support. But how do you actually pick one? It's impossible to know what issues +will follow that choice, so I tend to avoid commitment until the last possible moment.

+

Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a +small proof-of-concept system in each format and pit them against each other. All code can be found +in the repository for this post.

+

We'll discuss more in detail, but a quick preview of the results:

+
    +
  • Cap'n Proto: Theoretically performs incredibly well, the implementation had issues
  • +
  • Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises
  • +
  • SBE: Best median and worst-case performance, but the message structure has a limited feature set
  • +
+

Prologue: Binary Parsing with Nom

+

Our benchmark system will be a simple data processor; given depth-of-book market data from +IEX, serialize each message into the schema +format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. +This test isn't complex, but is representative of the project I need a binary format for.

+

But before we make it to that point, we have to actually read in the market data. To do so, I'm +using a library called nom. Version 5.0 was recently released and +brought some big changes, so this was an opportunity to build a non-trivial program and get +familiar.

+

If you don't already know about nom, it's a "parser generator". By combining different smaller +parsers, you can assemble a parser to handle complex structures without writing tedious code by +hand. For example, when parsing +PCAP files:

+
   0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+---------------------------------------------------------------+
0 | Block Type = 0x00000006 |
+---------------------------------------------------------------+
4 | Block Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Interface ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 | Timestamp (High) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 | Timestamp (Low) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 | Captured Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 | Packet Len |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Packet Data |
| ... |
+

...you can build a parser in nom that looks like +this:

+
const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00];
pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> {
let (
remaining,
(
block_type,
block_len,
interface_id,
timestamp_high,
timestamp_low,
captured_len,
packet_len,
),
) = tuple((
tag(ENHANCED_PACKET),
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
le_u32,
))(input)?;

let (remaining, packet_data) = take(captured_len)(remaining)?;
Ok((remaining, packet_data))
}
+

While this example isn't too interesting, more complex formats (like IEX market data) are where +nom really shines.

+

Ultimately, because the nom code in this shootout was the same for all formats, we're not too +interested in its performance. Still, it's worth mentioning that building the market data parser was +actually fun; I didn't have to write tons of boring code by hand.

+

Cap'n Proto

+

Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried +because of how long it has supported Rust (thanks to dwrensha for +maintaining the Rust port since +2014!). However, I had a ton +of performance concerns once I started using it.

+

To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the +heap to hold the message content, but because builders +can't be re-used, we have to allocate a +new buffer for every single message. I was able to work around this with a +special builder +that could re-use the buffer, but it required reading through Cap'n Proto's +benchmarks +to find an example, and used +std::mem::transmute to bypass Rust's borrow +checker.

+

The process of reading messages was better, but still had issues. Cap'n Proto has two message +encodings: a "packed" representation, and an +"unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into +before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't +able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n +Proto shines; its main selling point is that there's no decoding step. +However, accomplishing zero-copy deserialization required code in the private API +(since fixed), and we allocate a vector on +every read for the segment table.

+

In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too +many issues for me to feel comfortable using it long-term.

+

Flatbuffers

+

This is the new kid on the block. After a +first attempt didn't pan out, official support +was recently launched. Flatbuffers intends to +address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The +difference is that Flatbuffers claims to have a simpler wire format and +more flexibility.

+

On the whole, I enjoyed using Flatbuffers; the tooling is +nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, +there were still some issues.

+

First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats +like the following:

+
table Message {
symbol: string;
}
table MultiMessage {
messages:[Message];
}
+

We want to create a MultiMessage which contains a vector of Message, and each Message itself +contains a vector (the string type). I was able to work around this by +caching Message elements +in a SmallVec before building the final MultiMessage, but it was a painful process that I +believe contributed to poor serialization performance.

+

Second, streaming support in Flatbuffers seems to be something of an +afterthought. Where Cap'n Proto in Rust handles +reading messages from a stream as part of the API, Flatbuffers just sticks a u32 at the front of +each message to indicate the size. Not specifically a problem, but calculating message size without +that tag is nigh on impossible.

+

Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform +well.

+

Simple Binary Encoding

+

Support for SBE was added by the author of one of my favorite +Rust blog posts. +I've talked previously about how important +variance is in high-performance systems, so it was encouraging to read about a format that +directly addressed my +concerns. SBE has by far the simplest binary format, but it does make some tradeoffs.

+

Both Cap'n Proto and Flatbuffers use message offsets +to handle variable-length data, unions, and various +other features. In contrast, messages in SBE are essentially +just structs; +variable-length data is supported, but there's no union type.

+

As mentioned in the beginning, the Rust port of SBE works well, but is +essentially unmaintained. +However, if you don't need union types, and can accept that schemas are XML documents, it's still +worth using. SBE's implementation had the best streaming support of all formats I tested, and +doesn't trigger allocation during de/serialization.

+

Results

+

After building a test harness +for +each +format, it was +time to actually take them for a spin. I used +this script to run +the benchmarks, and the raw results are +here. All data reported +below is the average of 10 runs on a single day of IEX data. Results were validated to make sure +that each format parsed the data correctly.

+

Serialization

+

This test measures, on a +per-message basis, +how long it takes to serialize the IEX message into the desired format and write to a pre-allocated +buffer.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed413ns1751ns2943ns14.80s
Cap'n Proto Unpacked273ns1828ns2836ns10.65s
Flatbuffers355ns2185ns3497ns14.31s
SBE91ns1535ns2423ns3.91s
+

Deserialization

+

This test measures, on a +per-message basis, +how long it takes to read the previously-serialized message and perform some basic aggregation. The +aggregation code is the same for each format, so any performance differences are due solely to the +format implementation.

+
SchemaMedian99th Pctl99.9th PctlTotal
Cap'n Proto Packed539ns1216ns2599ns18.92s
Cap'n Proto Unpacked366ns737ns1583ns12.32s
Flatbuffers173ns421ns1007ns6.00s
SBE116ns286ns659ns4.05s
+

Conclusion

+

Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" +type isn't important to me, I can be confident that SBE best addresses my needs.

+

While SBE was the fastest in terms of both median and worst-case performance, its worst case +performance was proportionately far higher than any other format. It seems to be that +de/serialization time scales with message size, but I'll need to do some more research to understand +what exactly is going on.

]]>
+
+ + <![CDATA[On building high performance systems]]> + https://speice.io/2019/06/high-performance-systems + https://speice.io/2019/06/high-performance-systems + Mon, 01 Jul 2019 12:00:00 GMT + + Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is +made up of people who have access to secret techniques mortal developers could only dream of. There +had to be some secret art that could only be learned if one had an appropriately tragic backstory.

+

Kung Fu fight

+
+

How I assumed HFT people learn their secret techniques

+
+

How else do you explain people working on systems that complete the round trip of market data in to +orders out (a.k.a. tick-to-trade) consistently within +750-800 nanoseconds? In roughly the time it takes a +computer to access +main memory 8 times, +trading systems are capable of reading the market data packets, deciding what orders to send, doing +risk checks, creating new packets for exchange-specific protocols, and putting those packets on the +wire.

+

Having now worked in the trading industry, I can confirm the developers aren't super-human; I've +made some simple mistakes at the very least. Instead, what shows up in public discussions is that +philosophy, not technique, separates high-performance systems from everything else. +Performance-critical systems don't rely on "this one cool C++ optimization trick" to make code fast +(though micro-optimizations have their place); there's a lot more to worry about than just the code +written for the project.

+

The framework I'd propose is this: If you want to build high-performance systems, focus first on +reducing performance variance (reducing the gap between the fastest and slowest runs of the same +code), and only look at average latency once variance is at an acceptable level.

+

Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20 +seconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes +a full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a +week is the same in each situation, but you're painfully aware of that minute when it happens. When +it comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds +doesn't mean much if there's a 100ms difference between your fastest and slowest runs. When +performance matters, you need to respond quickly every time, not just in aggregate. +High-performance systems should first optimize for time variance. Once you're consistent at the time +scale you care about, then focus on improving average time.

+

This focus on variance shows up all the time in industry too (emphasis added in all quotes below):

+
    +
  • +

    In marketing materials for +NASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability +is highlighted in addition to instantaneous metrics:

    +
    +

    Able to consistently sustain an order rate of over 100,000 orders per second at sub-40 +microsecond average latency

    +
    +
  • +
  • +

    The Aeron message bus has this to say about performance:

    +
    +

    Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and +most predictable latency possible of any messaging system

    +
    +
  • +
  • +

    The company PolySync, which is working on autonomous vehicles, +mentions why they picked their +specific messaging format:

    +
    +

    In general, high performance is almost always desirable for serialization. But in the world of +autonomous vehicles, steady timing performance is even more important than peak throughput. +This is because safe operation is sensitive to timing outliers. Nobody wants the system that +decides when to slam on the brakes to occasionally take 100 times longer than usual to encode +its commands.

    +
    +
  • +
  • +

    Solarflare, which makes highly-specialized network hardware, points out +variance (jitter) as a big concern for +electronic trading:

    +
    +

    The high stakes world of electronic trading, investment banks, market makers, hedge funds and +exchanges demand the lowest possible latency and jitter while utilizing the highest +bandwidth and return on their investment.

    +
    +
  • +
+

And to further clarify: we're not discussing total run-time, but variance of total run-time. There +are situations where it's not reasonably possible to make things faster, and you'd much rather be +consistent. For example, trading firms use +wireless networks because +the speed of light through air is faster than through fiber-optic cables. There's still at absolute +minimum a ~33.76 millisecond delay required to send data between, +say, +Chicago and Tokyo. +If a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a +trade occurs, there's a physical limit to how long that will take. In this situation, the focus is +on keeping variance of additional processing to a minimum, since speed of light is the limiting +factor.

+

So how does one go about looking for and eliminating performance variance? To tell the truth, I +don't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep +understanding of the entire technology stack, and (B) actually measuring system performance (though +(C) watching a lot of CppCon videos for +inspiration never hurt). Even then, every project cares about performance to a different degree; you +may need to build an entire +replica production system to +accurately benchmark at nanosecond precision, or you may be content to simply +avoid garbage collection in +your Java code.

+

Even though everyone has different needs, there are still common things to look for when trying to +isolate and eliminate variance. In no particular order, these are my focus areas when thinking about +high-performance systems:

+

Update 2019-09-21: Added notes on isolcpus and systemd affinity.

+

Language-specific

+

Garbage Collection: How often does garbage collection happen? When is it triggered? What are the +impacts?

+
    +
  • In Python, individual objects are collected +if the reference count reaches 0, and each generation is collected if +num_alloc - num_dealloc > gc_threshold whenever an allocation happens. The GIL is acquired for +the duration of generational collection.
  • +
  • Java has +many +different +collection +algorithms +to choose from, each with different characteristics. The default algorithms (Parallel GC in Java +8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms +(ZGC and +Shenandoah) are designed to keep "stop the +world" to a minimum by doing collection work in parallel.
  • +
+

Allocation: Every language has a different way of interacting with "heap" memory, but the +principle is the same: running the allocator to allocate/deallocate memory takes time that can often +be put to better use. Understanding when your language interacts with the allocator is crucial, and +not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java +does (meaning potential GC pauses). Take time to understand heap behavior (I made a +a guide for Rust), and look into alternative +allocators (jemalloc, +tcmalloc) that might run faster than the +operating system default.

+

Data Layout: How your data is arranged in memory matters; +data-oriented design and +cache locality can have huge +impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have +guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't +make. Cachegrind and kernel +perf counters are both great for understanding +how performance relates to memory layout.

+

Just-In-Time Compilation: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are +great because they optimize your program for how it's actually being used, rather than how a +compiler expects it to be used. However, there's a variance problem if the program stops executing +while waiting for translation from VM bytecode to native code. As a remedy, many languages support +ahead-of-time compilation in addition to the JIT versions +(CoreRT in C# and GraalVM in Java). +On the other hand, LLVM supports +Profile Guided Optimization, +which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing +apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT +compiler kicked in.

+

Programming Tricks: These won't make or break performance, but can be useful in specific +circumstances. For example, C++ can use +templates instead of branches +in critical sections.

+

Kernel

+

Code you wrote is almost certainly not the only code running on your hardware. There are many ways +the operating system interacts with your program, from interrupts to system calls, that are +important to watch for. These are written from a Linux perspective, but Windows does typically have +equivalent functionality.

+

Scheduling: The kernel is normally free to schedule any process on any core, so it's important +to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, +limit the CPU cores that non-critical processes are allowed to run on by excluding cores from +scheduling +(isolcpus +kernel command-line option), or by setting the init process CPU affinity +(systemd example). Second, set critical processes +to run on the isolated cores by setting the +processor affinity using +taskset. Finally, use +NO_HZ or +chrt to disable scheduling interrupts. Turning off +hyper-threading is also likely beneficial.

+

System calls: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long +the I/O operation takes, these all trigger expensive +system calls (syscalls). To handle these, the CPU must +context switch to the kernel, let the kernel +operation complete, then context switch back to your program. We'd rather keep these +to a minimum (see +timestamp 18:20). Strace is your friend for understanding when +and where syscalls happen.

+

Signal Handling: Far less likely to be an issue, but signals do trigger a context switch if your +code has a handler registered. This will be highly dependent on the application, but you can +block signals +if it's an issue.

+

Interrupts: System interrupts are how devices connected to your computer notify the CPU that +something has happened. The CPU will then choose a processor core to pause and context switch to the +OS to handle the interrupt. Make sure that +SMP affinity is +set so that interrupts are handled on a CPU core not running the program you care about.

+

NUMA: While NUMA is good at making +multi-cell systems transparent, there are variance implications; if the kernel moves a process +across nodes, future memory accesses must wait for the controller on the original node. Use +numactl to handle memory-/cpu-cell pinning so this doesn't +happen.

+

Hardware

+

CPU Pipelining/Speculation: Speculative execution in modern processors gave us vulnerabilities +like Spectre, but it also gave us performance improvements like +branch prediction. And if the CPU mis-speculates +your code, there's variance associated with rewind and replay. While the compiler knows a lot about +how your CPU pipelines instructions, code can be +structured to help the branch +predictor.

+

Paging: For most systems, virtual memory is incredible. Applications live in their own worlds, +and the CPU/MMU figures out the details. +However, there's a variance penalty associated with memory paging and caching; if you access more +memory pages than the TLB can store, +you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an +issue, but using huge pages can +reduce TLB burdens. Alternately, running applications in a hypervisor like +Jailhouse allows one to skip virtual memory entirely, but +this is probably more work than the benefits are worth.

+

Network Interfaces: When more than one computer is involved, variance can go up dramatically. +Tuning kernel +network parameters may be +helpful, but modern systems more frequently opt to skip the kernel altogether with a technique +called kernel bypass. This typically requires +specialized hardware and drivers, but even industries like +telecom are +finding the benefits.

+

Networks

+

Routing: There's a reason financial firms are willing to pay +millions of euros +for rights to a small plot of land - having a straight-line connection from point A to point B means +the path their data takes is the shortest possible. In contrast, there are currently 6 computers in +between me and Google, but that may change at any moment if my ISP realizes a +more efficient route is available. Whether +it's using +research-quality equipment +for shortwave radio, or just making sure there's no data inadvertently going between data centers, +routing matters.

+

Protocol: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, +and congestion control all built in. But these attributes make the most sense when networking +infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the +setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may +make sense in these contexts as it avoids the chatter needed to track connection state, and +gap-fill +strategies +can handle the rest.

+

Switching: Many routers/switches handle packets using "store-and-forward" behavior: wait for the +whole packet, validate checksums, and then send to the next device. In variance terms, the time +needed to move data between two nodes is proportional to the size of that data; the switch must +"store" all data before it can calculate checksums and "forward" to the next node. With +"cut-through" +designs, switches will begin forwarding data as soon as they know where the destination is, +checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter +the size.

+

Final Thoughts

+

High-performance systems, regardless of industry, are not magical. They do require extreme precision +and attention to detail, but they're designed, built, and operated by regular people, using a lot of +tools that are publicly available. Interested in seeing how context switching affects performance of +your benchmarks? taskset should be installed in all modern Linux distributions, and can be used to +make sure the OS never migrates your process. Curious how often garbage collection triggers during a +crucial operation? Your language of choice will typically expose details of its operations +(Python, +Java). +Want to know how hard your program is stressing the TLB? Use perf record and look for +dtlb_load_misses.miss_causes_a_walk.

+

Two final guiding questions, then: first, before attempting to apply some of the technology above to +your own systems, can you first identify +where/when you care about "high-performance"? As an +example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable +effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are +they being designed in a way that's actually helpful? Tools like +Criterion (also in +Rust) and Google's +Benchmark output not only average run time, but variance as +well; your benchmarking environment is subject to the same concerns your production environment is.

+

Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. +Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate +it; once that's at an acceptable level, then optimize for speed.

]]>
+
+ + <![CDATA[Making bread]]> + https://speice.io/2019/05/making-bread + https://speice.io/2019/05/making-bread + Fri, 03 May 2019 12:00:00 GMT + + Having recently started my "gardening leave" between positions, I have some more personal time +available. I'm planning to stay productive, contributing to some open-source projects, but it also +occurred to me that despite talking about bread pics, this +blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites +and Bytes"?

+

Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on +some lighter material. I recently learned two critically important lessons: first, the temperature +of the dough when you put the yeast in makes a huge difference.

+

Previously, when I wasn't paying attention to dough temperature:

+

Whole weat dough

+

Compared with what happens when I put the dough in the microwave for a defrost cycle because the +water I used wasn't warm enough:

+

White dough

+

I mean, just look at the bubbles!

+

White dough with bubbles

+

After shaping the dough, I've got two loaves ready:

+

Shaped loaves

+

Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from +drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the +bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot +to add the water and learned my second lesson: never add room-temperature water to a glass dish +that's currently at 500 degrees.

+

Shattered glass dish

+

Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected +to be doing during my garden leave.

+

In the end, the bread crust wasn't great, but the bread itself turned out pretty alright:

+

Baked bread

+

I've been writing a lot more during this break, so I'm looking forward to sharing that in the +future. In the mean-time, I'm planning on making a sandwich.

]]>
+
+ + <![CDATA[Allocations in Rust: Summary]]> + https://speice.io/2019/02/summary + https://speice.io/2019/02/summary + Sat, 09 Feb 2019 12:00:00 GMT + + While there's a lot of interesting detail captured in this series, it's often helpful to have a +document that answers some "yes/no" questions. You may not care about what an Iterator looks like +in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust +will prioritize the fastest behavior it can, here are the rules for each memory type:

+

Global Allocation:

+
    +
  • const is a fixed value; the compiler is allowed to copy it wherever useful.
  • +
  • static is a fixed reference; the compiler will guarantee it is unique.
  • +
+

Stack Allocation:

+
    +
  • Everything not using a smart pointer will be allocated on the stack.
  • +
  • Structs, enums, iterators, arrays, and closures are all stack allocated.
  • +
  • Cell types (RefCell) behave like smart pointers, but are stack-allocated.
  • +
  • Inlining (#[inline]) will not affect allocation behavior for better or worse.
  • +
  • Types that are marked Copy are guaranteed to have their contents stack-allocated.
  • +
+

Heap Allocation:

+
    +
  • Smart pointers (Box, Rc, Mutex, etc.) allocate their contents in heap memory.
  • +
  • Collections (HashMap, Vec, String, etc.) allocate their contents in heap memory.
  • +
  • Some smart pointers in the standard library have counterparts in other crates that don't need heap +memory. If possible, use those.
  • +
+

Container Sizes in Rust

+

-- Raph Levien

]]>
+
+ + <![CDATA[Allocations in Rust: Compiler optimizations]]> + https://speice.io/2019/02/08/compiler-optimizations + https://speice.io/2019/02/08/compiler-optimizations + Fri, 08 Feb 2019 12:00:00 GMT + + Up to this point, we've been discussing memory usage in the Rust language by focusing on simple +rules that are mostly right for small chunks of code. We've spent time showing how those rules work +themselves out in practice, and become familiar with reading the assembly code needed to see each +memory type (global, stack, heap) in action.

+

Throughout the series so far, we've put a handicap on the code. In the name of consistent and +understandable results, we've asked the compiler to pretty please leave the training wheels on. Now +is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the +Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them +do their job.

+

Similar to +"What Has My Compiler Done For Me Lately?", we're +focusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll +still be looking at assembly code to understand what's going on, but it's important to mention +again: please use automated tools like alloc-counter to +double-check memory behavior if it's something you care about. It's far too easy to mis-read +assembly in large code sections, you should always verify behavior if you care about memory usage.

+

The guiding principal as we move forward is this: optimizing compilers won't produce worse programs +than we started with. There won't be any situations where stack allocations get moved to heap +allocations. There will, however, be an opera of optimization.

+

Update 2019-02-10: When debugging a +related issue, it was discovered that the +original code worked because LLVM optimized out the entire function, rather than just the allocation +segments. The code has been updated with proper use of +read_volatile, and a previous section +on vector capacity has been removed.

+

The Case of the Disappearing Box

+

Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently +short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the +stack instead! The way this interacts with #[inline] attributes is a bit opaque, but the important +part is that LLVM can sometimes do better than the baseline Rust language:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

pub fn cmp(x: u32) {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// The compiler is able to see through the constant `Box`
// and directly compare `x` to 24 - assembly line 73
let y = Box::new(24);
let equals = x == *y;

// This call to drop is eliminated
drop(y);

// Need to mark the comparison result as volatile so that
// LLVM doesn't strip out all the code. If `y` is marked
// volatile instead, allocation will be forced.
unsafe { std::ptr::read_volatile(&equals) };

// Turn off panicking, as there are some deallocations
// when we exit main.
DO_PANIC.store(false, Ordering::SeqCst);
}

fn main() {
cmp(12)
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- Compiler Explorer

+

-- Rust Playground

+

Dr. Array or: how I learned to love the optimizer

+

Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping +out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if +you're not careful, they can make your benchmarks look +impossibly good. In Rust, the +black_box function (implemented in both +libtest and +criterion) will tell the compiler +to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up +running programs that previously caused errors:

+
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

pub fn main() {
// Normally this blows up because we can't reserve size on stack
// for the `EightM` struct. But because the compiler notices we
// never do anything with `_x`, it optimizes out the stack storage
// and the program completes successfully.
let _x = EightM::default();
}
+

-- Compiler Explorer

+

-- Rust Playground

]]>
+
+ + <![CDATA[Allocations in Rust: Dynamic memory]]> + https://speice.io/2019/02/a-heaping-helping + https://speice.io/2019/02/a-heaping-helping + Thu, 07 Feb 2019 12:00:00 GMT + + Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and +some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how +the language uses dynamic memory (also referred to as the heap) is a system called ownership. +And as the docs mention, ownership +is Rust's most unique feature.

+

The heap is used in two situations; when the compiler is unable to predict either the total size of +memory needed, or how long the memory is needed for, it allocates space in the heap.

+

This happens +pretty frequently; if you want to download the Google home page, you won't know how large it is +until your program runs. And when you're finished with Google, we deallocate the memory so it can be +used to store other webpages. If you're interested in a slightly longer explanation of the heap, +check out +The Stack and the Heap +in Rust's documentation.

+

We won't go into detail on how the heap is managed; the +ownership documentation does a +phenomenal job explaining both the "why" and "how" of memory management. Instead, we're going to +focus on understanding "when" heap allocations occur in Rust.

+

To start off, take a guess for how many allocations happen in the program below:

+
fn main() {}
+

It's obviously a trick question; while no heap allocations occur as a result of that code, the setup +needed to call main does allocate on the heap. Here's a way to show it:

+
#![feature(integer_atomics)]
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicU64, Ordering};

static ALLOCATION_COUNT: AtomicU64 = AtomicU64::new(0);

struct CountingAllocator;

unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATION_COUNT.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout);
}
}

#[global_allocator]
static A: CountingAllocator = CountingAllocator;

fn main() {
let x = ALLOCATION_COUNT.fetch_add(0, Ordering::SeqCst);
println!("There were {} allocations before calling main!", x);
}
+

-- +Rust Playground

+

As of the time of writing, there are five allocations that happen before main is ever called.

+

But when we want to understand more practically where heap allocation happens, we'll follow this +guide:

+
    +
  • Smart pointers hold their contents in the heap
  • +
  • Collections are smart pointers for many objects at a time, and reallocate when they need to grow
  • +
+

Finally, there are two "addendum" issues that are important to address when discussing Rust and the +heap:

+
    +
  • Non-heap alternatives to many standard library types are available.
  • +
  • Special allocators to track memory behavior should be used to benchmark code.
  • +
+

Smart pointers

+

The first thing to note are the "smart pointer" types. When you have data that must outlive the +scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these +types.

+

The term smart pointer comes from C++, and while it's +closely linked to a general design pattern of +"Resource Acquisition Is Initialization", we'll +use it here specifically to describe objects that are responsible for managing ownership of data +allocated on the heap. The smart pointers available in the alloc crate should look mostly +familiar:

+ +

The standard library also defines some smart pointers to manage +heap objects, though more than can be covered here. Some examples are:

+ +

Finally, there is one "gotcha": cell types +(like RefCell) look and behave +similarly, but don't involve heap allocation. The +core::cell docs have more information.

+

When a smart pointer is created, the data it is given is placed in heap memory and the location of +that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to +deallocate that memory (when a Box has +gone out of scope or a reference count +goes to zero), the heap space is reclaimed. We can +prove these types use heap memory by looking at code:

+
use std::rc::Rc;
use std::sync::Arc;
use std::borrow::Cow;

pub fn my_box() {
// Drop at assembly line 1640
Box::new(0);
}

pub fn my_rc() {
// Drop at assembly line 1650
Rc::new(0);
}

pub fn my_arc() {
// Drop at assembly line 1660
Arc::new(0);
}

pub fn my_cow() {
// Drop at assembly line 1672
Cow::from("drop");
}
+

-- Compiler Explorer

+

Collections

+

Collection types use heap memory because their contents have dynamic size; they will request more +memory when needed, and can +release memory when it's +no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In +a way, collections are smart pointers for many objects at a time. Common types that fall under +this umbrella are Vec, +HashMap, and +String (not +str).

+

While collections store the objects they own in heap memory, creating new collections will not +allocate on the heap. This is a bit weird; if we call Vec::new(), the assembly shows a +corresponding call to real_drop_in_place:

+
pub fn my_vec() {
// Drop in place at line 481
Vec::<u8>::new();
}
+

-- Compiler Explorer

+

But because the vector has no elements to manage, no calls to the allocator will ever be dispatched:

+
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
// Turn on panicking if we allocate on the heap
DO_PANIC.store(true, Ordering::SeqCst);

// Interesting bit happens here
let x: Vec<u8> = Vec::new();
drop(x);

// Turn panicking back off, some deallocations occur
// after main as well.
DO_PANIC.store(false, Ordering::SeqCst);
}

#[global_allocator]
static A: PanicAllocator = PanicAllocator;
static DO_PANIC: AtomicBool = AtomicBool::new(false);
struct PanicAllocator;

unsafe impl GlobalAlloc for PanicAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected allocation.");
}
System.alloc(layout)
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if DO_PANIC.load(Ordering::SeqCst) {
panic!("Unexpected deallocation.");
}
System.dealloc(ptr, layout);
}
}
+

-- +Rust Playground

+

Other standard library types follow the same behavior; make sure to check out +HashMap::new(), +and String::new().

+

Heap Alternatives

+

While it is a bit strange to speak of the stack after spending time with the heap, it's worth +pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by +other crates. If you have need of the functionality, but want to avoid allocating, there are +typically alternatives available.

+

When it comes to some standard library smart pointers +(RwLock and +Mutex), stack-based alternatives are +provided in crates like parking_lot and +spin. You can check out +lock_api::RwLock, +lock_api::Mutex, and +spin::Once if you're in need +of synchronization primitives.

+

thread_id may be necessary if you're implementing an allocator +because thread::current().id() uses a +thread_local! structure +that needs heap allocation.

+

Tracing Allocators

+

When writing performance-sensitive code, there's no alternative to measuring your code. If you +didn't write a benchmark, +you don't care about it's performance +You should never rely on your instincts when +a microsecond is an eternity.

+

Similarly, there's great work going on in Rust with allocators that keep track of what they're doing +(like alloc_counter). When it comes to tracking heap +behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard +against future issues.

]]>
+
+ + <![CDATA[Allocations in Rust: Fixed memory]]> + https://speice.io/2019/02/stacking-up + https://speice.io/2019/02/stacking-up + Wed, 06 Feb 2019 12:00:00 GMT + + const and static are perfectly fine, but it's relatively rare that we know at compile-time about +either values or references that will be the same for the duration of our program. Put another way, +it's not often the case that either you or your compiler knows how much memory your entire program +will ever need.

+

However, there are still some optimizations the compiler can do if it knows how much memory +individual functions will need. Specifically, the compiler can make use of "stack" memory (as +opposed to "heap" memory) which can be managed far faster in both the short- and long-term.

+

When requesting memory, the push instruction +can typically complete in 1 or 2 cycles (<1ns +on modern CPUs). Contrast that to heap memory which requires an allocator (specialized +software to track what memory is in use) to reserve space. When you're finished with stack memory, +the pop instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory +fragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have +been used to design allocators:

+ +

But no matter how fast your allocator is, the principle remains: the fastest allocator is the one +you never use. As such, we're not going to discuss how exactly the +push and pop instructions work, but +we'll focus instead on the conditions that enable the Rust compiler to use faster stack-based +allocation for variables.

+

So, how do we know when Rust will or will not use stack allocation for objects we create? +Looking at other languages, it's often easy to delineate between stack and heap. Managed memory +languages (Python, Java, +C#) place +everything on the heap. JIT compilers (PyPy, +HotSpot) may optimize +some heap allocations away, but you should never assume it will happen. C makes things clear with +calls to special functions (like malloc(3)) needed to access +heap memory. Old C++ has the new keyword, though +modern C++/C++11 is more complicated with RAII.

+

For Rust, we can summarize as follows: stack allocation will be used for everything that doesn't +involve "smart pointers" and collections. We'll skip over a precise definition of the term "smart +pointer" for now, and instead discuss what we should watch for to understand when stack and heap +memory regions are used:

+
    +
  1. +

    Stack manipulation instructions (push, pop, and add/sub of the rsp register) indicate +allocation of stack memory:

    +
    pub fn stack_alloc(x: u32) -> u32 {
    // Space for `y` is allocated by subtracting from `rsp`,
    // and then populated
    let y = [1u8, 2, 3, 4];
    // Space for `y` is deallocated by adding back to `rsp`
    x
    }
    +

    -- Compiler Explorer

    +
  2. +
  3. +

    Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch +for call core::ptr::real_drop_in_place, and infer that a heap allocation happened in the recent +past:

    +
    pub fn heap_alloc(x: usize) -> usize {
    // Space for elements in a vector has to be allocated
    // on the heap, and is then de-allocated once the
    // vector goes out of scope
    let y: Vec<u8> = Vec::with_capacity(x);
    x
    }
    +

    -- Compiler Explorer (real_drop_in_place happens on line 1317) +Note: While the +Drop trait is +called for stack-allocated objects, +the Rust standard library only defines Drop implementations for types that involve heap +allocation.

    +
  4. +
  5. +

    If you don't want to inspect the assembly, use a custom allocator that's able to track and alert +when heap allocations occur. Crates like +alloc_counter are designed for exactly this purpose.

    +
  6. +
+

With all that in mind, let's talk about situations in which we're guaranteed to use stack memory:

+
    +
  • Structs are created on the stack.
  • +
  • Function arguments are passed on the stack, meaning the +#[inline] attribute will +not change the memory region used.
  • +
  • Enums and unions are stack-allocated.
  • +
  • Arrays are always stack-allocated.
  • +
  • Closures capture their arguments on the stack.
  • +
  • Generics will use stack allocation, even with dynamic dispatch.
  • +
  • Copy types are guaranteed to be +stack-allocated, and copying them will be done in stack memory.
  • +
  • Iterators in the standard library are +stack-allocated even when iterating over heap-based collections.
  • +
+

Structs

+

The simplest case comes first. When creating vanilla struct objects, we use stack memory to hold +their contents:

+
struct Point {
x: u64,
y: u64,
}

struct Line {
a: Point,
b: Point,
}

pub fn make_line() {
// `origin` is stored in the first 16 bytes of memory
// starting at location `rsp`
let origin = Point { x: 0, y: 0 };
// `point` makes up the next 16 bytes of memory
let point = Point { x: 1, y: 2 };

// When creating `ray`, we just move the content out of
// `origin` and `point` into the next 32 bytes of memory
let ray = Line { a: origin, b: point };
}
+

-- Compiler Explorer

+

Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the +sub rsp, 64 instruction indicates we're still working with the stack.

+

Function arguments

+

Have you ever wondered how functions communicate with each other? Like, once the variables are given +to you, everything's fine. But how do you "give" those variables to another function? How do you get +the results back afterward? The answer: the compiler arranges memory and assembly instructions using +a pre-determined calling convention. This +convention governs the rules around where arguments needed by a function will be located (either in +memory offsets relative to the stack pointer rsp, or in other registers), and where the results +can be found once the function has finished. And when multiple languages agree on what the calling +conventions are, you can do things like having Go call Rust code!

+

Put simply: it's the compiler's job to figure out how to call other functions, and you can assume +that the compiler is good at its job.

+

We can see this in action using a simple example:

+
struct Point {
x: i64,
y: i64,
}

// We use integer division operations to keep
// the assembly clean, understanding the result
// isn't accurate.
fn distance(a: &Point, b: &Point) -> i64 {
// Immediately subtract from `rsp` the bytes needed
// to hold all the intermediate results - this is
// the stack allocation step

// The compiler used the `rdi` and `rsi` registers
// to pass our arguments, so read them in
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

// Do the actual math work
let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared

// Our final result will be stored in the `rax` register
// so that our caller knows where to retrieve it.
// Finally, add back to `rsp` the stack memory that is
// now ready to be used by other functions.
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

As a consequence of function arguments never using heap memory, we can also infer that functions +using the #[inline] attributes also do not heap allocate. But better than inferring, we can look +at the assembly to prove it:

+
struct Point {
x: i64,
y: i64,
}

// Note that there is no `distance` function in the assembly output,
// and the total line count goes from 229 with inlining off
// to 306 with inline on. Even still, no heap allocations occur.
#[inline(always)]
fn distance(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (a.x - b.x) * (a.x - b.x);
let y_pow = (a.y - b.y) * (a.y - b.y);
let squared = x_pow + y_pow;
squared / squared
}

pub fn total_distance() {
let start = Point { x: 1, y: 2 };
let middle = Point { x: 3, y: 4 };
let end = Point { x: 5, y: 6 };

let _dist_1 = distance(&start, &middle);
let _dist_2 = distance(&middle, &end);
}
+

-- Compiler Explorer

+

Finally, passing by value (arguments with type +Copy) and passing by reference (either +moving ownership or passing a pointer) may have slightly different layouts in assembly, but will +still use either stack memory or CPU registers:

+
pub struct Point {
x: i64,
y: i64,
}

// Moving values
pub fn distance_moved(a: Point, b: Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}

// Borrowing values has two extra `mov` instructions on lines 21 and 22
pub fn distance_borrowed(a: &Point, b: &Point) -> i64 {
let x1 = a.x;
let x2 = b.x;
let y1 = a.y;
let y2 = b.y;

let x_pow = (x1 - x2) * (x1 - x2);
let y_pow = (y1 - y2) * (y1 - y2);
let squared = x_pow + y_pow;
squared / squared
}
+

-- Compiler Explorer

+

Enums

+

If you've ever worried that wrapping your types in +Option or +Result would finally make them +large enough that Rust decides to use heap allocation instead, fear no longer: enum and union +types don't use heap allocation:

+
enum MyEnum {
Small(u8),
Large(u64)
}

struct MyStruct {
x: MyEnum,
y: MyEnum,
}

pub fn enum_compare() {
let x = MyEnum::Small(0);
let y = MyEnum::Large(0);

let z = MyStruct { x, y };

let opt = Option::Some(z);
}
+

-- Compiler Explorer

+

Because the size of an enum is the size of its largest element plus a flag, the compiler can +predict how much memory is used no matter which variant of an enum is currently stored in a +variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great +way to show this in assembly, so I'll instead point you to the +core::mem::size_of +documentation.

+

Arrays

+

The array type is guaranteed to be stack allocated, which is why the array size must be declared. +Interestingly enough, this can be used to cause safe Rust programs to crash:

+
// 256 bytes
#[derive(Default)]
struct TwoFiftySix {
_a: [u64; 32]
}

// 8 kilobytes
#[derive(Default)]
struct EightK {
_a: [TwoFiftySix; 32]
}

// 256 kilobytes
#[derive(Default)]
struct TwoFiftySixK {
_a: [EightK; 32]
}

// 8 megabytes - exceeds space typically provided for the stack,
// though the kernel can be instructed to allocate more.
// On Linux, you can check stack size using `ulimit -s`
#[derive(Default)]
struct EightM {
_a: [TwoFiftySixK; 32]
}

fn main() {
// Because we already have things in stack memory
// (like the current function call stack), allocating another
// eight megabytes of stack memory crashes the program
let _x = EightM::default();
}
+

-- +Rust Playground

+

There aren't any security implications of this (no memory corruption occurs), but it's good to note +that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to +overflow the stack.

+

Closures

+

Rules for how anonymous functions capture their arguments are typically language-specific. In Java, +Lambda Expressions are +actually objects created on the heap that capture local primitives by copying, and capture local +non-primitives as (final) references. +Python and +JavaScript +both bind everything by reference normally, but Python can also +capture values and JavaScript has +Arrow functions.

+

In Rust, arguments to closures are the same as arguments to other functions; closures are simply +functions that don't have a declared name. Some weird ordering of the stack may be required to +handle them, but it's the compiler's responsiblity to figure that out.

+

Each example below has the same effect, but a different assembly implementation. In the simplest +case, we immediately run a closure returned by another function. Because we don't store a reference +to the closure, the stack memory needed to store the captured values is contiguous:

+
fn my_func() -> impl FnOnce() {
let x = 24;
// Note that this closure in assembly looks exactly like
// any other function; you even use the `call` instruction
// to start running it.
move || { x; }
}

pub fn immediate() {
my_func()();
my_func()();
}
+

-- Compiler Explorer, 25 total assembly instructions

+

If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory +of the original function. Getting the details right is a bit harder, so the instruction count goes +up even though this code is functionally equivalent to our original example:

+
pub fn simple_reference() {
let x = my_func();
let y = my_func();
y();
x();
}
+

-- Compiler Explorer, 55 total assembly instructions

+

Even things like variable order can make a difference in instruction count:

+
pub fn complex() {
let x = my_func();
let y = my_func();
x();
y();
}
+

-- Compiler Explorer, 70 total assembly instructions

+

In every circumstance though, the compiler ensured that no heap allocations were necessary.

+

Generics

+

Traits in Rust come in two broad forms: static dispatch (monomorphization, impl Trait) and dynamic +dispatch (trait objects, dyn Trait). While dynamic dispatch is often associated with trait +objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:

+
trait GetInt {
fn get_int(&self) -> u64;
}

// vtable stored at section L__unnamed_1
struct WhyNotU8 {
x: u8
}
impl GetInt for WhyNotU8 {
fn get_int(&self) -> u64 {
self.x as u64
}
}

// vtable stored at section L__unnamed_2
struct ActualU64 {
x: u64
}
impl GetInt for ActualU64 {
fn get_int(&self) -> u64 {
self.x
}
}

// `&dyn` declares that we want to use dynamic dispatch
// rather than monomorphization, so there is only one
// `retrieve_int` function that shows up in the final assembly.
// If we used generics, there would be one implementation of
// `retrieve_int` for each type that implements `GetInt`.
pub fn retrieve_int(u: &dyn GetInt) {
// In the assembly, we just call an address given to us
// in the `rsi` register and hope that it was set up
// correctly when this function was invoked.
let x = u.get_int();
}

pub fn do_call() {
// Note that even though the vtable for `WhyNotU8` and
// `ActualU64` includes a pointer to
// `core::ptr::real_drop_in_place`, it is never invoked.
let a = WhyNotU8 { x: 0 };
let b = ActualU64 { x: 0 };

retrieve_int(&a);
retrieve_int(&b);
}
+

-- Compiler Explorer

+

It's hard to imagine practical situations where dynamic dispatch would be used for objects that +aren't heap allocated, but it technically can be done.

+

Copy types

+

Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs +go into detail far better than can +be addressed here, so I'll leave them to do the job. From a memory perspective though, their +guideline is reasonable: +if your type can implemement Copy, it should. +While there are potential speed tradeoffs to benchmark when discussing Copy (move semantics for +stack objects vs. copying stack pointers vs. copying stack structs), it's impossible for Copy +to introduce a heap allocation.

+

But why is this the case? Fundamentally, it's because the language controls what Copy means - +"the behavior of Copy is not overloadable" +because it's a marker trait. From there we'll note that a type +can implement Copy +if (and only if) its components implement Copy, and that +no heap-allocated types implement Copy. +Thus, assignments involving heap types are always move semantics, and new heap allocations won't +occur because of implicit operator behavior.

+
#[derive(Clone)]
struct Cloneable {
x: Box<u64>
}

// error[E0204]: the trait `Copy` may not be implemented for this type
#[derive(Copy, Clone)]
struct NotCopyable {
x: Box<u64>
}
+

-- Compiler Explorer

+

Iterators

+

In managed memory languages (like +Java), there's a subtle +difference between these two code samples:

+
public static int sum_for(List<Long> vals) {
long sum = 0;
// Regular for loop
for (int i = 0; i < vals.length; i++) {
sum += vals[i];
}
return sum;
}

public static int sum_foreach(List<Long> vals) {
long sum = 0;
// "Foreach" loop - uses iteration
for (Long l : vals) {
sum += l;
}
return sum;
}
+

In the sum_for function, nothing terribly interesting happens. In sum_foreach, an object of type +Iterator +is allocated on the heap, and will eventually be garbage-collected. This isn't a great design; +iterators are often transient objects that you need during a function and can discard once the +function ends. Sounds exactly like the issue stack-allocated objects address, no?

+

In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in +heap memory, but the iterator itself +(Iter) doesn't need to use the heap. In +each of the examples below we iterate over a collection, but never use heap allocation:

+
use std::collections::HashMap;
// There's a lot of assembly generated, but if you search in the text,
// there are no references to `real_drop_in_place` anywhere.

pub fn sum_vec(x: &Vec<u32>) {
let mut s = 0;
// Basic iteration over vectors doesn't need allocation
for y in x {
s += y;
}
}

pub fn sum_enumerate(x: &Vec<u32>) {
let mut s = 0;
// More complex iterators are just fine too
for (_i, y) in x.iter().enumerate() {
s += y;
}
}

pub fn sum_hm(x: &HashMap<u32, u32>) {
let mut s = 0;
// And it's not just Vec, all types will allocate the iterator
// on stack memory
for y in x.values() {
s += y;
}
}
+

-- Compiler Explorer

]]>
+
+ + <![CDATA[Allocations in Rust: Global memory]]> + https://speice.io/2019/02/the-whole-world + https://speice.io/2019/02/the-whole-world + Tue, 05 Feb 2019 12:00:00 GMT + + The first memory type we'll look at is pretty special: when Rust can prove that a value is fixed +for the life of a program (const), and when a reference is unique for the life of a program +(static as a declaration, not +'static as a +lifetime), we can make use of global memory. This special section of data is embedded directly in +the program binary so that variables are ready to go once the program loads; no additional +computation is necessary.

+

Understanding the value/reference distinction is important for reasons we'll go into below, and +while the +full specification for +these two keywords is available, we'll take a hands-on approach to the topic.

+

const values

+

When a value is guaranteed to be unchanging in your program (where "value" may be scalars, +structs, etc.), you can declare it const. This tells the compiler that it's safe to treat the +value as never changing, and enables some interesting optimizations; not only is there no +initialization cost to creating the value (it is loaded at the same time as the executable parts of +your program), but the compiler can also copy the value around if it speeds up the code.

+

The points we need to address when talking about const are:

+
    +
  • Const values are stored in read-only memory - it's impossible to modify.
  • +
  • Values resulting from calling a const fn are materialized at compile-time.
  • +
  • The compiler may (or may not) copy const values wherever it chooses.
  • +
+

Read-Only

+

The first point is a bit strange - "read-only memory." +The Rust book +mentions in a couple places that using mut with constants is illegal, but it's also important to +demonstrate just how immutable they are. Typically in Rust you can use +interior mutability to modify +things that aren't declared mut. +RefCell provides an example of this +pattern in action:

+
use std::cell::RefCell;

fn my_mutator(cell: &RefCell<u8>) {
// Even though we're given an immutable reference,
// the `replace` method allows us to modify the inner value.
cell.replace(14);
}

fn main() {
let cell = RefCell::new(25);
// Prints out 25
println!("Cell: {:?}", cell);
my_mutator(&cell);
// Prints out 14
println!("Cell: {:?}", cell);
}
+

-- +Rust Playground

+

When const is involved though, interior mutability is impossible:

+
use std::cell::RefCell;

const CELL: RefCell<u8> = RefCell::new(25);

fn my_mutator(cell: &RefCell<u8>) {
cell.replace(14);
}

fn main() {
// First line prints 25 as expected
println!("Cell: {:?}", &CELL);
my_mutator(&CELL);
// Second line *still* prints 25
println!("Cell: {:?}", &CELL);
}
+

-- +Rust Playground

+

And a second example using Once:

+
use std::sync::Once;

const SURPRISE: Once = Once::new();

fn main() {
// This is how `Once` is supposed to be used
SURPRISE.call_once(|| println!("Initializing..."));
// Because `Once` is a `const` value, we never record it
// having been initialized the first time, and this closure
// will also execute.
SURPRISE.call_once(|| println!("Initializing again???"));
}
+

-- +Rust Playground

+

When the +const specification +refers to "rvalues", this +behavior is what they refer to. Clippy will treat this +as an error, but it's still something to be aware of.

+

Initialization

+

The next thing to mention is that const values are loaded into memory as part of your program +binary. Because of this, any const values declared in your program will be "realized" at +compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may +be able to prefetch the value), but that's it.

+
use std::cell::RefCell;

const CELL: RefCell<u32> = RefCell::new(24);

pub fn multiply(value: u32) -> u32 {
// CELL is stored at `.L__unnamed_1`
value * (*CELL.get_mut())
}
+

-- Compiler Explorer

+

The compiler creates one RefCell, uses it everywhere, and never needs to call the RefCell::new +function.

+

Copying

+

If it's helpful though, the compiler can choose to copy const values.

+
const FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// See assembly line 4 for the `mov edi, 1000` instruction
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// See assembly lines 22 and 29 for `mov edi, 1000` instructions
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

In this example, the FACTOR value is turned into the mov edi, 1000 instruction in both the +multiply and multiply_twice functions; the "1000" value is never "stored" anywhere, as it's +small enough to inline into the assembly instructions.

+

Finally, getting the address of a const value is possible, but not guaranteed to be unique +(because the compiler can choose to copy values). I was unable to get non-unique pointers in my +testing (even using different crates), but the specifications are clear enough: don't rely on +pointers to const values being consistent. To be frank, caring about locations for const values +is almost certainly a code smell.

+

static values

+

Static variables are related to const variables, but take a slightly different approach. When we +declare that a reference is unique for the life of a program, you have a static variable +(unrelated to the 'static lifetime). Because of the reference/value distinction with +const/static, static variables behave much more like typical "global" variables.

+

But to understand static, here's what we'll look at:

+
    +
  • static variables are globally unique locations in memory.
  • +
  • Like const, static variables are loaded at the same time as your program being read into +memory.
  • +
  • All static variables must implement the +Sync marker trait.
  • +
  • Interior mutability is safe and acceptable when using static variables.
  • +
+

Memory Uniqueness

+

The single biggest difference between const and static is the guarantees provided about +uniqueness. Where const variables may or may not be copied in code, static variables are +guarantee to be unique. If we take a previous const example and change it to static, the +difference should be clear:

+
static FACTOR: u32 = 1000;

pub fn multiply(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR
}

pub fn multiply_twice(value: u32) -> u32 {
// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used
value * FACTOR * FACTOR
}
+

-- Compiler Explorer

+

Where previously there were plenty of references to multiplying by 1000, the new +assembly refers to FACTOR as a named memory location instead. No initialization work needs to be +done, but the compiler can no longer prove the value never changes during execution.

+

Initialization

+

Next, let's talk about initialization. The simplest case is initializing static variables with +either scalar or struct notation:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

static MY_STRUCT: MyStruct = MyStruct {
// You can even reference other statics
// declared later
x: MY_VAL
};

static MY_VAL: u32 = 24;

fn main() {
println!("Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

Things can get a bit weirder when using const fn though. In most cases, it just works:

+
#[derive(Debug)]
struct MyStruct {
x: u32
}

impl MyStruct {
const fn new() -> MyStruct {
MyStruct { x: 24 }
}
}

static MY_STRUCT: MyStruct = MyStruct::new();

fn main() {
println!("const fn Static MyStruct: {:?}", MY_STRUCT);
}
+

-- +Rust Playground

+

However, there's a caveat: you're currently not allowed to use const fn to initialize static +variables of types that aren't marked Sync. For example, +RefCell::new() is a +const fn, but because +RefCell isn't Sync, you'll +get an error at compile time:

+
use std::cell::RefCell;

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_LOCK: RefCell<u8> = RefCell::new(0);
+

-- +Rust Playground

+

It's likely that this will +change in the future though.

+

The Sync marker

+

Which leads well to the next point: static variable types must implement the +Sync marker. Because they're globally +unique, it must be safe for you to access static variables from any thread at any time. Most +struct definitions automatically implement the Sync trait because they contain only elements +which themselves implement Sync (read more in the +Nomicon). This is why earlier examples could +get away with initializing statics, even though we never included an impl Sync for MyStruct in the +code. To demonstrate this property, Rust refuses to compile our earlier example if we add a +non-Sync element to the struct definition:

+
use std::cell::RefCell;

struct MyStruct {
x: u32,
y: RefCell<u8>,
}

// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely
static MY_STRUCT: MyStruct = MyStruct {
x: 8,
y: RefCell::new(8)
};
+

-- +Rust Playground

+

Interior mutability

+

Finally, while static mut variables are allowed, mutating them is an unsafe operation. If we +want to stay in safe Rust, we can use interior mutability to accomplish similar goals:

+
use std::sync::Once;

// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once
static INIT: Once = Once::new();

fn main() {
// Note that while `INIT` is declared immutable, we're still allowed
// to mutate its interior
INIT.call_once(|| println!("Initializing..."));
// This code won't panic, as the interior of INIT was modified
// as part of the previous `call_once`
INIT.call_once(|| panic!("INIT was called twice!"));
}
+

-- +Rust Playground

]]>
+
+ + <![CDATA[Allocations in Rust: Foreword]]> + https://speice.io/2019/02/understanding-allocations-in-rust + https://speice.io/2019/02/understanding-allocations-in-rust + Mon, 04 Feb 2019 12:00:00 GMT + + There's an alchemy of distilling complex technical topics into articles and videos that change the +way programmers see the tools they interact with on a regular basis. I knew what a linker was, but +there's a staggering amount of complexity in between +the OS and main(). Rust programmers use the +Box type all the time, but there's a +rich history of the Rust language itself wrapped up in +how special it is.

+

In a similar vein, this series attempts to look at code and understand how memory is used; the +complex choreography of operating system, compiler, and program that frees you to focus on +functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the +cognitive burden associated with memory management, but we're going to step into its world for a +while.

+

Let's learn a bit about memory in Rust.

+
+

Rust's three defining features of +Performance, Reliability, and Productivity are all driven to a great +degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, +Python), Rust +doesn't really +garbage collect; instead, it uses an +ownership system to reason about +how long objects will last in your program. In some cases, if the life of an object is fairly +transient, Rust can make use of a very fast region called the "stack." When that's not possible, +Rust uses +dynamic (heap) memory +and the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it +is important to have available.

+

That said, there are specific situations in Rust where you'd never need to worry about the +stack/heap distinction! If you:

+
    +
  1. Never use unsafe
  2. +
  3. Never use #![feature(alloc)] or the alloc crate
  4. +
+

...then it's not possible for you to use dynamic memory!

+

For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited +memory, and the program binary size itself may significantly affect what's available! There's no +operating system able to manage this +"virtual memory" thing, but that's not an issue +because there's only one running application. The +embedonomicon is ever in mind, and +interacting with the "real world" through extra peripherals is accomplished by reading and writing +to specific memory addresses.

+

Most Rust programs find these requirements overly burdensome though. C++ developers would struggle +without access to std::vector (except those +hardcore no-STL people), and Rust developers would struggle without +std::vec. But with the constraints above, +std::vec is actually a part of the +alloc crate, and thus off-limits. Box, +Rc, etc., are also unusable for the same reason.

+

Whether writing code for embedded devices or not, the important thing in both situations is how much +you know before your application starts about what its memory usage will look like. In embedded +devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large +google.com's home page is until you start trying to download it. The +compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code +runs faster when the compiler can guarantee exactly how much memory your program needs while it's +running. This series is all about understanding how the compiler reasons about your program, with an +emphasis on the implications for performance.

+

Now let's address some conditions and caveats before going much further:

+
    +
  • We'll focus on "safe" Rust only; unsafe lets you use platform-specific allocation API's +(malloc) that we'll +ignore.
  • +
  • We'll assume a "debug" build of Rust code (what you get with cargo run and cargo test) and +address (pun intended) release mode at the end (cargo run --release and cargo test --release).
  • +
  • All content will be run using Rust 1.32, as that's the highest currently supported in the +Compiler Exporer. As such, we'll avoid upcoming innovations like +compile-time evaluation of static +that are available in nightly.
  • +
  • Because of the nature of the content, being able to read assembly is helpful. We'll keep it +simple, but I found a +refresher on the push and pop +instructions was helpful while writing +this.
  • +
  • I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are +available, but if there's something said in error it will be corrected expeditiously. Please let +me know at bradlee@speice.io
  • +
+

Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth +repeating:

+
+

Rust does not currently have a rigorously and formally defined memory model.

+

-- the docs

+
]]>
+
+ + <![CDATA[QADAPT - debug_assert! for allocations]]> + https://speice.io/2018/12/allocation-safety + https://speice.io/2018/12/allocation-safety + Sat, 15 Dec 2018 12:00:00 GMT + + I think it's part of the human condition to ignore perfectly good advice when it comes our way. A +bit over a month ago, I was dispensing sage wisdom for the ages:

+
+

I had a really great idea: build a custom allocator that allows you to track your own allocations. +I gave it a shot, but learned very quickly: never write your own allocator.

+

-- me

+
+

I proceeded to ignore it, because we never really learn from our mistakes.

+

There's another part of the human condition that derives joy from seeing things explode.

+

Explosions

+

And that's the part I'm going to focus on.

+

Why an Allocator?

+

So why, after complaining about allocators, would I still want to write one? There are three reasons +for that:

+
    +
  1. Allocation/dropping is slow
  2. +
  3. It's difficult to know exactly when Rust will allocate or drop, especially when using code that +you did not write
  4. +
  5. I want automated tools to verify behavior, instead of inspecting by hand
  6. +
+

When I say "slow," it's important to define the terms. If you're writing web applications, you'll +spend orders of magnitude more time waiting for the database than you will the allocator. However, +there's still plenty of code where micro- or nano-seconds matter; think +finance, +real-time audio, +self-driving cars, and +networking. In these situations it's simply +unacceptable for you to spend time doing things that are not your program, and waiting on the +allocator is not cool.

+

As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. +So, I propose we play a quick trivia game: Does this code invoke the allocator?

+

Example 1

+
fn my_function() {
let v: Vec<u8> = Vec::new();
}
+

No: Rust knows how big the Vec type is, +and reserves a fixed amount of memory on the stack for the v vector. However, if we wanted to +reserve extra space (using Vec::with_capacity) the allocator would get invoked.

+

Example 2

+
fn my_function() {
let v: Box<Vec<u8>> = Box::new(Vec::new());
}
+

Yes: Because Boxes allow us to work with things that are of unknown size, it has to allocate on +the heap. While the Box is unnecessary in this snippet (release builds will optimize out the +allocation), reserving heap space more generally is needed to pass a dynamically sized type to +another function.

+

Example 3

+
fn my_function(v: Vec<u8>) {
v.push(5);
}
+

Maybe: Depending on whether the Vector we were given has space available, we may or may not +allocate. Especially when dealing with code that you did not author, it's difficult to verify that +things behave as you expect them to.

+

Blowing Things Up

+

So, how exactly does QADAPT solve these problems? Whenever an allocation or drop occurs in code +marked allocation-safe, QADAPT triggers a thread panic. We don't want to let the program continue +as if nothing strange happened, we want things to explode.

+

However, you don't want code to panic in production because of circumstances you didn't predict. +Just like debug_assert!, QADAPT will +strip out its own code when building in release mode to guarantee no panics and no performance +impact.

+

Finally, there are three ways to have QADAPT check that your code will not invoke the allocator:

+

Using a procedural macro

+

The easiest method, watch an entire function for allocator invocation:

+
use qadapt::no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

#[no_alloc]
fn push_vec(v: &mut Vec<u8>) {
// This triggers a panic if v.len() == v.capacity()
v.push(5);
}

fn main() {
let v = Vec::with_capacity(1);

// This will *not* trigger a panic
push_vec(&v);

// This *will* trigger a panic
push_vec(&v);
}
+

Using a regular macro

+

For times when you need more precision:

+
use qadapt::assert_no_alloc;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
let v = Vec::with_capacity(1);

// No allocations here, we already have space reserved
assert_no_alloc!(v.push(5));

// Even though we remove an item, it doesn't trigger a drop
// because it's a scalar. If it were a `Box<_>` type,
// a drop would trigger.
assert_no_alloc!({
v.pop().unwrap();
});
}
+

Using function calls

+

Both the most precise and most tedious:

+
use qadapt::enter_protected;
use qadapt::exit_protected;
use qadapt::QADAPT;

#[global_allocator]
static Q: QADAPT = QADAPT;

fn main() {
// This triggers an allocation (on non-release builds)
let v = Vec::with_capacity(1);

enter_protected();
// This does not trigger an allocation because we've reserved size
v.push(0);
exit_protected();

// This triggers an allocation because we ran out of size,
// but doesn't panic because we're no longer protected.
v.push(1);
}
+

Caveats

+

It's important to point out that QADAPT code is synchronous, so please be careful when mixing in +asynchronous functions:

+
use futures::future::Future;
use futures::future::ok;

#[no_alloc]
fn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> {
ok(12).and_then(|e| Ok(Vec::with_capacity(e)))
}

fn main() {
// This doesn't trigger a panic because the `and_then` closure
// wasn't run during the function call.
async_capacity();

// Still no panic
assert_no_alloc!(async_capacity());

// This will panic because the allocation happens during `unwrap`
// in the `assert_no_alloc!` macro
assert_no_alloc!(async_capacity().poll().unwrap());
}
+

Conclusion

+

While there's a lot more to writing high-performance code than managing your usage of the allocator, +it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing +what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for +most allocators. Version 1.0 was released today, and you can check it out over at +crates.io or on github.

+

I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will +help guide that. If there are topics you're interested in, let me know in the comments below!

]]>
+
+ + <![CDATA[More "what companies really mean"]]> + https://speice.io/2018/12/what-small-business-really-means + https://speice.io/2018/12/what-small-business-really-means + Tue, 04 Dec 2018 12:00:00 GMT + + I recently stumbled across a phenomenal small article entitled +What Startups Really Mean By "Why Should We Hire You?". +Having been interviewed by smaller companies (though not exactly startups), the questions and +subtexts are the same. There's often a question behind the question that you're actually trying to +answer, and I wish I spotted the nuance earlier in my career.

+

Let me also make note of one more question/euphemism I've come across:

+

How do you feel about production support?

+

Translation: We're a fairly small team, and when things break on an evening/weekend/Christmas +Day, can we call on you to be there?

+

I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're +incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning +that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make +it out the door before the zombie apocalypse.

+

Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people +who either enjoy that, or play along nicely enough that our systems keep working.

+

Small teams have no such luck. If you're interviewing at a small company, especially as a "data +scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the +most inopportune moments.

+

Terrible-but-popular answers include: It's a part of the job, and I'm happy to contribute.

]]>
+
+ + <![CDATA[A case study in heaptrack]]> + https://speice.io/2018/10/case-study-optimization + https://speice.io/2018/10/case-study-optimization + Mon, 08 Oct 2018 12:00:00 GMT + + I remember early in my career someone joking that:

+
+

Programmers have it too easy these days. They should learn to develop in low memory environments +and be more efficient.

+
+

...though it's not like the first code I wrote was for a +graphing calculator +packing a whole 24KB of RAM.

+

But the principle remains: be efficient with the resources you have, because +what Intel giveth, Microsoft taketh away.

+

My professional work is focused on this kind of efficiency; low-latency financial markets demand +that you understand at a deep level exactly what your code is doing. As I continue experimenting +with Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's +flexibility for the times I pretend to have a garbage collector, and flexibility for the times that +I really care about how memory is used.

+

This post is a (small) case study in how I went from the former to the latter. And ultimately, it's +intended to be a starting toolkit to empower analysis of your own code.

+

Curiosity

+

When I first started building the dtparse crate, my intention was to mirror as closely as possible +the equivalent Python library. Python, as you may know, is garbage collected. Very +rarely is memory usage considered in Python, and I likewise wasn't paying too much attention when +dtparse was first being built.

+

This lackadaisical approach to memory works well enough, and I'm not planning on making dtparse +hyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the +advent of Rust 1.28 and the +Global Allocator trait, I had a really +great idea: build a custom allocator that allows you to track your own allocations. That way, you +can do things like writing tests for both correct results and correct memory usage. I gave it a +shot, but learned very quickly: never write your own allocator. It went from "fun +weekend project" to "I have literally no idea what my computer is doing" at breakneck speed.

+

Instead, I'll highlight a separate path I took to make sense of my memory usage: heaptrack.

+

Turning on the System Allocator

+

This is the hardest part of the post. Because Rust uses +its own allocator by default, +heaptrack is unable to properly record unmodified Rust code. To remedy this, we'll make use of the +#[global_allocator] attribute.

+

Specifically, in lib.rs or main.rs, add this:

+
use std::alloc::System;

#[global_allocator]
static GLOBAL: System = System;
+

...and that's it. Everything else comes essentially for free.

+

Running heaptrack

+

Assuming you've installed heaptrack (Homebrew in Mac, package manager +in Linux, ??? in Windows), all that's left is to fire up your application:

+
heaptrack my_application
+

It's that easy. After the program finishes, you'll see a file in your local directory with a name +like heaptrack.my_appplication.XXXX.gz. If you load that up in heaptrack_gui, you'll see +something like this:

+

heaptrack

+
+

And even these pretty colors:

+

pretty colors

+

Reading Flamegraphs

+

To make sense of our memory usage, we're going to focus on that last picture - it's called a +"flamegraph". These charts are typically used to +show how much time your program spends executing each function, but they're used here to show how +much memory was allocated during those functions instead.

+

For example, we can see that all executions happened during the main function:

+

allocations in main

+

...and within that, all allocations happened during dtparse::parse:

+

allocations in dtparse

+

...and within that, allocations happened in two different places:

+

allocations in parseinfo

+

Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue: +what the heck is the Default thing doing?

+

pretty colors

+

Optimizing dtparse

+

See, I knew that there were some allocations during calls to dtparse::parse, but I was totally +wrong about where the bulk of allocations occurred in my program. Let me post the code and see if +you can spot the mistake:

+
/// Main entry point for using `dtparse`.
pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> {
let res = Parser::default().parse(
timestr, None, None, false, false,
None, false,
&HashMap::new(),
)?;

Ok((res.0, res.1))
}
+
+

dtparse

+
+
+

Because Parser::parse requires a mutable reference to itself, I have to create a new +Parser::default every time it receives a string. This is excessive! We'd rather have an immutable +parser that can be re-used, and avoid allocating memory in the first place.

+

Armed with that information, I put some time in to +make the parser immutable. +Now that I can re-use the same parser over and over, the allocations disappear:

+

allocations cleaned up

+

In total, we went from requiring 2 MB of memory in +version 1.0.2:

+

memory before

+

All the way down to 300KB in version 1.0.3:

+

memory after

+

Conclusion

+

In the end, you don't need to write a custom allocator to be efficient with memory, great tools +already exist to help you understand what your program is doing.

+

Use them.

+

Given that Moore's Law is +dead, we've all got to do +our part to take back what Microsoft stole.

]]>
+
+ + <![CDATA[Isomorphic desktop apps with Rust]]> + https://speice.io/2018/09/isomorphic-apps + https://speice.io/2018/09/isomorphic-apps + Sat, 15 Sep 2018 12:00:00 GMT + + I both despise Javascript and am stunned by its success doing some really cool things. It's +this duality that's +led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I +bootstrap a simple desktop application.

+

See, as much as +Webassembly isn't trying to replace Javascript, +I want Javascript gone. There are plenty of people who don't share my views, and they are +probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think +it's hilarious that the +language specification +dramatically outpaces anyone's +actual implementation. The answer to this +conundrum is of course to recompile code from newer versions of the language to older versions of +the same language before running. At least Babel is a nice tongue-in-cheek reference.

+

Yet for as much hate as Electron receives, it does a stunningly good job at solving a really hard +problem: how the hell do I put a button on the screen and react when the user clicks it? GUI +programming is hard, straight up. But if browsers are already able to run everywhere, why don't we +take advantage of someone else solving the hard problems for us? I don't like that I have to use +Javascript for it, but I really don't feel inclined to whip out good ol' wxWidgets.

+

Now there are other native solutions (libui-rs, conrod, oh hey wxWdidgets again!), but +those also have their own issues with distribution, styling, etc. With Electron, I can +yarn create electron-app my-app and just get going, knowing that packaging/upgrades/etc. are built +in.

+

My question is: given recent innovations with WASM, are we Electron yet?

+

No, not really.

+

Instead, what would it take to get to a point where we can skip Javascript in Electron apps?

+

Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There +may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to +try and organize what I did manage to discover.

+

I should also mention that the content and things I'm talking about here are not intended to be +prescriptive, but more "if someone else is interested, what do we already know doesn't work?" I +expect everything in this post to be obsolete within two months. Even over the course of writing +this, a separate blog post had +to be modified because upstream changes broke a +Rust tool the post tried to use. The post +ultimately +got updated, but +all this happened within the span of a week. Things are moving quickly.

+

I'll also note that we're going to skip asm.js and emscripten. Truth be told, I couldn't get +either of these to output anything, and so I'm just going to say +here be dragons. Everything I'm discussing here +uses the wasm32-unknown-unknown target.

+

The code that I did get running is available +over here. Feel free to use it as a starting point, +but I'm mostly including the link as a reference for the things that were attempted.

+

An Example Running Application

+

So, I did technically get a running application:

+

Electron app using WASM

+

...which you can also try out if you want:

+
git clone https://github.com/speice-io/isomorphic-rust.git
cd isomorphic_rust/percy
yarn install && yarn start
+

...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly +there to prove this is possible in the first place. And that's something to be proud of! There's a +huge amount of engineering that went into showing a window with the text "It's alive!".

+

There's also a lot of usability issues that prevent me from recommending anyone try Electron and +WASM apps at the moment, and I think that's the more important thing to discuss.

+

Issue the First: Complicated Toolchains

+

I quickly established that wasm-bindgen was necessary to "link" my Rust code to Javascript. At +that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM +blob. To keep things simple, the goal was to package everything using webpack so that I could just +load a bundle.js file on the page. That decision was to be the last thing that kinda worked in +this process.

+

The first issue +I ran into +while attempting to bundle everything via webpack is a detail in the WASM spec:

+
+

This function accepts a Response object, or a promise for one, and ... [if > it] does not match +the application/wasm MIME type, the returned promise will be rejected with a TypeError;

+

WebAssembly - Additional Web Embedding API

+
+

Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the +web this isn't a huge issue, as the server can set MIME types when delivering the blob. With +Electron, you're resolving things with a file:// URL and thus can't control the MIME type:

+

TypeError: Incorrect response MIME type. Expected &#39;application/wasm&#39;.

+

There are a couple of solutions depending on how far into the deep end you care to venture:

+
    +
  • Embed a static file server in your Electron application
  • +
  • Use a custom protocol and custom protocol handler
  • +
  • Host your WASM blob on a website that you resolve at runtime
  • +
+

But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. +Instead, my workaround was to +open a PR with webpack and use regex to remove +calls to instantiateStreaming in the +build script:

+
cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
# Have to use --mode=development so we can patch out the call to instantiateStreaming
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \
sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js"
+

Once that lands, the +build process +becomes much simpler:

+

cargo +nightly build --target=wasm32-unknown-unknown && \
wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \
"$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js"
+

But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via +wasm-bindgen and webpack), we still have to make an Electron app. For this purpose I used a +starter app from Electron Forge, and then a +prestart script +to actually handle starting the application.

+

The +final toolchain +looks something like this:

+
    +
  • yarn start triggers the prestart script
  • +
  • prestart checks for missing tools (wasm-bindgen-cli, etc.) and then: +
      +
    • Uses cargo to compile the Rust code into WASM
    • +
    • Uses wasm-bindgen to link the WASM blob into a Javascript file with exported symbols
    • +
    • Uses webpack to bundle the page start script with the Javascript we just generated +
        +
      • Uses babel under the hood to compile the wasm-bindgen code down from ES6 into something +browser-compatible
      • +
      +
    • +
    +
  • +
  • The start script runs an Electron Forge handler to do some sanity checks
  • +
  • Electron actually starts
  • +
+

...which is complicated. I think more work needs to be done to either build a high-quality starter +app that can manage these steps, or another tool that "just handles" the complexity of linking a +compiled WASM file into something the Electron browser can run.

+

Issue the Second: WASM tools in Rust

+

For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only +bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that +leads to a fragmented ecosystem. Here's what I can recommend as a starting point:

+

Don't check in your Cargo.lock files to version control. If there's a disagreement between the +version of wasm-bindgen-cli you have installed and the wasm-bindgen you're compiling with in +Cargo.lock, you get a nasty error:

+
it looks like the Rust project used to create this wasm file was linked against
a different version of wasm-bindgen than this binary:

rust wasm file: 0.2.21
this binary: 0.2.17

Currently the bindgen format is unstable enough that these two version must
exactly match, so it's required that these two version are kept in sync by
either updating the wasm-bindgen dependency or this binary.
+

Not that I ever managed to run into this myself (coughs nervously).

+

There are two projects attempting to be "application frameworks": percy and yew. Between those, +I managed to get two +examples running +using percy, but was unable to get an +example running with yew because +of issues with "missing modules" during the webpack step:

+
ERROR in ./dist/electron_yew_wasm_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist'
@ ./dist/electron_yew_wasm_bg.wasm
@ ./dist/electron_yew_wasm.js
@ ./dist/app.js
@ ./dist/app_loader.js
+

If you want to work with the browser APIs directly, your choices are percy-webapis or stdweb (or +eventually web-sys). See above for my percy examples, but when I tried +an example with stdweb, I was +unable to get it running:

+
ERROR in ./dist/stdweb_electron_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist'
@ ./dist/stdweb_electron_bg.wasm
@ ./dist/stdweb_electron.js
@ ./dist/app_loader.js
+

At this point I'm pretty convinced that stdweb is causing issues for yew as well, but can't +prove it.

+

I did also get a minimal example +running that doesn't depend on any tools besides wasm-bindgen. However, it requires manually +writing "extern C" blocks for everything you need from the browser. Es no bueno.

+

Finally, from a tools and platform view, there are two up-and-coming packages that should be +mentioned: js-sys and web-sys. Their purpose is to be fundamental building blocks that exposes +the browser's APIs to Rust. If you're interested in building an app framework from scratch, these +should give you the most flexibility. I didn't touch either in my research, though I expect them to +be essential long-term.

+

So there's a lot in play from the Rust side of things, and it's just going to take some time to +figure out what works and what doesn't.

+

Issue the Third: Known Unknowns

+

Alright, so after I managed to get an application started, I stopped there. It was a good deal of +effort to chain together even a proof of concept, and at this point I'd rather learn Typescript +than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...

+

The important point I want to make is that there's a lot unknown about how any of this holds up +outside proofs of concept. Things I didn't attempt:

+
    +
  • Testing
  • +
  • Packaging
  • +
  • Updates
  • +
  • Literally anything related to why I wanted to use Electron in the first place
  • +
+

What it Would Take

+

Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and +WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an +application in production a couple months from now. But at the moment, I'm personally going to stay +away.

+

Let's finish with a wishlist then - here are the things that I think need to happen before +Electron/WASM/Rust can become a thing:

+
    +
  • Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet +(#7983)
  • +
  • Browser API libraries (web-sys and stdweb) need to make sure they can support running in +Electron (see module error above)
  • +
  • Projects need to stabilize. There's talk of stdweb being turned into a Rust API +on top of web-sys, and percy +moving to web-sys, both of which are big changes
  • +
  • wasm-bindgen is great, but still in the "move fast and break things" phase
  • +
  • A good "boilerplate" app would dramatically simplify the start-up costs; +electron-react-boilerplate comes to +mind as a good project to imitate
  • +
  • More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm +doing
  • +
]]>
+
+ + <![CDATA[Primitives in Rust are weird (and cool)]]> + https://speice.io/2018/09/primitives-in-rust-are-weird + https://speice.io/2018/09/primitives-in-rust-are-weird + Sat, 01 Sep 2018 12:00:00 GMT + + I wrote a really small Rust program a while back because I was curious. I was 100% convinced it +couldn't possibly run:

+
fn main() {
println!("{}", 8.to_string())
}
+

And to my complete befuddlement, it compiled, ran, and produced a completely sensible output.

+

The reason I was so surprised has to do with how Rust treats a special category of things I'm going to +call primitives. In the current version of the Rust book, you'll see them referred to as +scalars, and in older versions they'll be called primitives, but +we're going to stick with the name primitive for the time being. Explaining why this program is so +cool requires talking about a number of other programming languages, and keeping a consistent +terminology makes things easier.

+

You've been warned: this is going to be a tedious post about a relatively minor issue that +involves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking +about with assembly.

+

Defining primitives (Java)

+

The reason I'm using the name primitive comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special +name for some specific types of values:

+
+
bool    char    byte
short int long
float double
+
+

They are referred to as primitives. And relative to the other bits of Java, +they have two unique features. First, they don't have to worry about the +billion-dollar mistake; +primitives in Java can never be null. Second: they can't have instance methods. +Remember that Rust program from earlier? Java has no idea what to do with it:

+
class Main {
public static void main(String[] args) {
int x = 8;
System.out.println(x.toString()); // Triggers a compiler error
}
}
+

The error is:

+
Main.java:5: error: int cannot be dereferenced
System.out.println(x.toString());
^
1 error
+

Specifically, Java's Object +and things that inherit from it are pointers under the hood, and we have to dereference them before +the fields and methods they define can be used. In contrast, primitive types are just values - +there's nothing to be dereferenced. In memory, they're just a sequence of bits.

+

If we really want, we can turn the int into an +Integer and then dereference +it, but it's a bit wasteful:

+
class Main {
public static void main(String[] args) {
int x = 8;
Integer y = Integer.valueOf(x);
System.out.println(y.toString());
}
}
+

This creates the variable y of type Integer (which inherits Object), and at run time we +dereference y to locate the toString() function and call it. Rust obviously handles things a bit +differently, but we have to dig into the low-level details to see it in action.

+

Low Level Handling of Primitives (C)

+

We first need to build a foundation for reading and understanding the assembly code the final answer +requires. Let's begin with showing how the C language (and your computer) thinks about "primitive" +values in memory:

+
void my_function(int num) {}

int main() {
int x = 8;
my_function(x);
}
+

The compiler explorer gives us an easy way of showing off the +assembly-level code that's generated: whose output has been lightly +edited

+
main:
push rbp
mov rbp, rsp
sub rsp, 16

; We assign the value `8` to `x` here
mov DWORD PTR [rbp-4], 8

; And copy the bits making up `x` to a location
; `my_function` can access (`edi`)
mov eax, DWORD PTR [rbp-4]
mov edi, eax

; Call `my_function` and give it control
call my_function

mov eax, 0
leave
ret

my_function:
push rbp
mov rbp, rsp

; Copy the bits out of the pre-determined location (`edi`)
; to somewhere we can use
mov DWORD PTR [rbp-4], edi
nop

pop rbp
ret
+

At a really low level of memory, we're copying bits around using the mov instruction; +nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C +to Rust:

+
fn my_function(x: i32) {}

fn main() {
let x = 8;
my_function(x)
}
+

And the assembly generated when we stick it in the +compiler explorer: again, lightly +edited

+
example::main:
push rax

; Look familiar? We're copying bits to a location for `my_function`
; The compiler just optimizes out holding `x` in memory
mov edi, 8

; Call `my_function` and give it control
call example::my_function

pop rax
ret

example::my_function:
sub rsp, 4

; And copying those bits again, just like in C
mov dword ptr [rsp], edi

add rsp, 4
ret
+

The generated Rust assembly is functionally pretty close to the C assembly: When working with +primitives, we're just dealing with bits in memory.

+

In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to +dereference. So what exactly is going on with this .to_string() function call?

+

impl primitive (and Python)

+

Now it's time to reveal my trap card show the revelation that tied all this +together: Rust has implementations for its primitive types. That's right, impl blocks aren't +only for structs and traits, primitives get them too. Don't believe me? Check out +u32, +f64 and +char as examples.

+

But the really interesting bit is how Rust turns those impl blocks into assembly. Let's break out +the compiler explorer once again:

+
pub fn main() {
8.to_string()
}
+

And the interesting bits in the assembly: heavily trimmed down

+
example::main:
sub rsp, 24
mov rdi, rsp
lea rax, [rip + .Lbyte_str.u]
mov rsi, rax

; Cool stuff right here
call <T as alloc::string::ToString>::to_string@PLT

mov rdi, rsp
call core::ptr::drop_in_place
add rsp, 24
ret
+

Now, this assembly is a bit more complicated, but here's the big revelation: we're calling +to_string() as a function that exists all on its own, and giving it the instance of 8. Instead +of thinking of the value 8 as an instance of u32 and then peeking in to find the location of the +function we want to call (like Java), we have a function that exists outside of the instance and +just give that function the value 8.

+

This is an incredibly technical detail, but the interesting idea I had was this: if to_string() +is a static function, can I refer to the unbound function and give it an instance?

+

Better explained in code (and a compiler explorer link because I +seriously love this thing):

+
struct MyVal {
x: u32
}

impl MyVal {
fn to_string(&self) -> String {
self.x.to_string()
}
}

pub fn main() {
let my_val = MyVal { x: 8 };

// THESE ARE THE SAME
my_val.to_string();
MyVal::to_string(&my_val);
}
+

Rust is totally fine "binding" the function call to the instance, and also as a static.

+

MIND == BLOWN.

+

Python does the same thing where I can both call functions bound to their instances and also call as +an unbound function where I give it the instance:

+
class MyClass():
x = 24

def my_function(self):
print(self.x)

m = MyClass()

m.my_function()
MyClass.my_function(m)
+

And Python tries to make you think that primitives can have instance methods...

+
>>> dir(8)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
'__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__',
...
'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__',
...]

>>> # Theoretically `8.__str__()` should exist, but:

>>> 8.__str__()
File "<stdin>", line 1
8.__str__()
^
SyntaxError: invalid syntax

>>> # It will run if we assign it first though:
>>> x = 8
>>> x.__str__()
'8'
+

...but in practice it's a bit complicated.

+

So while Python handles binding instance methods in a way similar to Rust, it's still not able to +run the example we started with.

+

Conclusion

+

This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor +details like primitives leads to really cool effects. Primitives are optimized like C in how they +have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python +(like both instance and late binding).

+

And when you put it together, there are areas where Rust does cool things nobody else can; as a +quirky feature of Rust's type system, 8.to_string() is actually valid code.

+

Now go forth and fool your friends into thinking you know assembly. This is all I've got.

]]>
+
+ + <![CDATA[What I learned porting dateutil to Rust]]> + https://speice.io/2018/06/dateutil-parser-to-rust + https://speice.io/2018/06/dateutil-parser-to-rust + Mon, 25 Jun 2018 12:00:00 GMT + + I've mostly been a lurker in Rust for a while, making a couple small contributions here and there. +So launching dtparse feels like nice step towards becoming a +functioning member of society. But not too much, because then you know people start asking you to +pay bills, and ain't nobody got time for that.

+

But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you +what to do with your life (but you should totally keep reading).

+

Slow down, what?

+

OK, fine, I guess I should start with why someone would do this.

+

Dateutil is a Python library for handling dates. The +standard library support for time in Python is kinda dope, but there are a lot of extras that go +into making it useful beyond just the datetime +module. dateutil.parser specifically is code to take all the super-weird time formats people come +up with and turn them into something actually useful.

+

Date/time parsing, it turns out, is just like everything else involving +computers and +time: it +feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people +suck and this is why +we can't we have nice things. But +alas, we'll try and make contemporary art out of the rubble and give it a pretentious name like +Time.

+

A gravel mound

+
+

Time

+
+

What makes dateutil.parser great is that there's single function with a single argument that +drives what programmers interact with: +parse(timestr). +It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can +possibly do to make sense of your input" value. It doesn't expect much of you.

+

And now it's in Rust.

+

Lost in Translation

+

Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm +admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can +actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better +experiences than +this guy +who attempted the same thing for D. These are the actual take-aways:

+

When transcribing code, stay as close to the original library as possible. I'm talking about +using the same variable names, same access patterns, the whole shebang. It's way too easy to make a +couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference +manual for verbatim what your code should be means that you don't spend that long debugging +complicated logic, you're more looking for typos.

+

Also, don't use nice Rust things like enums. While +one time it worked out OK for me, +I also managed to shoot myself in the foot a couple times because dateutil stores AM/PM as a +boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In +general, writing nice code should not be a first-pass priority when you're just trying to recreate +the same functionality.

+

Exceptions are a pain. Make peace with it. Python code is just allowed to skip stack frames. So +when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out +he's not quite right, and I'm OK with that. And while +dateutil is pretty well-behaved about not skipping multiple stack frames, +130-line try-catch blocks +take a while to verify.

+

As another Python quirk, be very careful about +long nested if-elif-else blocks. +I used to think that Python's whitespace was just there to get you to format your code correctly. I +think that no longer. It's way too easy to close a block too early and have incredibly weird issues +in the logic. Make sure you use an editor that displays indentation levels so you can keep things +straight.

+

Rust macros are not free. I originally had the +main test body +wrapped up in a macro using pyo3. It took two minutes to compile. +After +moving things to a function +compile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code +to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually +functions that need to be liberated, man.

+

Finally, I really miss list comprehensions and dictionary comprehensions. As a quick comparison, +see +this dateutil code +and +the implementation in Rust. +I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be +added through macros or syntax extensions. Either way, they're expressive, save typing, and are +super-readable. Let's get more of that.

+

Using a young language

+

Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On +more than one occasion though, I've had issues navigating the Rust ecosystem.

+

What I'll call the "canonical library" is still being built. In Python, if you need datetime +parsing, you use dateutil. If you want decimal types, it's already in the +standard library. While I might've gotten away +with f64, dateutil uses decimals, and I wanted to follow the principle of staying as close to +the original library as possible. Thus began my quest to find a decimal library in Rust. What I +quickly found was summarized in a comment:

+
+

Writing a BigDecimal is easy. Writing a good BigDecimal is hard.

+

-cmr

+
+

In practice, this means that there are at least 4 +different +implementations available. +And that's a lot of decisions to worry about when all I'm thinking is "why can't +calendar reform be a thing" and I'm forced to dig +through a couple +different +threads to figure out if the library I'm look at is dead +or just stable.

+

And even when the "canonical library" exists, there's no guarantees that it will be well-maintained. +Chrono is the de facto date/time library in Rust, and just +released version 0.4.4 like two days ago. Meanwhile, +chrono-tz appears to be dead in the water even though +there are people happy to help maintain it. I +know relatively little about it, but it appears that most of the release process is automated; +keeping that up to date should be a no-brainer.

+

Trial Maintenance Policy

+

Specifically given "maintenance" being an +oft-discussed +issue, I'm going to try out the following policy to keep things moving on dtparse:

+
    +
  1. +

    Issues/PRs needing maintainer feedback will be updated at least weekly. I want to make sure +nobody's blocking on me.

    +
  2. +
  3. +

    To keep issues/PRs needing contributor feedback moving, I'm going to (kindly) ask the +contributor to check in after two weeks, and close the issue without resolution if I hear nothing +back after a month.

    +
  4. +
+

The second point I think has the potential to be a bit controversial, so I'm happy to receive +feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm +running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And +second: I don't mind keeping those requests going indefinitely. I just want to try and balance +keeping things moving with giving people the necessary time they need.

+

I should also note that I'm still getting some best practices in place - CONTRIBUTING and +CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are +perfect.

+

Roadmap and Conclusion

+

So if I've now built a dateutil-compatible parser, we're done, right? Of course not! That's not +nearly ambitious enough.

+

Ultimately, I'd love to have a library that's capable of parsing everything the Linux date command +can do (and not date on OSX, because seriously, BSD coreutils are the worst). I know Rust has a +coreutils rewrite going on, and dtparse would potentially be an interesting candidate since it +doesn't bring in a lot of extra dependencies. humantime +could help pick up some of the (current) slack in dtparse, so maybe we can share and care with each +other?

+

All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month +on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going +to take it hard.

+

And in the mean time, I'm looking forward to building more. Onwards.

]]>
+
+ + <![CDATA[Hello!]]> + https://speice.io/2018/05/hello + https://speice.io/2018/05/hello + Mon, 28 May 2018 12:00:00 GMT + + I'll do what I can to keep this short, there's plenty of other things we both should be doing right +now.

+

If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you +covered:

+

Saturday Bread

+

And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven.

+

Okay, just one:

+

Bread as rock

+

Thanks, and keep it amazing.

]]>
+
+ + <![CDATA[Captain's Cookbook: Practical usage]]> + https://speice.io/2018/01/captains-cookbook-part-2 + https://speice.io/2018/01/captains-cookbook-part-2 + Tue, 16 Jan 2018 13:00:00 GMT + + A look at more practical usages of Cap'N Proto

+

Part 1 of this series took a look at a basic starting project +with Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty +basic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's +some documentation surrounding practical usage of the library.

+

As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps +here. Our current example is going to build on +the code we wrote there; after the deserialization step, we'll try and send the point_reader to a separate thread +for verification.

+

I'm going to walk through the attempts as I made them and my thinking throughout. +If you want to skip to the final project, check out the code available here

+

Attempt 1: Move the reference

+

As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from
// somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// By using `point_reader` inside the new thread, we're hoping that Rust can
// safely move the reference and invalidate the original thread's usage.
// Since the original thread doesn't use `point_reader` again, this should
// be safe, right?
let handle = std::thread:spawn(move || {

assert_eq!(point_reader.get_x(), 12);

assert_eq!(point_reader.get_y(), 14);
});

handle.join().unwrap()
}
+

Well, the Rust compiler doesn't really like this. We get four distinct errors back:

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`                                                                                                                
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]`
--> src/main.rs:31:18
|
31 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating. +Pay attention to the text that keeps on getting repeated though: XYZ cannot be sent between threads safely.

+

This is a bit frustrating: we own the buffer from which all the content was derived, and we don't have any +unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility +of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust +preventing us from doing something that really should be legal?

+

This is what is known as fighting the borrow checker. +Let our crusade begin.

+

Attempt 2: Put the Reader in a Box

+

The Box type allows us to convert a pointer we have +(in our case the point_reader) into an "owned" value, which should be easier to send across threads. +Our next attempt looks something like this:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content
// from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

let boxed_reader = Box::new(point_reader);

// Now that the reader is `Box`ed, we've proven ownership, and Rust can
// move the ownership to the new thread, right?
let handle = std::thread::spawn(move || {

assert_eq!(boxed_reader.get_x(), 12);

assert_eq!(boxed_reader.get_y(), 14);
});

handle.join().unwrap();
}
+

Spoiler alert: still doesn't work. Same errors still show up.

+
error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`                       
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
|

error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely
|

error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely
|

error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>`
--> src/main.rs:33:18
|
33 | let handle = std::thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely
|

error: aborting due to 4 previous errors
+

Let's be a little bit smarter about the exceptions this time though. What is that +std::marker::Send thing the compiler keeps telling us about?

+

The documentation is pretty clear; Send is used to denote:

+
+

Types that can be transferred across thread boundaries.

+
+

In our case, we are seeing the error messages for two reasons:

+
    +
  1. +

    Pointers (*const u8) are not safe to send across thread boundaries. While we're nice in our code +making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make +that assumption, and so complains that we're not using this in a safe manner.

    +
  2. +
  3. +

    The point_capnp::point::Reader type is itself not safe to send across threads because it doesn't +implement the Send trait. Which is to say, the things that make up a Reader are themselves not thread-safe, +so the Reader is also not thread-safe.

    +
  4. +
+

So, how are we to actually transfer a parsed Cap'N Proto message between threads?

+

Attempt 3: The TypedReader

+

The TypedReader is a new API implemented in the Cap'N Proto Rust code. +We're interested in it here for two reasons:

+
    +
  1. +

    It allows us to define an object where the object owns the underlying data. In previous attempts, +the current context owned the data, but the Reader itself had no such control.

    +
  2. +
  3. +

    We can compose the TypedReader using objects that are safe to Send across threads, guaranteeing +that we can transfer parsed messages across threads.

    +
  4. +
+

The actual type info for the TypedReader +is a bit complex. And to be honest, I'm still really not sure what the whole point of the +PhantomData thing is either. +My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto +message represents. That is, technically the only thing we're storing is the untyped binary message; +PhantomData just enforces the principle that the binary represents some specific object that has been parsed.

+

Either way, we can carefully construct something which is safe to move between threads:

+
fn main() {

// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else

let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> =
capnp::message::TypedReader::new(deserialized);

// Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message
// (which is 'static lifetime), this is now safe
let handle = std::thread::spawn(move || {

// The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader
// object from it
let point_root = point_reader.get().unwrap();

assert_eq!(point_root.get_x(), 12);

assert_eq!(point_root.get_y(), 14);
});

handle.join().unwrap();
}
+

And while we've left Rust to do the dirty work of actually moving the point_reader into the new thread, +we could also use things like mpsc channels to achieve a similar effect.

+

So now we're able to define basic Cap'N Proto messages, and send them all around our programs.

]]>
+
+ + <![CDATA[Captain's Cookbook: Project setup]]> + https://speice.io/2018/01/captains-cookbook-part-1 + https://speice.io/2018/01/captains-cookbook-part-1 + Tue, 16 Jan 2018 12:00:00 GMT + + A basic introduction to getting started with Cap'N Proto.

+

I've been working a lot with Cap'N Proto recently with Rust, but there's a real dearth of information +on how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's +fantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going.

+

So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with Protobuf +and FlatBuffers, but is better compared with FlatBuffers. The whole point behind it +is to define a schema language and serialization format such that:

+
    +
  1. Applications that do not share the same base programming language can communicate
  2. +
  3. The data and schema you use can naturally evolve over time as your needs change
  4. +
+

Accompanying this are typically code generators that take the schemas you define for your application and give you back +code for different languages to get data to and from that schema.

+

Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way +as is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.

+

We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some +examples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects. +If you want to follow along, feel free. If not, I've posted the final result +for reference.

+

Step 1: Installing capnp

+

The capnp binary itself is needed for taking the schema files you write and turning them into a format that can be used by the +code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed.

+

I'll refer you to Cap'N Proto's installation instructions here. As a quick TLDR though:

+
    +
  • Linux users will likely have a binary shipped by their package manager - On Ubuntu, apt install capnproto is enough
  • +
  • OS X users can use Homebrew as an easy install path. Just brew install capnp
  • +
  • Windows users are a bit more complicated. If you're using Chocolatey, there's a package available. If that doesn't work however, you need to download a release zip and make sure that the capnp.exe binary is in your %PATH% environment variable
  • +
+

The way you know you're done with this step is if the following command works in your shell:

+
capnp id
+

Step 2: Starting a Cap'N Proto Rust project

+

After the capnp binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple

+
mkdir capnp_cookbook_1
cd capnp_cookbook_1
cargo init --bin
+

We'll put the following content into Cargo.toml:

+
[package]
name = "capnp_cookbook_1"
version = "0.1.0"
authors = ["Bradlee Speice <bspeice@kcg.com>"]

[build-dependencies]
capnpc = "0.8" # 1

[dependencies]
capnp = "0.8" # 2
+

This sets up:

+
    +
  1. The Rust code generator (CAPNProto Compiler)
  2. +
  3. The Cap'N Proto runtime library (CAPNProto runtime)
  4. +
+

We've now got everything prepared that we need for writing a Cap'N Proto project.

+

Step 3: Writing a basic schema

+

We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure +you get familiar with how to start from a basic project.

+

First, we're going to create a top-level directory for storing the schema files in:

+
# Assuming we're starting from the `capnp_cookbook_1` directory created earlier

mkdir schema
cd schema
+

Now, we're going to put the following content in point.capnp:

+
@0xab555145c708dad2;

struct Point {
x @0 :Int32;
y @1 :Int32;
}
+

Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format.

+

Step 4: Setting up the build process

+

Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using. +This is typically done through a build.rs file to invoke the schema compiler.

+

In the same folder as your Cargo.toml file, please put the following content in build.rs:

+
extern crate capnpc;

fn main() {
::capnpc::CompilerCommand::new()
.src_prefix("schema") // 1
.file("schema/point.capnp") // 2
.run().expect("compiling schema");
}
+

This sets up the protocol compiler (capnpc from earlier) to compile the schema we've built so far.

+
    +
  1. Because Cap'N Proto schema files can re-use types specified in other files, the src_prefix() tells the compiler +where to look for those extra files at.
  2. +
  3. We specify the schema file we're including by hand. In a much larger project, you could presumably build the CompilerCommand +dynamically, but we won't worry too much about that one for now.
  4. +
+

Step 5: Running the build

+

If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code. +Run a cargo build command, and if you don't see cargo complaining, you're doing just fine!

+

So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated +code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives +somewhere in the target/ directory.

+

The long answer is that you're best off running a find command to get the actual file path:

+
# Assuming we're running from the capnp_cookbook_1 project folder
find . -name point_capnp.rs
+

Alternately, if the find command isn't available, the path will look something like:

+
./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs
+

See if there are any paths in your target directory that look similar.

+

Now, the file content looks pretty nasty. I've included an example here +if you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how +the schema we wrote for the "Point" message is tied to the generated code.

+

First, the Cap'N Proto library splits things up into Builder and Reader structs. These are best thought of the same way +Rust separates mut from non-mut code. Builders are mut versions of your message, and Readers are immutable versions.

+

For example, the Builder impl for point defines get_x(), set_x(), get_y(), and set_y() methods. +In comparison, the Reader impl only defines get_x() and get_y() methods.

+

So now we know that there are some get and set methods available for our x and y coordinates; +but what do we actually do with those?

+

Step 6: Making a point

+

So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building +Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code +should go in src/main.rs:

+
// Note that we use `capnp` here, NOT `capnpc`
extern crate capnp;

// We create a module here to define how we are to access the code
// being included.
pub mod point_capnp {
// The environment variable OUT_DIR is set by Cargo, and
// is the location of all the code that was built as part
// of the codegen step.
// point_capnp.rs is the actual file to include
include!(concat!(env!("OUT_DIR"), "/point_capnp.rs"));
}

fn main() {

// The process of building a Cap'N Proto message is a bit tedious.
// We start by creating a generic Builder; it acts as the message
// container that we'll later be filling with content of our `Point`
let mut builder = capnp::message::Builder::new_default();

// Because we need a mutable reference to the `builder` later,
// we fence off this part of the code to allow sequential mutable
// borrows. As I understand it, non-lexical lifetimes:
// https://github.com/rust-lang/rust-roadmap/issues/16
// will make this no longer necessary
{
// And now we can set up the actual message we're trying to create
let mut point_msg = builder.init_root::<point_capnp::point::Builder>();

// Stuff our message with some content
point_msg.set_x(12);

point_msg.set_y(14);
}

// It's now time to serialize our message to binary. Let's set up a buffer for that:
let mut buffer = Vec::new();

// And actually fill that buffer with our data
capnp::serialize::write_message(&mut buffer, &builder).unwrap();

// Finally, let's deserialize the data
let deserialized = capnp::serialize::read_message(
&mut buffer.as_slice(),
capnp::message::ReaderOptions::new()
).unwrap();

// `deserialized` is currently a generic reader; it understands
// the content of the message we gave it (i.e. that there are two
// int32 values) but doesn't really know what they represent (the Point).
// This is where we map the generic data back into our schema.
let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap();

// We can now get our x and y values back, and make sure they match
assert_eq!(point_reader.get_x(), 12);
assert_eq!(point_reader.get_y(), 14);
}
+

And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up +some practical examples of Cap'N Proto in action:

]]>
+
+
+
\ No newline at end of file diff --git a/rss.xsl b/rss.xsl new file mode 100644 index 0000000..e9695b2 --- /dev/null +++ b/rss.xsl @@ -0,0 +1,86 @@ + + + + + + + + RSS Feed | <xsl:value-of select="rss/channel/title" /> + + + +
+
+
+ This is an RSS feed. Subscribe by copying the URL + from the address bar into your newsreader. Visit + About Feeds to learn more + and get started. It’s free. +
+

+
+ + + + + + + + + + +
+ +

+

+ +

+
+

Recent Posts

+
+ +
+

+ +
+ +
+
+
+
+
+ + +
+
diff --git a/search-doc-1731274975527.json b/search-doc-1731274975527.json new file mode 100644 index 0000000..6825e18 --- /dev/null +++ b/search-doc-1731274975527.json @@ -0,0 +1 @@ +{"searchDocs":[{"title":"The webpack industrial complex","type":0,"sectionRef":"#","url":"/2011/11/webpack-industrial-complex","content":"","keywords":"","version":null},{"title":"Starting strong​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#starting-strong","content":" The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser." Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an onEvent handler and a function easy. Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical." ","version":null,"tagName":"h2"},{"title":"Continuing on​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#continuing-on","content":" Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead? The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API was missing. After searching out Github issues and (unsuccessfully) tweaking the .tsconfig settings, I settled on installing a package and moving on. The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use new URL(<local path>, import.meta.url) and it worked! Well, kind of: That file has the audio processor code, so why does it get served with Content-Type: video/mp2t? ","version":null,"tagName":"h2"},{"title":"Floundering about​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#floundering-about","content":" Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to just use JavaScript and stuck by the original TypeScript requirement. I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package. I tried three different CRA tools - react-app-rewired, craco, customize-react-app - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well. I tried changing the webpack configuration: using new loaders, setting asset rules, even changing how webpack detects worker resources. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up. I tried so many application frameworks. Next.js looked like a good candidate, but added its own bespoke webpack complexity to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work. ","version":null,"tagName":"h2"},{"title":"Learning and reflecting​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#learning-and-reflecting","content":" I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned. For myself: I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important workI tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts For the tools: Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexityWebpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaksThere's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down. ","version":null,"tagName":"h2"},{"title":"Autocallable Bonds","type":0,"sectionRef":"#","url":"/2015/11/autocallable","content":"","keywords":"","version":null},{"title":"Underlying simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#underlying-simulation","content":" In order to price the autocallable bonds, we need to simulate the underlying assets. Let's go ahead and set up the simulation first, as this lays the foundation for what we're trying to do. We're going to use JNJ as the basis for our simulation. This implies the following parameters: S0S_0S0​ = $102.2 (as of time of writing)qqq = 2.84%rrr = [.49, .9, 1.21, 1.45, 1.69] (term structure as of time of writing, linear interpolation)μ\\muμ = r−qr - qr−q (note that this implies a negative drift because of current low rates)σ\\sigmaσ = σimp\\sigma_{imp}σimp​ = 15.62% (from VIX implied volatility) We additionally define some parameters for simulation: T: The number of years to simulatem: The number of paths to simulaten: The number of steps to simulate in a year S0 = 102.2 nominal = 100 q = 2.84 / 100 σ = 15.37 / 100 term = [0, .49, .9, 1.21, 1.45, 1.69] / 100 + 1 ### # Potential: Based on PEP # S0 = 100.6 # σ = 14.86 # q = 2.7 ### # Simulation parameters T = 5 # Using years as the unit of time n = 250 # simulations per year m = 100000 # paths num_simulations = 5; # simulation rounds per price ","version":null,"tagName":"h2"},{"title":"Defining the simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#defining-the-simulation","content":" To make things simpler, we simulate a single year at a time. This allows us to easily add in a dividend policy without too much difficulty, and update the simulation every year to match the term structure. The underlying uses GBM for simulation between years. simulate_gbm = function(S0, μ, σ, T, n) # Set the initial state m = length(S0) t = T / n motion = zeros(m, n) motion[:,1] = S0 # Build out all states for i=1:(n-1) motion[:,i+1] = motion[:,i] .* exp((μ - σ^2/2)*t) .* exp(sqrt(t) * σ .* randn(m)) end return motion end function display_motion(motion, T) # Given a matrix of paths, display the motion n = length(motion[1,:]) m = length(motion[:,1]) x = repmat(1:n, m) # Calculate the ticks we're going to use. We'd like to # have an xtick every month, so calculate where those # ticks will actually be at. if (T > 3) num_ticks = T xlabel = "Years" else num_ticks = T * 12 xlabel = "Months" end tick_width = n / num_ticks x_ticks = [] for i=1:round(num_ticks) x_ticks = vcat(x_ticks, i*tick_width) end # Use one color for each path. I'm not sure if there's # a better way to do this without going through DataFrames colors = [] for i = 1:m colors = vcat(colors, ones(n)*i) end plot(x=x, y=motion', color=colors, Geom.line, Guide.xticks(ticks=x_ticks, label=false), Guide.xlabel(xlabel), Guide.ylabel("Value")) end; ","version":null,"tagName":"h3"},{"title":"Example simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#example-simulation","content":" Let's go ahead and run a sample simulation to see what the functions got us! initial = ones(5) * S0 # Using μ=0, T=.25 for now, we'll use the proper values later motion = simulate_gbm(initial, 0, σ, .25, 200) display_motion(motion, .25) ","version":null,"tagName":"h3"},{"title":"Computing the term structure​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#computing-the-term-structure","content":" Now that we've got the basic motion set up, let's start making things a bit more sophisticated for the model. We're going to assume that the drift of the stock is the difference between the implied forward rate and the quarterly dividend rate. We're given the yearly term structure, and need to calculate the quarterly forward rate to match this structure. The term structure is assumed to follow: d(0,t)=d(0,t−1)⋅fi−1,id(0, t) = d(0,t-1)\\cdot f_{i-1, i}d(0,t)=d(0,t−1)⋅fi−1,i​ Where fi−1,if_{i-1, i}fi−1,i​ is the quarterly forward rate. forward_term = function(yearly_term) # It is assumed that we have a yearly term structure passed in, and starts at year 0 # This implies a nominal rate above 0 for the first year! years = length(term)-1 # because we start at 0 structure = [(term[i+1] / term[i]) for i=1:years] end; ","version":null,"tagName":"h3"},{"title":"Illustrating the term structure​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#illustrating-the-term-structure","content":" Now that we've got our term structure, let's validate that we're getting the correct results! If we've done this correctly, then: term[2] == term[1] * structure[1] # Example term structure taken from: # http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield # Linear interpolation used years in-between periods, assuming real-dollar # interest rates forward_yield = forward_term(term) calculated_term2 = term[1] * forward_yield[1] println("Actual term[2]: $(term[2]); Calculated term[2]: $(calculated_term2)") Actual term[2]: 1.0049; Calculated term[2]: 1.0049 ","version":null,"tagName":"h3"},{"title":"The full underlying simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#the-full-underlying-simulation","content":" Now that we have the term structure set up, we can actually start doing some real simulation! Let's construct some paths through the full 5-year time frame. In order to do this, we will simulate 1 year at a time, and use the forward rates at those times to compute the drift. Thus, there will be 5 total simulations batched together. full_motion = ones(5) * S0 full_term = vcat(term[1], forward_yield) for i=1:T μ = (full_term[i] - 1 - q) year_motion = simulate_gbm(full_motion[:,end], μ, σ, 1, n) full_motion = hcat(full_motion, year_motion) end display_motion(full_motion, T) ","version":null,"tagName":"h3"},{"title":"Final simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#final-simulation","content":" We're now going to actually build out the full motion that we'll use for computing the pricing of our autocallable products. It will be largely the same, but we will use far more sample paths for the simulation. full_simulation = function(S0, T, n, m, term) forward = vcat(term[1], forward_term(term)) # And an S0 to kick things off. final_motion = ones(m) * S0 for i=1:T μ = (forward[i] - 1 - q) year_motion = simulate_gbm(final_motion[:,end], μ, σ, 1, n) final_motion = hcat(final_motion, year_motion) end return final_motion end tic() full_simulation(S0, T, n, m, term) time = toq() @printf("Time to run simulation: %.2fs", time) Time to run simulation: 5.34s ","version":null,"tagName":"h3"},{"title":"Athena Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#athena-simulation","content":" Now that we've defined our underlying simulation, let's actually try and price an Athena note. Athena has the following characteristics: Automatically called if the underlying is above the call barrier at observationAccelerated coupon paid if the underlying is above the call barrier at observation The coupon paid is c⋅ic \\cdot ic⋅i with iii as the current year, and ccc the coupon rate Principle protection up until a protection barrier at observation; All principle at risk if this barrier not metObserved yearly call_barrier = S0 strike = S0 protection_barrier = S0 * .6 coupon = nominal * .07 price_athena = function(initial_price, year_prices, call_barrier, protection_barrier, coupon, forward_structure) total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price ≥ call_barrier return (nominal + coupon*i) * exp((prod(forward_structure[i:end])-1)*(t-i)) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_athena(S0, year_prices, call_barrier, protection_barrier, coupon, forward_structure) athena = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = athena() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * (exp(-(prod(forward_structure)-1)*T)) @printf("Present value of Athena note: \\$%.2f, notional: \\$%.2f", pv, nominal) Mean of simulation 1: $103.2805; Simulation time: 5.59s Mean of simulation 2: $103.3796; Simulation time: 5.05s Mean of simulation 3: $103.4752; Simulation time: 5.18s Mean of simulation 4: $103.4099; Simulation time: 5.37s Mean of simulation 5: $103.3260; Simulation time: 5.32s Mean over 5 simulations: 103.37421610015554 Present value of Athena note: $95.00, notional: $100.00 ","version":null,"tagName":"h2"},{"title":"Phoenix without Memory Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#phoenix-without-memory-simulation","content":" Let's move into pricing a Phoenix without memory. It's very similar to the Athena production, with the exception that we introduce a coupon barrier so coupons are paid even when the underlying is below the initial price. The Phoenix product has the following characteristics (example here): Automatically called if the underlying is above the call barrier at observationCoupon paid if the underlying is above a coupon barrier at observationPrinciple protection up until a protection barrier at observation; All principle at risk if this barrier not metObserved yearly Some example paths (all assume that a call barrier of the current price, and coupon barrier some level below that): At the end of year 1, the stock is above the call barrier; the note is called and you receive the value of the stock plus the coupon being paid.At the end of year 1, the stock is above the coupon barrier, but not the call barrier; you receive the coupon. At the end of year 2, the stock is below the coupon barrier; you receive nothing. At the end of year 3, the stock is above the call barrier; the note is called and you receive the value of the stock plus a coupon for year 3. We're going to re-use the same simulation, with the following parameters: Call barrier: 100%Coupon barrier: 70%Coupon: 6%Capital protection until 70% (at maturity) call_barrier = S0 coupon_barrier = S0 * .8 protection_barrier = S0 * .6 coupon = nominal * .06 price_phoenix_no_memory = function(initial_price, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price ≥ call_barrier return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i)) elseif price ≥ coupon_barrier total_coupons = total_coupons * exp(forward_structure[i]-1) + coupon else total_coupons *= exp(forward_structure[i]-1) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal + total_coupons else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_phoenix_no_memory(S0, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) phoenix_no_memory = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = phoenix_no_memory() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * exp(-(prod(forward_structure)-1)*(T)) @printf("Present value of Phoenix without memory note: \\$%.2f", pv) Mean of simulation 1: $106.0562; Simulation time: 5.72s Mean of simulation 2: $106.0071; Simulation time: 5.85s Mean of simulation 3: $105.9959; Simulation time: 5.87s Mean of simulation 4: $106.0665; Simulation time: 5.93s Mean of simulation 5: $106.0168; Simulation time: 5.81s Mean over 5 simulations: 106.02850857209883 Present value of Phoenix without memory note: $97.44 ","version":null,"tagName":"h2"},{"title":"Phoenix with Memory Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#phoenix-with-memory-simulation","content":" The Phoenix with Memory structure is very similar to the Phoenix, but as the name implies, has a special "memory" property: It remembers any coupons that haven't been paid at prior observation times, and pays them all if the underlying crosses the coupon barrier. For example: Note issued with 100% call barrier, 70% coupon barrier. At year 1, the underlying is at 50%, so no coupons are paid. At year 2, the underlying is at 80%, so coupons for both year 1 and 2 are paid, resulting in a double coupon. You can also find an example here. Let's go ahead and set up the simulation! The parameters will be the same, but we can expect that the value will go up because of the memory attribute call_barrier = S0 coupon_barrier = S0 * .8 protection_barrier = S0 * .6 coupon = nominal * .07 price_phoenix_with_memory = function(initial_price, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) last_coupon = 0 total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price > call_barrier return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i)) elseif price > coupon_barrier #################################################################### # The only difference between with/without memory is the below lines memory_coupons = (i - last_coupon) * coupon last_coupon = i total_coupons = total_coupons * exp(forward_structure[i]-1) + memory_coupons #################################################################### else total_coupons *= exp(forward_structure[i]-1) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal + total_coupons else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_phoenix_with_memory(S0, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) phoenix_with_memory = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = phoenix_with_memory() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * exp(-(prod(forward_structure)-1)*(T)) @printf("Present value of Phoenix with memory note: \\$%.2f", pv) Mean of simulation 1: $108.8612; Simulation time: 5.89s Mean of simulation 2: $109.0226; Simulation time: 5.90s Mean of simulation 3: $108.9175; Simulation time: 5.92s Mean of simulation 4: $108.9426; Simulation time: 5.94s Mean of simulation 5: $108.8087; Simulation time: 6.06s Mean over 5 simulations: 108.91052564051816 Present value of Phoenix with memory note: $100.09 ","version":null,"tagName":"h2"},{"title":"Welcome, and an algorithm","type":0,"sectionRef":"#","url":"/2015/11/welcome","content":"","keywords":"","version":null},{"title":"Trading Competition Optimization​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#trading-competition-optimization","content":" Goal: Max return given maximum Sharpe and Drawdown from IPython.display import display import Quandl from datetime import datetime, timedelta tickers = ['XOM', 'CVX', 'CLB', 'OXY', 'SLB'] market_ticker = 'GOOG/NYSE_VOO' lookback = 30 d_col = 'Close' data = {tick: Quandl.get('YAHOO/{}'.format(tick))[-lookback:] for tick in tickers} market = Quandl.get(market_ticker) ","version":null,"tagName":"h2"},{"title":"Calculating the Return​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-return","content":" We first want to know how much each ticker returned over the prior period. returns = {tick: data[tick][d_col].pct_change() for tick in tickers} display({tick: returns[tick].mean() for tick in tickers}) {'CLB': -0.0016320202164526894, 'CVX': 0.0010319531629488911, 'OXY': 0.00093418904454400551, 'SLB': 0.00098431254720448159, 'XOM': 0.00044165797556096868} ","version":null,"tagName":"h2"},{"title":"Calculating the Sharpe ratio​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-sharpe-ratio","content":" Sharpe: R−RMσ{R - R_M \\over \\sigma}σR−RM​​ We use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive. market_returns = market.pct_change() sharpe = lambda ret: (ret.mean() - market_returns[d_col].mean()) / ret.std() sharpes = {tick: sharpe(returns[tick]) for tick in tickers} display(sharpes) {'CLB': -0.10578734457846127, 'CVX': 0.027303529817677398, 'OXY': 0.022622210057414487, 'SLB': 0.026950946344858676, 'XOM': -0.0053519259698605499} ","version":null,"tagName":"h2"},{"title":"Calculating the drawdown​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-drawdown","content":" This one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change? drawdown = lambda ret: ret.abs().max() drawdowns = {tick: drawdown(returns[tick]) for tick in tickers} display(drawdowns) {'CLB': 0.043551495607375035, 'CVX': 0.044894389686214398, 'OXY': 0.051424517867144637, 'SLB': 0.034774627850375328, 'XOM': 0.035851524605672758} Performing the optimization max μ⋅ωs.t. 1⃗ω=1S⃗ω≥sD⃗⋅∣ω∣≤d∣ω∣≤l\\begin{align*} max\\ \\ & \\mu \\cdot \\omega\\\\ s.t.\\ \\ & \\vec{1} \\omega = 1\\\\ & \\vec{S} \\omega \\ge s\\\\ & \\vec{D} \\cdot | \\omega | \\le d\\\\ & \\left|\\omega\\right| \\le l\\\\ \\end{align*}max s.t. ​μ⋅ω1ω=1Sω≥sD⋅∣ω∣≤d∣ω∣≤l​ We want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don't have huge long/short positions. import numpy as np from scipy.optimize import minimize #sharpe_limit = .1 drawdown_limit = .05 leverage = 250 # Use the map so we can guarantee we maintain the correct order # So we can write as upper-bound # sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1 dd_a = np.array(list(map(lambda tick: drawdowns[tick], tickers))) # Because minimizing returns_a = np.array(list(map(lambda tick: returns[tick].mean(), tickers))) meets_sharpe = lambda x: sum(abs(x) * sharpe_a) - sharpe_limit def meets_dd(x): portfolio = sum(abs(x)) if portfolio < .1: # If there are no stocks in the portfolio, # we can accidentally induce division by 0, # or division by something small enough to cause infinity return 0 return drawdown_limit - sum(abs(x) * dd_a) / sum(abs(x)) is_portfolio = lambda x: sum(x) - 1 def within_leverage(x): return leverage - sum(abs(x)) objective = lambda x: sum(x * returns_a) * -1 # Because we're minimizing bounds = ((None, None),) * len(tickers) x = np.zeros(len(tickers)) constraints = [ { 'type': 'eq', 'fun': is_portfolio }, { 'type': 'ineq', 'fun': within_leverage #}, { # 'type': 'ineq', # 'fun': meets_sharpe }, { 'type': 'ineq', 'fun': meets_dd } ] optimal = minimize(objective, x, bounds=bounds, constraints=constraints, options={'maxiter': 500}) # Optimization time! display(optimal.message) display("Holdings: {}".format(list(zip(tickers, optimal.x)))) # multiply by -100 to scale, and compensate for minimizing expected_return = optimal.fun * -100 display("Expected Return: {:.3f}%".format(expected_return)) expected_drawdown = sum(abs(optimal.x) * dd_a) / sum(abs(optimal.x)) * 100 display("Expected Max Drawdown: {0:.2f}%".format(expected_drawdown)) # TODO: Calculate expected Sharpe 'Optimization terminated successfully.' "Holdings: [('XOM', 5.8337945679814904), ('CVX', 42.935064321851307), ('CLB', -124.5), ('OXY', 36.790387773552119), ('SLB', 39.940753336615096)]" 'Expected Return: 32.375%' 'Expected Max Drawdown: 4.34%' ","version":null,"tagName":"h2"},{"title":"Testing Cramer","type":0,"sectionRef":"#","url":"/2015/12/testing-cramer","content":"","keywords":"","version":null},{"title":"Downloading Futures data from Seeking Alpha​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#downloading-futures-data-from-seeking-alpha","content":" We're going to define two HTML parsing classes - one to get the article URL's from a page, and one to get the actual data from each article. class ArticleListParser(HTMLParser): """Given a web page with articles on it, parse out the article links""" articles = [] def handle_starttag(self, tag, attrs): #if tag == 'div' and ("id", "author_articles_wrapper") in attrs: # self.fetch_links = True if tag == 'a' and ('class', 'dashboard_article_link') in attrs: href = list(filter(lambda x: x[0] == 'href', attrs))[0][1] self.articles.append(href) base_url = "http://seekingalpha.com/author/wall-street-breakfast/articles" article_page_urls = [base_url] + [base_url + '/{}'.format(i) for i in range(2, 20)] global_articles = [] for page in article_page_urls: # We need to switch the user agent, as SA blocks the standard requests agent articles_html = requests.get(page, headers={"User-Agent": "Wget/1.13.4"}) parser = ArticleListParser() parser.feed(articles_html.text) global_articles += (parser.articles) class ArticleReturnParser(HTMLParser): "Given an article, parse out the futures returns in it" record_font_tags = False in_font_tag = False counter = 0 # data = {} # See __init__ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = {} def handle_starttag(self, tag, attrs): if tag == 'span' and ('itemprop', 'datePublished') in attrs: date_string = list(filter(lambda x: x[0] == 'content', attrs))[0][1] date = dtparser.parse(date_string) self.data['date'] = date self.in_font_tag = tag == 'font' def safe_float(self, string): try: return float(string[:-1]) / 100 except ValueError: return np.NaN def handle_data(self, content): if not self.record_font_tags and "Futures at 6" in content: self.record_font_tags = True if self.record_font_tags and self.in_font_tag: if self.counter == 0: self.data['DOW'] = self.safe_float(content) elif self.counter == 1: self.data['S&P'] = self.safe_float(content) elif self.counter == 2: self.data['NASDAQ'] = self.safe_float(content) elif self.counter == 3: self.data['Crude'] = self.safe_float(content) elif self.counter == 4: self.data['Gold'] = self.safe_float(content) self.counter += 1 def handle_endtag(self, tag): self.in_font_tag = False def retrieve_data(url): sa = "http://seekingalpha.com" article_html = requests.get(sa + url, headers={"User-Agent": "Wget/1.13.4"}) parser = ArticleReturnParser() parser.feed(article_html.text) parser.data.update({"url": url}) parser.data.update({"text": article_html.text}) return parser.data # This copy **MUST** be in place. I'm not sure why, # as you'd think that the data being returned would already # represent a different memory location. Even so, it blows up # if you don't do this. article_list = list(set(global_articles)) article_data = [copy(retrieve_data(url)) for url in article_list] # If there's an issue downloading the article, drop it. article_df = pd.DataFrame.from_dict(article_data).dropna() ","version":null,"tagName":"h2"},{"title":"Fetching the Returns data​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#fetching-the-returns-data","content":" Now that we have the futures data, we're going to compare across 4 different indices - the S&P 500 index, Dow Jones Industrial, Russell 2000, and NASDAQ 100. Let's get the data off of Quandl to make things easier! # article_df is sorted by date, so we get the first row. start_date = article_df.sort_values(by='date').iloc[0]['date'] - relativedelta(days=1) SPY = Quandl.get("GOOG/NYSE_SPY", trim_start=start_date) DJIA = Quandl.get("GOOG/AMS_DIA", trim_start=start_date) RUSS = Quandl.get("GOOG/AMEX_IWM", trim_start=start_date) NASDAQ = Quandl.get("GOOG/EPA_QQQ", trim_start=start_date) ","version":null,"tagName":"h2"},{"title":"Running the Comparison​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#running-the-comparison","content":" There are two types of tests I want to determine: How accurate each futures category is at predicting the index's opening change over the close before, and predicting the index's daily return. Let's first calculate how good each future is at predicting the opening return over the previous day. I expect that the futures will be more than 50% accurate, since the information is recorded 3 hours before the markets open. def calculate_opening_ret(frame): # I'm not a huge fan of the appending for loop, # but it's a bit verbose for a comprehension data = {} for i in range(1, len(frame)): date = frame.iloc[i].name prior_close = frame.iloc[i-1]['Close'] open_val = frame.iloc[i]['Open'] data[date] = (open_val - prior_close) / prior_close return data SPY_open_ret = calculate_opening_ret(SPY) DJIA_open_ret = calculate_opening_ret(DJIA) RUSS_open_ret = calculate_opening_ret(RUSS) NASDAQ_open_ret = calculate_opening_ret(NASDAQ) def signs_match(list_1, list_2): # This is a surprisingly difficult task - we have to match # up the dates in order to check if opening returns actually match index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()} matches = [] for row in list_1.iterrows(): row_dt = row[1][1] row_value = row[1][0] index_dt = datetime(row_dt.year, row_dt.month, row_dt.day) if index_dt in list_2: index_value = list_2[index_dt] if (row_value > 0 and index_value > 0) or \\ (row_value < 0 and index_value < 0) or \\ (row_value == 0 and index_value == 0): matches += [1] else: matches += [0] #print("{}".format(list_2[index_dt])) return matches prediction_dict = {} matches_dict = {} count_dict = {} index_dict = {"SPY": SPY_open_ret, "DJIA": DJIA_open_ret, "RUSS": RUSS_open_ret, "NASDAQ": NASDAQ_open_ret} indices = ["SPY", "DJIA", "RUSS", "NASDAQ"] futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"] for index in indices: matches_dict[index] = {future: signs_match(article_df[[future, 'date']], index_dict[index]) for future in futures} count_dict[index] = {future: len(matches_dict[index][future]) for future in futures} prediction_dict[index] = {future: np.mean(matches_dict[index][future]) for future in futures} print("Articles Checked: ") print(pd.DataFrame.from_dict(count_dict)) print() print("Prediction Accuracy:") print(pd.DataFrame.from_dict(prediction_dict)) Articles Checked: DJIA NASDAQ RUSS SPY Crude 268 268 271 271 DOW 268 268 271 271 Gold 268 268 271 271 NASDAQ 268 268 271 271 S&P 268 268 271 271 Prediction Accuracy: DJIA NASDAQ RUSS SPY Crude 0.544776 0.522388 0.601476 0.590406 DOW 0.611940 0.604478 0.804428 0.841328 Gold 0.462687 0.455224 0.464945 0.476015 NASDAQ 0.615672 0.608209 0.797048 0.830258 S&P 0.604478 0.597015 0.811808 0.848708 This data is very interesting. Some insights: Both DOW and NASDAQ futures are pretty bad at predicting their actual market openingsNASDAQ and Dow are fairly unpredictable; Russell 2000 and S&P are very predictableGold is a poor predictor in general - intuitively Gold should move inverse to the market, but it appears to be about as accurate as a coin flip. All said though it appears that futures data is important for determining market direction for both the S&P 500 and Russell 2000. Cramer is half-right: futures data isn't very helpful for the Dow and NASDAQ indices, but is great for the S&P and Russell indices. ","version":null,"tagName":"h2"},{"title":"The next step - Predicting the close​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#the-next-step---predicting-the-close","content":" Given the code we currently have, I'd like to predict the close of the market as well. We can re-use most of the code, so let's see what happens: def calculate_closing_ret(frame): # I'm not a huge fan of the appending for loop, # but it's a bit verbose for a comprehension data = {} for i in range(0, len(frame)): date = frame.iloc[i].name open_val = frame.iloc[i]['Open'] close_val = frame.iloc[i]['Close'] data[date] = (close_val - open_val) / open_val return data SPY_close_ret = calculate_closing_ret(SPY) DJIA_close_ret = calculate_closing_ret(DJIA) RUSS_close_ret = calculate_closing_ret(RUSS) NASDAQ_close_ret = calculate_closing_ret(NASDAQ) def signs_match(list_1, list_2): # This is a surprisingly difficult task - we have to match # up the dates in order to check if opening returns actually match index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()} matches = [] for row in list_1.iterrows(): row_dt = row[1][1] row_value = row[1][0] index_dt = datetime(row_dt.year, row_dt.month, row_dt.day) if index_dt in list_2: index_value = list_2[index_dt] if (row_value > 0 and index_value > 0) or \\ (row_value < 0 and index_value < 0) or \\ (row_value == 0 and index_value == 0): matches += [1] else: matches += [0] #print("{}".format(list_2[index_dt])) return matches matches_dict = {} count_dict = {} prediction_dict = {} index_dict = {"SPY": SPY_close_ret, "DJIA": DJIA_close_ret, "RUSS": RUSS_close_ret, "NASDAQ": NASDAQ_close_ret} indices = ["SPY", "DJIA", "RUSS", "NASDAQ"] futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"] for index in indices: matches_dict[index] = {future: signs_match(article_df[[future, 'date']], index_dict[index]) for future in futures} count_dict[index] = {future: len(matches_dict[index][future]) for future in futures} prediction_dict[index] = {future: np.mean(matches_dict[index][future]) for future in futures} print("Articles Checked:") print(pd.DataFrame.from_dict(count_dict)) print() print("Prediction Accuracy:") print(pd.DataFrame.from_dict(prediction_dict)) Articles Checked: DJIA NASDAQ RUSS SPY Crude 268 268 271 271 DOW 268 268 271 271 Gold 268 268 271 271 NASDAQ 268 268 271 271 S&P 268 268 271 271 Prediction Accuracy: DJIA NASDAQ RUSS SPY Crude 0.533582 0.529851 0.501845 0.542435 DOW 0.589552 0.608209 0.535055 0.535055 Gold 0.455224 0.451493 0.483395 0.512915 NASDAQ 0.582090 0.626866 0.531365 0.538745 S&P 0.585821 0.608209 0.535055 0.535055 Well, it appears that the futures data is terrible at predicting market close. NASDAQ predicting NASDAQ is the most interesting data point, but 63% accuracy isn't accurate enough to make money consistently. ","version":null,"tagName":"h2"},{"title":"Final sentiments​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#final-sentiments","content":" The data bears out very close to what I expected would happen: Futures data is more accurate than a coin flip for predicting openings, which makes sense since it is recorded only 3 hours before the actual openingFutures data is about as acccurate as a coin flip for predicting closings, which means there is no money to be made in trying to predict the market direction for the day given the futures data. In summary: Cramer is half right: Futures data is not good for predicting the market open of the Dow and NASDAQ indices. Contrary to Cramer though, it is very good for predicting the S&P and Russell indices - we can achieve an accuracy slightly over 80% for each.Making money in the market is hard. We can't just go to the futures and treat them as an oracle for where the market will close. I hope you've enjoyed this, I quite enjoyed taking a deep dive in the analytics this way. I'll be posting more soon! ","version":null,"tagName":"h2"},{"title":"Cloudy in Seattle","type":0,"sectionRef":"#","url":"/2016/01/cloudy-in-seattle","content":"","keywords":"","version":null},{"title":"Examining other cities​","type":1,"pageTitle":"Cloudy in Seattle","url":"/2016/01/cloudy-in-seattle#examining-other-cities","content":" After taking some time to explore how the weather in North Carolina stacked up over the past years, I was interested in doing the same analysis for other cities. Growing up with family from Binghamton, NY I was always told it was very cloudy there. And Seattle has a nasty reputation for being very depressing and cloudy. All said, the cities I want to examine are: Binghamton, NYCary, NCSeattle, WANew York City, NY I'd be interested to try this analysis worldwide at some point - comparing London and Seattle might be an interesting analysis. For now though, we'll stick with trying out the US data. There will be plenty of charts. I want to know: How has average cloud cover and precipitation chance changed over the years for each city mentioned? This will hopefully tell us whether Seattle has actually earned its reputation for being a depressing city. city_forecasts = pickle.load(open('city_forecasts.p', 'rb')) forecasts_df = pd.DataFrame.from_dict(city_forecasts) cities = ['binghamton', 'cary', 'nyc', 'seattle'] city_colors = {cities[i]: Palette[i] for i in range(0, 4)} def safe_cover(frame): if frame and 'cloudCover' in frame: return frame['cloudCover'] else: return np.NaN def monthly_avg_cloudcover(city, year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(forecasts_df[city][x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below. with warnings.catch_warnings(): warnings.simplefilter('ignore') return np.nanmean(cloud_cover_vals), cloud_cover_samples years = range(1990, 2016) def city_avg_cc(city, month): return [monthly_avg_cloudcover(city, y, month) for y in years] months = [ ('July', 7), ('August', 8), ('September', 9), ('October', 10), ('November', 11) ] for month, month_id in months: month_averages = {city: city_avg_cc(city, month_id) for city in cities} f = figure(title="{} Average Cloud Cover".format(month), x_axis_label='Year', y_axis_label='Cloud Cover Percentage') for city in cities: f.line(years, [x[0] for x in month_averages[city]], legend=city, color=city_colors[city]) show(f) Well, as it so happens it looks like there are some data issues. July's data is a bit sporadic, and 2013 seems to be missing from most months as well. I think really only two things can really be confirmed here: Seattle, specifically for the months of October and November, is in fact significantly more cloudy on average than are other citiesAll cities surveyed have seen average cloud cover decline over the months studied. There are data issues, but the trend seems clear. Let's now move from cloud cover data to looking at average rainfall chance. def safe_precip(frame): if frame and 'precipProbability' in frame: return frame['precipProbability'] else: return np.NaN def monthly_avg_precip(city, year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_vals = list(map(lambda x: safe_precip(forecasts_df[city][x]['currently']), dates)) precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals))) # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below. with warnings.catch_warnings(): warnings.simplefilter('ignore') return np.nanmean(precip_vals), precip_samples def city_avg_precip(city, month): return [monthly_avg_precip(city, y, month) for y in years] for month, month_id in months: month_averages = {city: city_avg_cc(city, month_id) for city in cities} f = figure(title="{} Average Precipitation Chance".format(month), x_axis_label='Year', y_axis_label='Precipitation Chance Percentage') for city in cities: f.line(years, [x[0] for x in month_averages[city]], legend=city, color=city_colors[city]) show(f) The same data issue caveats apply here: 2013 seems to be missing some data, and July has some issues as well. However, this seems to confirm the trends we saw with cloud cover: Seattle, specifically for the months of August, October, and November has had a consistently higher chance of rain than other cities surveyed.Average precipitation chance, just like average cloud cover, has been trending down over time. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Cloudy in Seattle","url":"/2016/01/cloudy-in-seattle#conclusion","content":" I have to admit I was a bit surprised after doing this analysis. Seattle showed a higher average cloud cover and average precipitation chance than did the other cities surveyed. Maybe Seattle is actually an objectively more depressing city to live in. Well that's all for weather data at the moment. It's been a great experiment, but I think this is about as far as I'll be able to get with weather data without some domain knowledge. Talk again soon! ","version":null,"tagName":"h2"},{"title":"Complaining about the weather","type":0,"sectionRef":"#","url":"/2016/01/complaining-about-the-weather","content":"Figuring out whether people should be complaining about the recent weather in North Carolina. from bokeh.plotting import figure, output_notebook, show from bokeh.palettes import PuBuGn9 as Palette import pandas as pd import numpy as np from datetime import datetime import pickle output_notebook() BokehJS successfully loaded. I'm originally from North Carolina, and I've been hearing a lot of people talking about how often it's been raining recently. They're excited for any day that has sun. So I got a bit curious: Has North Carolina over the past few months actually had more cloudy and rainy days recently than in previous years? This shouldn't be a particularly challenging task, but I'm interested to know if people's perceptions actually reflect reality. The data we'll use comes from forecast.io, since they can give us a cloud cover percentage. I've gone ahead and retrieved the data to a pickle file, and included the code that was used to generate it. First up: What was the average cloud cover in North Carolina during August - November, and how many days were cloudy? We're going to assume that a "cloudy" day is defined as any day in which the cloud cover is above 50%. city_forecasts = pickle.load(open('city_forecasts.p', 'rb')) forecast_df = pd.DataFrame.from_dict(city_forecasts) cary_forecast = forecast_df['cary'] years = range(1990, 2016) months = range(7, 12) months_str = ['July', 'August', 'September', 'October', 'November'] def safe_cover(frame): if frame and 'cloudCover' in frame: return frame['cloudCover'] else: return np.NaN def monthly_avg_cloudcover(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) return np.nanmean(cloud_cover_vals), cloud_cover_samples monthly_cover_vals = [[monthly_avg_cloudcover(y, m)[0] for y in years] for m in months] f = figure(title='Monthly Average Cloud Cover', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_cover_vals[x], legend=months_str[x], color=Palette[x]) show(f) As we can see from the chart above, on the whole the monthly average cloud cover has been generally trending down over time. The average cloud cover is also lower than it was last year - it seems people are mostly just complaining. There are some data issues that start in 2012 that we need to be aware of - the cloud cover percentage doesn't exist for all days. Even so, the data that we have seems to reflect the wider trend, so we'll assume for now that the missing data doesn't skew our results. There's one more metric we want to check though - how many cloudy days were there? This is probably a better gauge of sentiment than the average monthly cover. def monthly_cloudy_days(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) cloudy_days = [cover > .5 for cover in cloud_cover_vals] return np.count_nonzero(cloudy_days), cloud_cover_samples monthly_days_vals = [[monthly_cloudy_days(y, m)[0] for y in years] for m in months] monthly_cover_samples = [[monthly_cloudy_days(y, m)[1] for y in years] for m in months] f = figure(title='Monthly Cloudy Days', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_days_vals[x], legend=months_str[x], color=Palette[x]) show(f) f = figure(title='Monthly Cloud Cover Samples', x_range=(1990, 2015), x_axis_label='Year', height=300) for x in range(0, len(months)): f.line(years, monthly_cover_samples[x], legend=months_str[x], color=Palette[x]) show(f) On the whole, the number of cloudy days seems to reflect the trend with average cloud cover - it's actually becoming more sunny as time progresses. That said, we need to be careful in how we view this number - because there weren't as many samples in 2015 as previous years, the number of days can get thrown off. In context though, even if most days not recorded were in fact cloudy, the overall count for 2015 would still be lower than previous years. In addition to checking cloud cover, I wanted to check precipitation data as well - what is the average precipitation chance over a month, and how many days during a month is rain likely? The thinking is that days with a high-precipitation chance will also be days in which it is cloudy or depressing. def safe_precip(frame): if frame and 'precipProbability' in frame: return frame['precipProbability'] else: return np.NaN def monthly_avg_precip(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates)) precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals))) return np.nanmean(precip_vals), precip_samples monthly_avg_precip_vals = [[monthly_avg_precip(y, m)[0] for y in years] for m in months] f = figure(title='Monthly Average Precipitation Chance', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_avg_precip_vals[x], legend=months_str[x], color=Palette[x]) show(f) As we can see from the chart, the average chance of precipitation over a month more or less stays within a band of 0 - .1 for all months over all years. This is further evidence that the past few months are no more cloudy or rainy than previous years. Like the cloud cover though, we still want to get a count of all the rainy days, in addition to the average chance. We'll define a "rainy day" as any day in which the chance of rain is greater than 25%. def monthly_rainy_days(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_prob_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates)) precip_prob_samples = len(list(filter(lambda x: x is not np.NaN, precip_prob_vals))) precip_days = [prob > .25 for prob in precip_prob_vals] return np.count_nonzero(precip_days), precip_prob_samples monthly_precip_days_vals = [[monthly_rainy_days(y, m)[0] for y in years] for m in months] monthly_precip_samples = [[monthly_rainy_days(y, m)[1] for y in years] for m in months] f = figure(title='Monthly Rainy Days', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_precip_days_vals[x], legend=months_str[x], color=Palette[x]) show(f) f = figure(title='Monthly Rainy Days Samples', x_range=(1990, 2015), x_axis_label='Year', height=300) for x in range(0, len(months)): f.line(years, monthly_precip_samples[x], legend=months_str[x], color=Palette[x]) show(f) After trying to find the number of days that are rainy, we can see that November hit its max value for rainy days in 2015. However, that value is 6, as compared to a previous maximum of 5. While it is a new record, the value isn't actually all that different. And for other months, the values are mostly in-line with the averages. Summary and Conclusions After having looked at forecast data for Cary, it appears that the months of July - November this year in terms of weather were at worst on par with prior years, if not slightly more sunny. This seems to be a case of confirmation bias: someone complains about a string of cloudy or rainy days, and suddenly you start noticing them more. While this analysis doesn't take into account other areas of North Carolina, my initial guess would be to assume that other areas also will show similar results: nothing interesting is happening. Maybe that will be for another blog post later! Coming soon: I'll compare rain/cloud conditions in North Carolina to some other places in the U.S.! Generating the Forecast file The following code was generates the file that was used throughout the blog post. Please note that I'm retrieving data for other cities to use in a future blog post, only Cary data was used for this post. import pandas as pd from functools import reduce import requests from datetime import datetime # Coordinate data from http://itouchmap.com/latlong.html cary_loc = (35.79154,-78.781117) nyc_loc = (40.78306,-73.971249) seattle_loc = (47.60621,-122.332071) binghamton_loc = (42.098687,-75.917974) cities = { 'cary': cary_loc, 'nyc': nyc_loc, 'seattle': seattle_loc, 'binghamton': binghamton_loc } apikey = '' # My super-secret API Key def get_forecast(lat, long, date=None): forecast_base = "https://api.forecast.io/forecast/" if date is None: url = forecast_base + apikey + '/{},{}'.format(lat, long) else: epoch = int(date.timestamp()) url = forecast_base + apikey + '/{},{},{}'.format(lat, long, epoch) return requests.get(url).json() years = range(1990,2016) # For datetimes, the 12 is for getting the weather at noon. # We're doing this over midnight because we're more concerned # with what people see, and people don't typically see the weather # at midnight. dt_indices = [pd.date_range(start=datetime(year, 7, 1, 12), end=datetime(year, 11, 30, 12)) for year in years] dt_merge = reduce(lambda x, y: x.union(y), dt_indices) # Because we have to pay a little bit to use the API, we use for loops here # instead of a comprehension - if something breaks, we want to preserve the # data already retrieved city_forecasts = {} for city, loc in cities.items(): print("Retrieving data for {} starting at {}".format(city, datetime.now().strftime("%I:%M:%S %p"))) for dt in dt_merge: try: city_forecasts[(city, dt)] = get_forecast(*loc, dt) except Exception as e: print(e) city_forecasts[(city, dt)] = None print("End forecast retrieval: {}".format(datetime.now().strftime("%I:%M:%S %p"))) import pickle pickle.dump(city_forecasts, open('city_forecasts.p', 'wb')) ### Output: # Retrieving data for binghamton starting at 05:13:42 PM # Retrieving data for seattle starting at 05:30:51 PM # Retrieving data for nyc starting at 05:48:30 PM # Retrieving data for cary starting at 06:08:32 PM # End forecast retrieval: 06:25:21 PM ","keywords":"","version":null},{"title":"Guaranteed money maker","type":0,"sectionRef":"#","url":"/2016/02/guaranteed-money-maker","content":"","keywords":"","version":null},{"title":"Applying the Martingale Strategy​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#applying-the-martingale-strategy","content":" But we're all realistic people, and once you start talking about "unlimited money" eyebrows should be raised. Even still, this is an interesting strategy to investigate, and I want to apply it to the stock market. As long as we can guarantee there's a single day in which the stock goes up, we should be able to make money right? The question is just how much we have to invest to guarantee this. Now it's time for the math. We'll use the following definitions: oio_ioi​ = the share price at the opening of day iiicic_ici​ = the share price at the close of day iiidid_idi​ = the amount of money we want to invest at the beginning of day iii With those definitions in place, I'd like to present the formula that is guaranteed to make you money. I call it Bradlee's Investment Formula: cn∑i=1ndioi>∑i=1ndic_n \\sum_{i=1}^n \\frac{d_i}{o_i} > \\sum_{i=1}^{n} d_icn​∑i=1n​oi​di​​>∑i=1n​di​ It might not look like much, but if you can manage to make it so that this formula holds true, you will be guaranteed to make money. The intuition behind the formula is this: The closing share price times the number of shares you have purchased ends up greater than the amount of money you invested. That is, on day nnn, if you know what the closing price will be you can set up the amount of money you invest that day to guarantee you make money. I'll even teach you to figure out how much money that is! Take a look: cn∑i=1n−1dioi+cndnon>∑i=1n−1di+dncndnon−dn>∑i=1n−1(di−cndioi)dn(cn−onon)>∑i=1n−1di(1−cnoi)dn>oncn−on∑i=1n−1di(1−1oi)\\begin{align*} c_n \\sum_{i=1}^{n-1} \\frac{d_i}{o_i} + \\frac{c_nd_n}{o_n} &> \\sum_{i=1}^{n-1}d_i + d_n\\\\ \\frac{c_nd_n}{o_n} - d_n &> \\sum_{i=1}^{n-1}(d_i - \\frac{c_nd_i}{o_i})\\\\ d_n (\\frac{c_n - o_n}{o_n}) &> \\sum_{i=1}^{n-1} d_i(1 - \\frac{c_n}{o_i})\\\\ d_n &> \\frac{o_n}{c_n - o_n} \\sum_{i=1}^{n-1} d_i(1 - \\frac{1}{o_i}) \\end{align*}cn​i=1∑n−1​oi​di​​+on​cn​dn​​on​cn​dn​​−dn​dn​(on​cn​−on​​)dn​​>i=1∑n−1​di​+dn​>i=1∑n−1​(di​−oi​cn​di​​)>i=1∑n−1​di​(1−oi​cn​​)>cn​−on​on​​i=1∑n−1​di​(1−oi​1​)​ If you invest exactly dnd_ndn​ that day, you'll break even. But if you can make sure the money you invest is greater than that quantity on the right (which requires that you have a crystal ball tell you the stock's closing price) you are guaranteed to make money! ","version":null,"tagName":"h2"},{"title":"Interesting Implications​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#interesting-implications","content":" On a more serious note though, the formula above tells us a couple of interesting things: It's impossible to make money without the closing price at some point being greater than the opening price (or vice-versa if you are short selling) - there is no amount of money you can invest that will turn things in your favor.Close prices of the past aren't important if you're concerned about the bottom line. While chart technicians use price history to make judgment calls, in the end, the closing price on anything other than the last day is irrelevant.It's possible to make money as long as there is a single day where the closing price is greater than the opening price! You might have to invest a lot to do so, but it's possible.You must make a prediction about where the stock will close at if you want to know how much to invest. That is, we can set up our investment for the day to make money if the stock goes up 1%, but if it only goes up .5% we'll still lose money.It's possible the winning move is to scale back your position. Consider the scenario: You invest money and the stock closes down the day .5%You invest tomorrow expecting the stock to go up 1%The winning investment to break even (assuming a 1% increase) is to scale back the position, since the shares you purchased at the beginning would then be profitable ","version":null,"tagName":"h2"},{"title":"Running the simulation​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#running-the-simulation","content":" So now that we've defined our investment formula,we need to tweak a couple things in order to make an investment strategy we can actually work with. There are two issues we need to address: The formula only tells us how much to invest if we want to break even (dnd_ndn​). If we actually want to turn a profit, we need to invest more than that, which we will refer to as the bias.The formula assumes we know what the closing price will be on any given day. If we don't know this, we can still invest assuming the stock price will close at a level we choose. If the price doesn't meet this objective, we try again tomorrow! This predetermined closing price will be referred to as the expectation. Now that we've defined our bias and expectation, we can actually build a strategy we can simulate. Much like the martingale strategy told you to bet twice your previous bet in order to make money, we've designed a system that tells us how much to bet in order to make money as well. Now, let's get to the code! using Quandl api_key = "" daily_investment = function(current_open, current_close, purchase_history, open_history) # We're not going to safeguard against divide by 0 - that's the user's responsibility t1 = current_close / current_open - 1 t2 = sum(purchase_history - purchase_history*current_close ./ open_history) return t2 / t1 end; And let's code a way to run simulations quickly: is_profitable = function(current_price, purchase_history, open_history) shares = sum(purchase_history ./ open_history) return current_price*shares > sum(purchase_history) end simulate = function(name, start, init, expected, bias) ticker_info = quandlget(name, from=start, api_key=api_key) open_vals = ticker_info["Open"].values close_vals = ticker_info["Close"].values invested = [init] # The simulation stops once we've made a profit day = 1 profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) || is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)]) while !profitable expected_close = open_vals[day+1] * expected todays_purchase = daily_investment(open_vals[day+1], expected_close, invested, open_vals[1:day]) invested = [invested; todays_purchase + bias] # expected_profit = expected_close * sum(invested ./ open_vals[1:length(invested)]) - sum(invested) day += 1 profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) || is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)]) end shares = sum(invested ./ open_vals[1:length(invested)]) max_profit = max(close_vals[day], open_vals[day+1]) profit = shares * max_profit - sum(invested) return (invested, profit) end sim_summary = function(investments, profit) leverages = [sum(investments[1:i]) for i=1:length(investments)] max_leverage = maximum(leverages) / investments[1] println("Max leverage: $(max_leverage)") println("Days invested: $(length(investments))") println("Profit: $profit") end; Now, let's get some data and run a simulation! Our first test: We'll invest 100 dollars in LMT, and expect that the stock will close up 1% every day. We'll invest dnd_ndn​ + 10 dollars every day that we haven't turned a profit, and end the simulation once we've made a profit. investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.01, 10) sim_summary(investments, profit) Max leverage: 5.590373200042106 Days invested: 5 Profit: 0.6894803101560001 The result: We need to invest 5.6x our initial position over a period of 5 days to make approximately .69¢ Now let's try the same thing, but we'll assume the stock closes up 2% instead. investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.02, 10) sim_summary(investments, profit) Max leverage: 1.854949900247809 Days invested: 25 Profit: 0.08304813163696423 In this example, we only get up to a 1.85x leveraged position, but it takes 25 days to turn a profit of 8¢ ","version":null,"tagName":"h2"},{"title":"Summary​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#summary","content":" We've defined an investment strategy that can tell us how much to invest when we know what the closing position of a stock will be. We can tweak the strategy to actually make money, but plenty of work needs to be done so that we can optimize the money invested. In the next post I'm going to post more information about some backtests and strategy tests on this strategy (unless of course this experiment actually produces a significant profit potential, and then I'm keeping it for myself). ","version":null,"tagName":"h2"},{"title":"Side note and disclaimer​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#side-note-and-disclaimer","content":" The claims made in this presentation about being able to guarantee making money are intended as a joke and do not constitute investment advice of any sort. ","version":null,"tagName":"h3"},{"title":"Profitability using the investment formula","type":0,"sectionRef":"#","url":"/2016/02/profitability-using-the-investment-formula","content":"","keywords":"","version":null},{"title":"Theoretical Justification​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#theoretical-justification","content":" The formula itself is designed to be simple in principle: I like making a profit, and I want to penalize the leverage you incur and days you have to invest. Ideally, we want to have a stock that goes up all the time. However, the investment formula takes advantage of a different case: trying to profit from highly volatile assets. If we can make money when the investment only has one day up, let's do it! Even so, there are two potential issues: First, stocks that trend upward will have a higher profitability score - both leverage and days invested will be 1. To protect against only investing in this trend, I can do things like taking log⁡(d)\\log(d)log(d). I don't want to start biasing the scoring function until I have a practical reason to do so, so right now I'll leave it standing. The second issue is how to penalize leverage and days invested relative to each other. As it currently stands, a leverage of 6x with only 1 day invested is the same as leveraging 2x with 3 days invested. In the future, I'd again want to look at making the impact of days invested smaller - I can get over an extra 3 days in the market if it means that I don't have to incur a highly leveraged position. So there could be things about the scoring function we change in the future, but I want to run some actual tests before we start worrying about things like that! ","version":null,"tagName":"h2"},{"title":"Running a simulation​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#running-a-simulation","content":" This won't be an incredibly rigorous backtest, I just want to see some results from the work so far. Let's set up the simulation code again, and start looking into some random stocks. If you've read the last blog post, you can skip over the code. The only difference is that it's been ported to python to make the data-wrangling easier. Julia doesn't yet support some of the multi-index things I'm trying to do. import numpy as np import pandas as pd import matplotlib.pyplot as plt from Quandl import get as qget %matplotlib inline api_key = '' profitability = lambda p, i, m, d: 1000*p / (m + i*d) def is_profitable(current_price, purchase_history, open_history): shares = (purchase_history / open_history).sum() return current_price * shares > sum(purchase_history) def daily_investment(current_open, current_close, purchase_history, open_history): t1 = current_close / current_open - 1 t2 = (purchase_history - purchase_history * current_close / open_history).sum() return t2 / t1 def simulate_day(open_vals, close_vals, init, expected, bias): invested = np.array([init]) day = 1 profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\ or is_profitable(open_vals[day], invested, open_vals[0:len(invested)]) while not profitable: expected_close = open_vals[day] * expected todays_purchase = daily_investment(open_vals[day], expected_close, invested, open_vals[0:day]) invested = np.append(invested, todays_purchase + bias) # expected_profit = expected_close * (invested / open_vals[0:len(invested)]).sum() - invested.sum() day += 1 profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\ or is_profitable(open_vals[day], invested, open_vals[0:len(invested)]) shares = (invested / open_vals[0:len(invested)]).sum() # Make sure we can't see into the future - we know either today's close or tomorrow's open # will be profitable, but we need to check which one. if is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]): ending_price = close_vals[day-1] else: ending_price = open_vals[day] profit = shares * ending_price - sum(invested) return invested, profit def simulate_ts(name, start, end, initial, expected, bias): ticker_info = qget(name, trim_start=start, api_key=api_key) evaluation_times = ticker_info[:end].index # Handle Google vs. YFinance data if "Adjusted Close" in ticker_info.columns: close_column = "Adjusted Close" else: close_column = "Close" sim = {d: simulate_day(ticker_info[d:]["Open"], ticker_info[d:][close_column], 100, 1.02, 10) for d in evaluation_times} sim_series = pd.Series(sim) result = pd.DataFrame() result["profit"] = sim_series.apply(lambda x: x[1]) result["max"] = sim_series.apply(lambda x: max(x[0])) result["days"] = sim_series.apply(lambda x: len(x[0])) result["score"] = sim_series.apply(lambda x: profitability(x[1], x[0][0], max(x[0]), len(x[0]))) result["investments"] = sim_series.apply(lambda x: x[0]) return result def simulate_tickers(tickers): from datetime import datetime results = {} for ticker in tickers: start = datetime(2015, 1, 1) results_df = simulate_ts(ticker, start, datetime(2016, 1, 1), 100, 1.01, 10) results[ticker] = results_df return pd.concat(list(results.values()), keys=list(results.keys()), axis=1) ","version":null,"tagName":"h2"},{"title":"And now the interesting part​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#and-now-the-interesting-part","content":" Let's start looking into the data! FANG stocks have been big over the past year, let's see how they look: fang_df = simulate_tickers(["YAHOO/FB", "YAHOO/AAPL", "YAHOO/NFLX", "YAHOO/GOOG"]) fang_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); fang_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); Let's think about these graphs. First, the histogram. What we like seeing is a lot of 1's - that means there were a lot of days that the stock went up and we didn't have to worry about actually implementing the strategy - we were able to close the trade at a profit. Looking at the profitability score over time though is a bit more interesting. First off, stocks that are more volatile will tend to have a higher profitability score, no two ways about that. However, Netflix consistently outperformed on this metric. We know that 2015 was a good year for Netflix, so that's a (small) sign the strategy is performing as expected. The final interesting note happens around the end of August 2015. Around this period, the markets were selling off in a big way due to issues in China (not unlike what's happening now). Even so, all of the FANG stocks saw an uptick in profitability around this time. This is another sign that the strategy being developed performs better during periods of volatility, rather than from riding markets up or down. What about FANG vs. some cyclicals? cyclic_df = simulate_tickers(["YAHOO/X", "YAHOO/CAT", "YAHOO/NFLX", "YAHOO/GOOG"]) cyclic_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); cyclic_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); Some more interesting results come from this as well. First off, US Steel (X) has a much smoother distribution of days until profitability - it doesn't have a huge number of values at 1 and then drop off. Intuitively, we're not terribly large fans of this, we want a stock to go up! However, on the profitability score it is the only serious contender to Netflix. Second, we see the same trend around August - the algorithm performs well in volatile markets. For a final test, let's try some biotech and ETFs! biotech_df = simulate_tickers(['YAHOO/REGN', 'YAHOO/CELG', 'GOOG/NASDAQ_BIB', 'GOOG/NASDAQ_IBB']) biotech_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); biotech_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); In this example, we don't see a whole lot of interesting things: the scores are all fairly close together with notable exceptions in late August, and mid-October. What is interesting is that during the volatile period, the ETF's performed significantly better than the stocks did in terms of profitability. The leveraged ETF (BIB) performed far above anyone else, and it appears that indeed, it is most profitable during volatile periods. Even so, it was far more likely to take multiple days to give a return. Its count of 1-day investments trails the other ETF and both stocks by a decent margin. And consider me an OCD freak, but I just really like Celgene's distribution - it looks nice and smooth. ","version":null,"tagName":"h2"},{"title":"Summary and plans for the next post​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#summary-and-plans-for-the-next-post","content":" So far I'm really enjoying playing with this strategy - there's a lot of depth here to understand, though the preliminary results seem to indicate that it profits mostly from taking the other side of a volatile trade. I'd be interested to run results later on data from January - It's been a particularly volatile start to the year so it would be neat to see whether this strategy would work then. For the next post, I want to start playing with some of the parameters: How do the bias and expected close influence the process? The values have been fairly conservative so far, it will be interesting to see how the simulations respond afterward. ","version":null,"tagName":"h2"},{"title":"Predicting Santander customer happiness","type":0,"sectionRef":"#","url":"/2016/03/predicting-santander-customer-happiness","content":"","keywords":"","version":null},{"title":"Data Exploration​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#data-exploration","content":" First up: we need to load our data and do some exploratory work. Because we're going to be using this data for model selection prior to testing, we need to make a further split. I've already gone ahead and done this work, please see the code in the appendix below. import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline # Record how long it takes to run the notebook - I'm curious. from datetime import datetime start = datetime.now() dataset = pd.read_csv('split_train.csv') dataset.index = dataset.ID X = dataset.drop(['TARGET', 'ID', 'ID.1'], 1) y = dataset.TARGET y.unique() array([0, 1], dtype=int64) len(X.columns) 369 Okay, so there are only two classes we're predicting: 1 for unsatisfied customers, 0 for satisfied customers. I would have preferred this to be something more like a regression, or predicting multiple classes: maybe the customer isn't the most happy, but is nowhere near closing their accounts. For now though, that's just the data we're working with. Now, I'd like to make a scatter matrix of everything going on. Unfortunately as noted above, we have 369 different features. There's no way I can graphically make sense of that much data to start with. We're also not told what the data actually represents: Are these survey results? Average time between contact with a customer care person? Frequency of contacting a customer care person? The idea is that I need to reduce the number of dimensions we're predicting across. ","version":null,"tagName":"h2"},{"title":"Dimensionality Reduction pt. 1 - Binary Classifiers​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#dimensionality-reduction-pt-1---binary-classifiers","content":" My first attempt to reduce the data dimensionality is to find all the binary classifiers in the dataset (i.e. 0 or 1 values) and see if any of those are good (or anti-good) predictors of the final data. cols = X.columns b_class = [] for c in cols: if len(X[c].unique()) == 2: b_class.append(c) len(b_class) 111 So there are 111 features in the dataset that are a binary label. Let's see if any of them are good at predicting the users satisfaction! # First we need to `binarize` the data to 0-1; some of the labels are {0, 1}, # some are {0, 3}, etc. from sklearn.preprocessing import binarize X_bin = binarize(X[b_class]) accuracy = [np.mean(X_bin[:,i] == y) for i in range(0, len(b_class))] acc_df = pd.DataFrame({"Accuracy": accuracy}, index=b_class) acc_df.describe() \tAccuracycount\t111.000000 mean\t0.905159 std\t0.180602 min\t0.043598 25%\t0.937329 50%\t0.959372 75%\t0.960837 max\t0.960837 Wow! Looks like we've got some incredibly predictive features! So much so that we should be a bit concerned. My initial guess for what's happening is that we have a sparsity issue: so many of the values are 0, and these likely happen to line up with satisfied customers. So the question we must now answer, which I likely should have asked long before now: What exactly is the distribution of un/satisfied customers? unsat = y[y == 1].count() print("Satisfied customers: {}; Unsatisfied customers: {}".format(len(y) - unsat, unsat)) naive_guess = np.mean(y == np.zeros(len(y))) print("Naive guess accuracy: {}".format(naive_guess)) Satisfied customers: 51131; Unsatisfied customers: 2083 Naive guess accuracy: 0.9608561656706882 This is a bit discouraging. A naive guess of "always satisfied" performs as well as our best individual binary classifier. What this tells me then, is that these data columns aren't incredibly helpful in prediction. I'd be interested in a polynomial expansion of this data-set, but for now, that's more computation than I want to take on. ","version":null,"tagName":"h3"},{"title":"Dimensionality Reduction pt. 2 - LDA​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#dimensionality-reduction-pt-2---lda","content":" Knowing that our naive guess performs so well is a blessing and a curse: Curse: The threshold for performance is incredibly high: We can only "improve" over the naive guess by 4%Blessing: All the binary classification features we just discovered are worthless on their own. We can throw them out and reduce the data dimensionality from 369 to 111. Now, in removing these features from the dataset, I'm not saying that there is no "information" contained within them. There might be. But the only way we'd know is through a polynomial expansion, and I'm not going to take that on within this post. My initial thought for a "next guess" is to use the LDA model for dimensionality reduction. However, it can only reduce dimensions to 1−p1 - p1−p, with ppp being the number of classes. Since this is a binary classification, every LDA model that I try will have dimensionality one; when I actually try this, the predictor ends up being slightly less accurate than the naive guess. Instead, let's take a different approach to dimensionality reduction: principle components analysis. This allows us to perform the dimensionality reduction without worrying about the number of classes. Then, we'll use a Gaussian Naive Bayes model to actually do the prediction. This model is chosen simply because it doesn't take a long time to fit and compute; because PCA will take so long, I just want a prediction at the end of this. We can worry about using a more sophisticated LDA/QDA/SVM model later. Now into the actual process: We're going to test out PCA dimensionality reduction from 1 - 20 dimensions, and then predict using a Gaussian Naive Bayes model. The 20 dimensions upper limit was selected because the accuracy never improves after you get beyond that (I found out by running it myself). Hopefully, we'll find that we can create a model better than the naive guess. from sklearn.naive_bayes import GaussianNB from sklearn.decomposition import PCA X_no_bin = X.drop(b_class, 1) def evaluate_gnb(dims): pca = PCA(n_components=dims) X_xform = pca.fit_transform(X_no_bin) gnb = GaussianNB() gnb.fit(X_xform, y) return gnb.score(X_xform, y) dim_range = np.arange(1, 21) plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy") plt.axhline(naive_guess, label="Naive Guess", c='k') plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k') plt.gcf().set_size_inches(12, 6) plt.legend(); sigh... After all the effort and computational power, we're still at square one: we have yet to beat out the naive guess threshold. With PCA in play we end up performing terribly, but not terribly enough that we can guess against ourselves. Let's try one last-ditch attempt using the entire data set: def evaluate_gnb_full(dims): pca = PCA(n_components=dims) X_xform = pca.fit_transform(X) gnb = GaussianNB() gnb.fit(X_xform, y) return gnb.score(X_xform, y) dim_range = np.arange(1, 21) plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy") plt.axhline(naive_guess, label="Naive Guess", c='k') plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k') plt.gcf().set_size_inches(12, 6) plt.legend(); Nothing. It is interesting to note that the graphs are almost exactly the same: This would imply again that the variables we removed earlier (all the binary classifiers) indeed have almost no predictive power. It seems this problem is high-dimensional, but with almost no data that can actually inform our decisions. ","version":null,"tagName":"h3"},{"title":"Summary for Day 1​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#summary-for-day-1","content":" After spending a couple hours with this dataset, there seems to be a fundamental issue in play: We have very high-dimensional data, and it has no bearing on our ability to actually predict customer satisfaction. This can be a huge issue: it implies that no matter what model we use, we fundamentally can't perform well. I'm sure most of this is because I'm not an experienced data scientist. Even so, we have yet to develop a strategy that can actually beat out the village idiot; so far, the bank is best off just assuming all its customers are satisfied. Hopefully more to come soon. end = datetime.now() print("Running time: {}".format(end - start)) Running time: 0:00:58.715714 ","version":null,"tagName":"h2"},{"title":"Appendix​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#appendix","content":" Code used to split the initial training data: from sklearn.cross_validation import train_test_split data = pd.read_csv('train.csv') data.index = data.ID data_train, data_validate = train_test_split( data, train_size=.7) data_train.to_csv('split_train.csv') data_validate.to_csv('split_validate.csv') ","version":null,"tagName":"h2"},{"title":"Tweet like me","type":0,"sectionRef":"#","url":"/2016/03/tweet-like-me","content":"","keywords":"","version":null},{"title":"The Objective​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-objective","content":" Given an input list of Tweets, build up the following things: The distribution of starting words; since there are no "prior" words to go from, we need to treat this as a special case.The distribution of words given a previous word; for example, every time I use the word woodchuck in the example sentence, there is a 50% chance it is followed by chuck and a 50% chance it is followed by could. I need this distribution for all words.The distribution of quantity of hashtags; Do I most often use just one? Two? Do they follow something like a Poisson distribution?Distribution of hashtags; Given a number of hashtags, what is the actual content? I'll treat hashtags as separate from the content of a tweet. ","version":null,"tagName":"h2"},{"title":"The Data​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-data","content":" I'm using as input my tweet history. I don't really use Twitter anymore, but it seems like a fun use of the dataset. I'd like to eventually build this to a point where I can imitate anyone on Twitter using their last 100 tweets or so, but I'll start with this as example code. ","version":null,"tagName":"h2"},{"title":"The Algorithm​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-algorithm","content":" I'll be using the NLTK library for doing a lot of the heavy lifting. First, let's import the data: import pandas as pd tweets = pd.read_csv('tweets.csv') text = tweets.text # Don't include tweets in reply to or mentioning people replies = text.str.contains('@') text_norep = text.loc[~replies] And now that we've got data, let's start crunching. First, tokenize and build out the distribution of first word: from nltk.tokenize import TweetTokenizer tknzr = TweetTokenizer() tokens = text_norep.map(tknzr.tokenize) first_words = tokens.map(lambda x: x[0]) first_words_alpha = first_words[first_words.str.isalpha()] first_word_dist = first_words_alpha.value_counts() / len(first_words_alpha) Next, we need to build out the conditional distributions. That is, what is the probability of the next word given the current word is XXX? This one is a bit more involved. First, find all unique words, and then find what words proceed them. This can probably be done in a more efficient manner than I'm currently doing here, but we'll ignore that for the moment. from functools import reduce # Get all possible words all_words = reduce(lambda x, y: x+y, tokens, []) unique_words = set(all_words) actual_words = set([x if x[0] != '.' else None for x in unique_words]) word_dist = {} for word in iter(actual_words): indices = [i for i, j in enumerate(all_words) if j == word] proceeding = [all_words[i+1] for i in indices] word_dist[word] = proceeding Now that we've got the tweet analysis done, it's time for the fun part: hashtags! Let's count how many hashtags are in each tweet, I want to get a sense of the distribution. import matplotlib.pyplot as plt %matplotlib inline hashtags = text_norep.str.count('#') bins = hashtags.unique().max() hashtags.plot(kind='hist', bins=bins) <matplotlib.axes._subplots.AxesSubplot at 0x18e59dc28d0> That looks like a Poisson distribution, kind of as I expected. I'm guessing my number of hashtags per tweet is ∼Poi(1)\\sim Poi(1)∼Poi(1), but let's actually find the most likely estimator which in this case is just λˉ\\bar{\\lambda}λˉ: mle = hashtags.mean() mle 0.870236869207003 Pretty close! So we can now simulate how many hashtags are in a tweet. Let's also find what hashtags are actually used: hashtags = [x for x in all_words if x[0] == '#'] n_hashtags = len(hashtags) unique_hashtags = list(set([x for x in unique_words if x[0] == '#'])) hashtag_dist = pd.DataFrame({'hashtags': unique_hashtags, 'prob': [all_words.count(h) / n_hashtags for h in unique_hashtags]}) len(hashtag_dist) 603 Turns out I have used 603 different hashtags during my time on Twitter. That means I was using a unique hashtag for about every third tweet. In better news though, we now have all the data we need to go about actually constructing tweets! The process will happen in a few steps: Randomly select what the first word will be.Randomly select the number of hashtags for this tweet, and then select the actual hashtags.Fill in the remaining space of 140 characters with random words taken from my tweets. And hopefully, we won't have anything too crazy come out the other end. The way we do the selection follows a Multinomial Distribution: given a lot of different values with specific probability, pick one. Let's give a quick example: x: .33 y: .5 z: .17 That is, I pick x with probability 33%, y with probability 50%, and so on. In context of our sentence construction, I've built out the probabilities of specific words already - now I just need to simulate that distribution. Time for the engine to actually be developed! import numpy as np def multinom_sim(n, vals, probs): occurrences = np.random.multinomial(n, probs) results = occurrences * vals return ' '.join(results[results != '']) def sim_n_hashtags(hashtag_freq): return np.random.poisson(hashtag_freq) def sim_hashtags(n, hashtag_dist): return multinom_sim(n, hashtag_dist.hashtags, hashtag_dist.prob) def sim_first_word(first_word_dist): probs = np.float64(first_word_dist.values) return multinom_sim(1, first_word_dist.reset_index()['index'], probs) def sim_next_word(current, word_dist): dist = pd.Series(word_dist[current]) probs = np.ones(len(dist)) / len(dist) return multinom_sim(1, dist, probs) ","version":null,"tagName":"h2"},{"title":"Pulling it all together​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#pulling-it-all-together","content":" I've now built out all the code I need to actually simulate a sentence written by me. Let's try doing an example with five words and a single hashtag: first = sim_first_word(first_word_dist) second = sim_next_word(first, word_dist) third = sim_next_word(second, word_dist) fourth = sim_next_word(third, word_dist) fifth = sim_next_word(fourth, word_dist) hashtag = sim_hashtags(1, hashtag_dist) ' '.join((first, second, third, fourth, fifth, hashtag)) 'My first all-nighter of friends #oldschool' Let's go ahead and put everything together! We're going to simulate a first word, simulate the hashtags, and then simulate to fill the gap until we've either taken up all the space or reached a period. def simulate_tweet(): chars_remaining = 140 first = sim_first_word(first_word_dist) n_hash = sim_n_hashtags(mle) hashtags = sim_hashtags(n_hash, hashtag_dist) chars_remaining -= len(first) + len(hashtags) tweet = first current = first while chars_remaining > len(tweet) + len(hashtags) and current[0] != '.' and current[0] != '!': current = sim_next_word(current, word_dist) tweet += ' ' + current tweet = tweet[:-2] + tweet[-1] return ' '.join((tweet, hashtags)).strip() ","version":null,"tagName":"h2"},{"title":"The results​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-results","content":" And now for something completely different: twenty random tweets dreamed up by my computer and my Twitter data. Here you go: for i in range(0, 20): print(simulate_tweet()) print() Also , I'm at 8 this morning. #thursdaysgohard #ornot Turns out of us breathe the code will want to my undergraduate career is becoming more night trying ? Religion is now as a chane #HYPE You know what recursion is to review the UNCC. #ornot There are really sore 3 bonfires in my first writing the library ground floor if awesome. #realtalk #impressed So we can make it out there's nothing but I'm not let us so hot I could think I may be good. #SwingDance Happy Christmas , at Harris Teeter to be be godly or Roman Catholic ). #4b392b#4b392b #Isaiah26 For context , I in the most decisive factor of the same for homework. #accomplishment Freaking done. #loveyouall New blog post : Don't jump in a quiz in with a knife fight. #haskell #earlybirthday God shows me legitimately want to get some food and one day. Stormed the queen city. #mindblown The day of a cold at least outside right before the semester .. Finished with the way back. #winners Waking up , OJ , I feel like Nick Jonas today. First draft of so hard drive. #humansvszombies Eric Whitacre is the wise creation. Ethics paper first , music in close to everyone who just be posting up with my sin , and Jerry Springr #TheLittleThings Love that you know enough time I've eaten at 8 PM. #deepthoughts #stillblownaway Lead. #ThinkingTooMuch #Christmas Aamazing conference when you married #DepartmentOfRedundancyDepartment Yep , but there's a legitimate challenge. ...Which all ended up being a whole lot more nonsensical than I had hoped for. There are some good ones, so I'll call that an accomplishment! I was banking on grammar not being an issue: since my tweets use impeccable grammar, the program modeled off them should have pretty good grammar as well. There are going to be some hilarious edge cases (I'm looking at you, Ethics paper first, music in close to everyone) that make no sense, and some hilarious edge cases (Waking up, OJ, I feel like Nick Jonas today) that make me feel like I should have a Twitter rap career. On the whole though, the structure came out alright. ","version":null,"tagName":"h2"},{"title":"Moving on from here​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#moving-on-from-here","content":" During class we also talked about an interesting idea: trying to analyze corporate documents and corporate speech. I'd be interested to know what this analysis applied to something like a couple of bank press releases could do. By any means, the code needs some work to clean it up before I get that far. ","version":null,"tagName":"h2"},{"title":"For further reading​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#for-further-reading","content":" I'm pretty confident I re-invented a couple wheels along the way - what I'm doing feels a lot like what Markov Chain Monte Carlo is intended to do. But I've never worked explicitly with that before, so more research is needed. ","version":null,"tagName":"h2"},{"title":"Tick tock...","type":0,"sectionRef":"#","url":"/2016/04/tick-tock","content":"","keywords":"","version":null},{"title":"2.5 Billion​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#25-billion","content":" If PBS is right, that's the total number of heartbeats we get. Approximately once every second that number goes down, and down, and down again... total_heartbeats = 2500000000 I got a Fitbit this past Christmas season, mostly because I was interested in the data and trying to work on some data science projects with it. This is going to be the first project, but there will likely be more (and not nearly as morbid). My idea was: If this is the final number that I'm running up against, how far have I come, and how far am I likely to go? I've currently had about 3 months' time to estimate what my data will look like, so let's go ahead and see: given a lifetime 2.5 billion heart beats, how much time do I have left? ","version":null,"tagName":"h2"},{"title":"Statistical Considerations​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#statistical-considerations","content":" Since I'm starting to work with health data, there are a few considerations I think are important before I start digging through my data. The concept of 2.5 billion as an agreed-upon number is tenuous at best. I've seen anywhere from 2.21 billion to 3.4 billion so even if I knew exactly how many times my heart had beaten so far, the ending result is suspect at best. I'm using 2.5 billion because that seems to be about the midpoint of the estimates I've seen so far.Most of the numbers I've seen so far are based on extrapolating number of heart beats from life expectancy. As life expectancy goes up, the number of expected heart beats goes up too.My estimation of the number of heartbeats in my life so far is based on 3 months worth of data, and I'm extrapolating an entire lifetime based on this. So while the ending number is not useful in any medical context, it is still an interesting project to work with the data I have on hand. ","version":null,"tagName":"h2"},{"title":"Getting the data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#getting-the-data","content":" Fitbit has an API available for people to pull their personal data off the system. It requires registering an application, authentication with OAuth, and some other complicated things. If you're not interested in how I fetch the data, skip here. ","version":null,"tagName":"h2"},{"title":"Registering an application​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#registering-an-application","content":" I've already registered a personal application with Fitbit, so I can go ahead and retrieve things like the client secret from a file. # Import all the OAuth secret information from a local file from secrets import CLIENT_SECRET, CLIENT_ID, CALLBACK_URL ","version":null,"tagName":"h2"},{"title":"Handling OAuth 2​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#handling-oauth-2","content":" So, all the people that know what OAuth 2 is know what's coming next. For those who don't: OAuth is how people allow applications to access other data without having to know your password. Essentially the dialog goes like this: Application: I've got a user here who wants to use my application, but I need their data. Fitbit: OK, what data do you need access to, and for how long? Application: I need all of these scopes, and for this amount of time. Fitbit: OK, let me check with the user to make sure they really want to do this. Fitbit: User, do you really want to let this application have your data? User: I do! And to prove it, here's my password. Fitbit: OK, everything checks out. I'll let the application access your data. Fitbit: Application, you can access the user's data. Use this special value whenever you need to request data from me. Application: Thank you, now give me all the data. Effectively, this allows an application to gain access to a user's data without ever needing to know the user's password. That way, even if the other application is hacked, the user's original data remains safe. Plus, the user can let the data service know to stop providing the application access any time they want. All in all, very secure. It does make handling small requests a bit challenging, but I'll go through the steps here. We'll be using the Implicit Grant workflow, as it requires fewer steps in processing. First, we need to set up the URL the user would visit to authenticate: import urllib FITBIT_URI = 'https://www.fitbit.com/oauth2/authorize' params = { # If we need more than one scope, must be a CSV string 'scope': 'heartrate', 'response_type': 'token', 'expires_in': 86400, # 1 day 'redirect_uri': CALLBACK_URL, 'client_id': CLIENT_ID } request_url = FITBIT_URI + '?' + urllib.parse.urlencode(params) Now, here you would print out the request URL, go visit it, and get the full URL that it sends you back to. Because that is very sensitive information (specifically containing my CLIENT_ID that I'd really rather not share on the internet), I've skipped that step in the code here, but it happens in the background. # The `response_url` variable contains the full URL that # FitBit sent back to us, but most importantly, # contains the token we need for authorization. access_token = dict(urllib.parse.parse_qsl(response_url))['access_token'] ","version":null,"tagName":"h3"},{"title":"Requesting the data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#requesting-the-data","content":" Now that we've actually set up our access via the access_token, it's time to get the actual heart rate data. I'll be using data from January 1, 2016 through March 31, 2016, and extrapolating wildly from that. Fitbit only lets us fetch intraday data one day at a time, so I'll create a date range using pandas and iterate through that to pull down all the data. from requests_oauthlib import OAuth2Session import pandas as pd from datetime import datetime session = OAuth2Session(token={ 'access_token': access_token, 'token_type': 'Bearer' }) format_str = '%Y-%m-%d' start_date = datetime(2016, 1, 1) end_date = datetime(2016, 3, 31) dr = pd.date_range(start_date, end_date) url = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json' hr_responses = [session.get(url.format(d.strftime(format_str))) for d in dr] def record_to_df(record): if 'activities-heart' not in record: return None date_str = record['activities-heart'][0]['dateTime'] df = pd.DataFrame(record['activities-heart-intraday']['dataset']) df.index = df['time'].apply( lambda x: datetime.strptime(date_str + ' ' + x, '%Y-%m-%d %H:%M:%S')) return df hr_dataframes = [record_to_df(record.json()) for record in hr_responses] hr_df_concat = pd.concat(hr_dataframes) # There are some minutes with missing data, so we need to correct that full_daterange = pd.date_range(hr_df_concat.index[0], hr_df_concat.index[-1], freq='min') hr_df_full = hr_df_concat.reindex(full_daterange, method='nearest') print("Heartbeats from {} to {}: {}".format(hr_df_full.index[0], hr_df_full.index[-1], hr_df_full['value'].sum())) Heartbeats from 2016-01-01 00:00:00 to 2016-03-31 23:59:00: 8139060 And now we've retrieved all the available heart rate data for January 1st through March 31st! Let's get to the actual analysis. ","version":null,"tagName":"h3"},{"title":"Wild Extrapolations from Small Data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#wild-extrapolations-from-small-data","content":" A fundamental issue of this data is that it's pretty small. I'm using 3 months of data to make predictions about my entire life. But, purely as an exercise, I'll move forward. ","version":null,"tagName":"h2"},{"title":"How many heartbeats so far?​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#how-many-heartbeats-so-far","content":" The first step is figuring out how many of the 2.5 billion heartbeats I've used so far. We're going to try and work backward from the present day to when I was born to get that number. The easy part comes first: going back to January 1st, 1992. That's because I can generalize how many 3-month increments there were between now and then, account for leap years, and call that section done. Between January 1992 and January 2016 there were 96 quarters, and 6 leap days. The number we're looking for is: hrq⋅n−hrd⋅(n−m)\\begin{equation*} hr_q \\cdot n - hr_d \\cdot (n-m) \\end{equation*}hrq​⋅n−hrd​⋅(n−m)​ hrqhr_qhrq​: Number of heartbeats per quarterhrdhr_dhrd​: Number of heartbeats on leap daynnn: Number of quarters, in this case 96mmm: Number of leap days, in this case 6 quarterly_count = hr_df_full['value'].sum() leap_day_count = hr_df_full[(hr_df_full.index.month == 2) & (hr_df_full.index.day == 29)]['value'].sum() num_quarters = 96 leap_days = 6 jan_92_jan_16 = quarterly_count * num_quarters - leap_day_count * (num_quarters - leap_days) jan_92_jan_16 773609400 So between January 1992 and January 2016 I've used ≈\\approx≈ 774 million heartbeats. Now, I need to go back to my exact birthday. I'm going to first find on average how many heartbeats I use in a minute, and multiply that by the number of minutes between my birthday and January 1992. For privacy purposes I'll put the code here that I'm using, but without any identifying information: minute_mean = hr_df_full['value'].mean() # Don't you wish you knew? # birthday_minutes = ??? birthday_heartbeats = birthday_minutes * minute_mean heartbeats_until_2016 = int(birthday_heartbeats + jan_92_jan_16) remaining_2016 = total_heartbeats - heartbeats_until_2016 print("Heartbeats so far: {}".format(heartbeats_until_2016)) print("Remaining heartbeats: {}".format(remaining_2016)) Heartbeats so far: 775804660 Remaining heartbeats: 1724195340 It would appear that my heart has beaten 775,804,660 times between my moment of birth and January 1st 2016, and that I have 1.72 billion left. ","version":null,"tagName":"h3"},{"title":"How many heartbeats longer?​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#how-many-heartbeats-longer","content":" Now comes the tricky bit. I know how many heart beats I've used so far, and how many I have remaining, so I'd like to come up with a (relatively) accurate estimate of when exactly my heart should give out. We'll do this in a few steps, increasing in granularity. First step, how many heartbeats do I use in a 4-year period? I have data for a single quarter including leap day, so I want to know: hrq⋅n−hrd⋅(n−m)\\begin{equation*} hr_q \\cdot n - hr_d \\cdot (n - m) \\end{equation*}hrq​⋅n−hrd​⋅(n−m)​ hrqhr_qhrq​: Heartbeats per quarterhrdhr_dhrd​: Heartbeats per leap daynnn: Number of quarters = 16mmm: Number of leap days = 1 heartbeats_4year = quarterly_count * 16 - leap_day_count * (16 - 1) heartbeats_4year 128934900 Now, I can fast forward from 2016 the number of periods of 4 years I have left. four_year_periods = remaining_2016 // heartbeats_4year remaining_4y = remaining_2016 - four_year_periods * heartbeats_4year print("Four year periods remaining: {}".format(four_year_periods)) print("Remaining heartbeats after 4 year periods: {}".format(remaining_4y)) Four year periods remaining: 13 Remaining heartbeats after 4 year periods: 48041640 Given that there are 13 four-year periods left, I can move from 2016 all the way to 2068, and find that I will have 48 million heart beats left. Let's drop down to figuring out how many quarters that is. I know that 2068 will have a leap day (unless someone finally decides to get rid of them), so I'll subtract that out first. Then, I'm left to figure out how many quarters exactly are left. remaining_leap = remaining_4y - leap_day_count # Ignore leap day in the data set heartbeats_quarter = hr_df_full[(hr_df_full.index.month != 2) & (hr_df_full.index.day != 29)]['value'].sum() quarters_left = remaining_leap // heartbeats_quarter remaining_year = remaining_leap - quarters_left * heartbeats_quarter print("Quarters left starting 2068: {}".format(quarters_left)) print("Remaining heartbeats after that: {}".format(remaining_year)) Quarters left starting 2068: 8 Remaining heartbeats after that: 4760716 So, that analysis gets me through until January 1st 2070. Final step, using that minute estimate to figure out how many minutes past that I'm predicted to have: from datetime import timedelta base = datetime(2070, 1, 1) minutes_left = remaining_year // minute_mean kaput = timedelta(minutes=minutes_left) base + kaput datetime.datetime(2070, 2, 23, 5, 28) According to this, I've got until February 23rd, 2070 at 5:28 PM in the evening before my heart gives out. ","version":null,"tagName":"h3"},{"title":"Summary​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#summary","content":" Well, that's kind of a creepy date to know. As I said at the top though, this number is totally useless in any medical context. It ignores the rate at which we continue to get better at making people live longer, and is extrapolating from 3 months' worth of data the rest of my life. Additionally, throughout my time developing this post I made many minor mistakes. I think they're all fixed now, but it's easy to mix a number up here or there and the analysis gets thrown off by a couple years. Even still, I think philosophically humans have a desire to know how much time we have left in the world. Man is but a breath, and it's scary to think just how quickly that date may be coming up. This analysis asks an important question though: what are you going to do with the time you have left? Thanks for sticking with me on this one, I promise it will be much less depressing next time! ","version":null,"tagName":"h2"},{"title":"The unfair casino","type":0,"sectionRef":"#","url":"/2016/05/the-unfair-casino","content":"","keywords":"","version":null},{"title":"Proving we can detect cheating​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#proving-we-can-detect-cheating","content":" My first question is simply, is this possible? There's a lot of trivial cases that make it obvious that there's cheating going on. But there are some edge cases that might give us more difficulty. First though, let's get a picture of what the fair distribution looks like. In principle, we can only detect cheating if the distribution of the fair die differs from the distribution of the loaded die. import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline fair_1 = np.random.randint(1, 7, 10000) fair_2 = np.random.randint(1, 7, 10000) pd.Series(fair_1 + fair_2).plot(kind='hist', bins=11); plt.title('Fair Distribution'); This distribution makes sense: there are many ways to make a 7 (the most frequent observed value) and very few ways to make a 12 or 2; an important symmetry. As a special note, you can notice that the sum of two fair dice is a discrete case of the Triangle Distribution, which is itself a special case of the Irwin-Hall Distribution. ","version":null,"tagName":"h2"},{"title":"The Edge Cases​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-edge-cases","content":" Given that we understand how the results of two fair dice are distributed, let's see some of the interesting edge cases that come up. This will give us assurance that when a casino is cheating, it is detectable (given sufficient data). To make this as hard as possible, we will think of scenarios where the expected value of the sum of loaded dice is the same as the expected value of the sum of fair dice. ","version":null,"tagName":"h2"},{"title":"Edge Case 1​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#edge-case-1","content":" What happens when one die is biased low, and one die is biased high? That is, where: D1={1w.p.1/32w.p.1/33w.p.1/124w.p.1/125w.p.1/126w.p.1/12D2={1w.p.1/122w.p.1/123w.p.1/124w.p.1/125w.p.1/36w.p.1/3E[D1]=2.5E[D2]=4.5E[D1+D2]=7=E[Dfair+Dfair]\\begin{align*} \\begin{array}{cc} D_1 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/3\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/12 \\end{array} \\right. & D_2 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/12\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/3\\\\ 6 & w.p. 1/3 \\end{array} \\right. \\\\ \\mathbb{E}[D_1] = 2.5 & \\mathbb{E}[D_2] = 4.5 \\end{array}\\\\ \\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}] \\end{align*}D1​=⎩⎨⎧​123456​w.p.1/3w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12​E[D1​]=2.5​D2​=⎩⎨⎧​123456​w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3w.p.1/3​E[D2​]=4.5​E[D1​+D2​]=7=E[Dfair​+Dfair​]​ def unfair_die(p_vals, n): x = np.random.multinomial(1, p_vals, n) return x.nonzero()[1] + 1 d1 = [1/3, 1/3, 1/12, 1/12, 1/12, 1/12] d2 = [1/12, 1/12, 1/12, 1/12, 1/3, 1/3] x1 = unfair_die(d1, 10000) x2 = unfair_die(d2, 10000) pd.Series(x1 + x2).plot(kind='hist', bins=11); plt.title('$D_1$ biased low, $D_2$ biased high'); We can see that while the 7 value remains the most likely (as expected), the distribution is not so nicely shaped any more. ","version":null,"tagName":"h3"},{"title":"Edge Case 2​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#edge-case-2","content":" When one die is loaded low, and one is loaded high, we've seen how we can detect them. How about when two die are loaded both low and high? That is, we have the following distribution: D1={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3D2={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3E[D1]=3.5E[D2]=3.5E[D1+D2]=7=E[Dfair+Dfair]\\begin{align*} \\begin{array}{cc} D_1 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/3 \\end{array} \\right. & D_2 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/3 \\end{array} \\right. \\\\ \\mathbb{E}[D_1] = 3.5 & \\mathbb{E}[D_2] = 3.5 \\end{array}\\\\ \\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}] \\end{align*}D1​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​E[D1​]=3.5​D2​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​E[D2​]=3.5​E[D1​+D2​]=7=E[Dfair​+Dfair​]​ We can see even that the expected value of each individual die is the same as the fair die! However, the distribution (if we are doing this correctly) should still be skewed: d1 = [1/3, 1/12, 1/12, 1/12, 1/12, 1/3] d2 = d1 x1 = unfair_die(d1, 10000) x2 = unfair_die(d2, 10000) pd.Series(x1 + x2).plot(kind='hist', bins=11) plt.title("$D_1$ and $D_2$ biased to 1 and 6"); In a very un-subtle way, we have of course made the values 2 and 12 far more likely. ","version":null,"tagName":"h3"},{"title":"Detection Conclusion​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#detection-conclusion","content":" There are some trivial examples of cheating that are easy to detect: whenever the expected value of the sum of two fair dice deviates from the expected value for the sum of two fair dice, we can immediately conclude that there is cheating at stake. The interesting edge cases occur when the expected value of the sum of loaded dice matches the expected value of the sum of fair dice. Considering the above examples (and a couple more I ran through in developing this), we have seen that in every circumstance having two unfair dice leads to a distribution of results different from the fair results. We can thus finally state: just by looking at the distribution of results from this game, we can immediately conclude whether there is cheating. ","version":null,"tagName":"h2"},{"title":"Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#simulated-annealing","content":" What we really would like to do though, is see if there is any way to determine how exactly the dice are loaded. This is significantly more complicated, but we can borrow some algorithms from Machine Learning to figure out exactly how to perform this process. I'm using the Simulated Annealing algorithm, and I discuss why this works and why I chose it over some of the alternatives in the justification. If you don't care about how I set up the model and just want to see the code, check out the actual code. Simulated Annealing is a variation of the Metropolis-Hastings Algorithm, but the important thing for us is: Simulated Annealing allows us to quickly optimize high-dimensional problems. But what exactly are we trying to optimize? Ideally, we want a function that can tell us whether one distribution for the dice better explains the results than another distribution. This is known as the likelihood function. ","version":null,"tagName":"h2"},{"title":"Deriving the Likelihood function​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#deriving-the-likelihood-function","content":" To derive our likelihood function, we want to know: what is the probability of seeing a specific result given those hidden parameters? This is actually a surprisingly difficult problem. While we can do a lot of calculations by hand, we need a more general solution since we will be working with very some interesting die distributions. We first note that the sum of two dice can take on 11 different values - 2 through 12. This implies that each individual sum follows a Categorical distribution. That is: L(x)={p2x=2p3x=3…p11x=11p12x=12\\begin{align*} \\mathcal{L(x)} = \\left\\{ \\begin{array}{lr} p_2 & x = 2\\\\ p_3 & x = 3\\\\ \\ldots & \\\\ p_{11} & x = 11\\\\ p_{12} & x = 12 \\end{array} \\right. \\end{align*}L(x)=⎩⎨⎧​p2​p3​…p11​p12​​x=2x=3x=11x=12​​ Where each pip_ipi​ is the probability of seeing that specific result. However, we need to calculate what each probability is! I'll save you the details, but this author explains how to do it. Now, we would like to know the likelihood of our entire data-set. This is trivial: L(X)=∏i=1nL(x)\\begin{align*} \\mathcal{L(\\mathbf{X})} &= \\prod_{i=1}^n L(x) \\end{align*}L(X)​=i=1∏n​L(x)​ However, it's typically much easier to work with the log⁡(L)\\log(\\mathcal{L})log(L) function instead. This is critically important from a computational perspective: when you multiply so many small numbers together (i.e. the product of L(x)L(x)L(x) terms) the computer suffers from rounding error; if we don't control for this, we will find that no matter the distributions we choose for each die, the "likelihood" will be close to zero because the computer is not precise enough. log⁡(L)=∑i=1nlog⁡(L)\\begin{align*} \\log(\\mathcal{L}) &= \\sum_{i=1}^n \\log(L) \\end{align*}log(L)​=i=1∑n​log(L)​ ","version":null,"tagName":"h3"},{"title":"The process of Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-process-of-simulated-annealing","content":" The means by which we optimize our likelihood function is the simulated annealing algorithm. The way it works is as follows: Start with a random guess for the parameters we are trying to optimize. In our case we are trying to guess the distribution of two dice, and so we "optimize" until we have a distribution that matches the data. For each iteration of the algorithm: Generate a new "proposed" set of parameters based on the current parameters - i.e. slightly modify the current parameters to get a new set of parameters.Calculate the value of log⁡(L)\\log(\\mathcal{L})log(L) for each set of parameters. If the function value for the proposed parameter set is higher than for the current, automatically switch to the new parameter set and continue the next iteration.Given the new parameter set performs worse, determine a probability of switching to the new parameter set anyways: P(pcurrent,pproposed)\\mathcal{P}(p_{current}, p_{proposed})P(pcurrent​,pproposed​)Switch to the new parameter set with probability P\\mathcal{P}P. If you fail to switch, begin the next iteration. The algorithm is complete after we fail to make a transition nnn times in a row. If everything goes according to plan, we will have a value that is close to the true distribution of each die. ","version":null,"tagName":"h3"},{"title":"The actual code​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-actual-code","content":" We start by defining the score function. This will tell us how well the proposed die densities actually explain the results. import numpy as np from numpy import polynomial def density_coef(d1_density, d2_density): # Calculating the probabilities of each outcome was taken # from this author: http://math.stackexchange.com/a/1710392/320784 d1_p = polynomial.Polynomial(d1_density) d2_p = polynomial.Polynomial(d2_density) coefs = (d1_p * d2_p).coef return coefs def score(x, d1_density, d2_density): # We've now got the probabilities of each event, but we need # to shift the array a bit so we can use the x values to actually # index into it. This will allow us to do all the calculations # incredibly quickly coefs = density_coef(d1_density, d2_density) coefs = np.hstack((0, 0, coefs)) return np.log(coefs[x]).sum() Afterward, we need to write something to permute the proposal densities. We make random modifications, and eventually the best one survives. def permute(d1_density, d2_density): # To ensure we have legitimate densities, we will randomly # increase one die face probability by `change`, # and decrease one by `change`. # This means there are something less than (1/`change`)^12 possibilities # we are trying to search over. change = .01 d1_index1, d1_index2 = np.random.randint(0, 6, 2) d2_index1, d2_index2 = np.random.randint(0, 6, 2) # Also make sure to copy. I've had some weird aliasing issues # in the past that made everything blow up. new_d1 = np.float64(np.copy(d1_density)) new_d2 = np.float64(np.copy(d2_density)) # While this doesn't account for the possibility that some # values go negative, in practice this never happens new_d1[d1_index1] += change new_d1[d1_index2] -= change new_d2[d2_index1] += change new_d2[d2_index2] -= change return new_d1, new_d2 Now we've got the main algorithm code to do. This is what brings all the pieces together. def optimize(data, conv_count=10, max_iter=1e4): switch_failures = 0 iter_count = 0 # Start with guessing fair dice cur_d1 = np.repeat(1/6, 6) cur_d2 = np.repeat(1/6, 6) cur_score = score(data, cur_d1, cur_d2) # Keep track of our best guesses - may not be # what we end with max_score = cur_score max_d1 = cur_d1 max_d2 = cur_d2 # Optimization stops when we have failed to switch `conv_count` # times (presumably because we have a great guess), or we reach # the maximum number of iterations. while switch_failures < conv_count and iter_count < max_iter: iter_count += 1 if iter_count % (max_iter / 10) == 0: print('Iteration: {}; Current score (higher is better): {}'.format( iter_count, cur_score)) new_d1, new_d2 = permute(cur_d1, cur_d2) new_score = score(data, new_d1, new_d2) if new_score > max_score: max_score = new_score max_d1 = new_d1 max_d2 = new_d2 if new_score > cur_score: # If the new permutation beats the old one, # automatically select it. cur_score = new_score cur_d1 = new_d1 cur_d2 = new_d2 switch_failures = 0 else: # We didn't beat the current score, but allow # for possibly switching anyways. accept_prob = np.exp(new_score - cur_score) coin_toss = np.random.rand() if coin_toss < accept_prob: # We randomly switch to the new distribution cur_score = new_score cur_d1 = new_d1 cur_d2 = new_d2 switch_failures = 0 else: switch_failures += 1 # Return both our best guess, and the ending guess return max_d1, max_d2, cur_d1, cur_d2 And now we have finished the hard work! ","version":null,"tagName":"h2"},{"title":"Catching the Casino​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#catching-the-casino","content":" Let's go through a couple of scenarios and see if we can catch the casino cheating with some loaded dice. In every scenario we start with an assumption of fair dice, and then try our hand to figure out what the actual distribution was. ","version":null,"tagName":"h2"},{"title":"Attempt 1​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-1","content":" The casino is using two dice that are both biased low. How well can we recover the distribution? import time def simulate_casino(d1_dist, d2_dist, n=10000): d1_vals = unfair_die(d1_dist, n) d2_vals = unfair_die(d2_dist, n) start = time.perf_counter() max_d1, max_d2, final_d1, final_d2 = optimize(d1_vals + d2_vals) end = time.perf_counter() print("Simulated Annealing time: {:.02f}s".format(end - start)) coef_range = np.arange(2, 13) - .5 plt.subplot(221) plt.bar(coef_range, density_coef(d1_dist, d2_dist), width=1) plt.title('True Distribution') plt.subplot(222) plt.hist(d1_vals + d2_vals, bins=11) plt.title('Empirical Distribution') plt.subplot(223) plt.bar(coef_range, density_coef(max_d1, max_d2), width=1) plt.title('Recovered Distribution') plt.gcf().set_size_inches(10, 10) simulate_casino([2/9, 2/9, 2/9, 1/9, 1/9, 1/9], [2/9, 2/9, 2/9, 1/9, 1/9, 1/9]) Iteration: 1000; Current score (higher is better): -22147.004400281654 Simulated Annealing time: 0.30s ","version":null,"tagName":"h3"},{"title":"Attempt 2​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-2","content":" The casino now uses dice that are both biased towards 1 and 6. simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3], [1/3, 1/12, 1/12, 1/12, 1/12, 1/3]) Simulated Annealing time: 0.08s ","version":null,"tagName":"h3"},{"title":"Attempt 3​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-3","content":" The casino will now use one die biased towards 1 and 6, and one die towards 3 and 4. simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3], [1/12, 1/12, 1/3, 1/3, 1/12, 1/12]) Simulated Annealing time: 0.09s ","version":null,"tagName":"h3"},{"title":"Attempt 4​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-4","content":" We'll now finally go to a fair casino to make sure that we can still recognize a positive result. simulate_casino(np.repeat(1/6, 6), np.repeat(1/6, 6)) Simulated Annealing time: 0.02s ","version":null,"tagName":"h3"},{"title":"Attempt 5​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-5","content":" We've so far been working with a large amount of data - 10,000 data points. Can we now scale things back to only 250 throws? We'll start with two dice biased high. simulate_casino([1/9, 1/9, 1/9, 2/9, 2/9, 2/9], [1/9, 1/9, 1/9, 2/9, 2/9, 2/9], n=250) Iteration: 1000; Current score (higher is better): -551.6995384525453 Iteration: 2000; Current score (higher is better): -547.7803673440676 Iteration: 3000; Current score (higher is better): -547.9805613193807 Iteration: 4000; Current score (higher is better): -546.7574874775273 Iteration: 5000; Current score (higher is better): -549.5798007672656 Iteration: 6000; Current score (higher is better): -545.0354060154496 Iteration: 7000; Current score (higher is better): -550.1134504086606 Iteration: 8000; Current score (higher is better): -549.9306537114975 Iteration: 9000; Current score (higher is better): -550.7075182119111 Iteration: 10000; Current score (higher is better): -549.400679551826 Simulated Annealing time: 1.94s The results are surprisingly good. While the actual optimization process took much longer to finish than in the other examples, we still have a very good guess. As a caveat though: the recovered distribution tends to overfit the data. That is, if the data doesn't fit the underlying distribution well, the model will also fail. ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#conclusion","content":" Given the results above, we can see that we have indeed come up with a very good algorithm to determine the distribution of two dice given their results. As a benefit, we have even seen that results come back very quickly; it's not uncommon for the optimization to converge within a tenth of a second. Additionally, we have seen that the algorithm can intuit the distribution even when there is not much data. While the final example shows that we can 'overfit' on the dataset, we can still get valuable information from a relatively small dataset. We can declare at long last: the mathematicians have again triumphed over the casino. ","version":null,"tagName":"h2"},{"title":"Justification of Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#justification-of-simulated-annealing","content":" ","version":null,"tagName":"h2"},{"title":"Why Simulated Annealing?​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#why-simulated-annealing","content":" So why even use an algorithm with a fancy title like Simulated Annealing? First of all, because the title is sexy. Second of all, because this is a reasonably complicated problem to try and solve. We have a parameter space where each value pij∈(0,1);i,j∈{1,…,6}p_{ij} \\in (0, 1); i, j \\in \\{1, \\ldots, 6\\}pij​∈(0,1);i,j∈{1,…,6}, for a total of 12 different variables we are trying to optimize over. Additionally, given a 12-dimensional function we are trying to optimize, simulated annealing makes sure that we don't fall into a local minimum. ","version":null,"tagName":"h3"},{"title":"Why not something else?​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#why-not-something-else","content":" This is a fair question. There are two classes of algorithms that can also be used to solve this problem: Non-linear optimization methods, and the EM algorithm. I chose not to use non-linear optimization simply because I'm a bit concerned that it will trap me in a local maximum. Instead of running multiple different optimizations from different starting points, I can just use simulated annealing to take that into account. In addition, throughout the course of testing the simulated annealing code converged incredibly quickly - far more quickly than any non-linear solver would be able to accomplish. The EM Algorithm was originally what I intended to write this blog post with. Indeed, the post was inspired by the crooked casino example which uses the EM algorithm to solve it. However, after modeling the likelihood function I realized that the algebra would very quickly get out of hand. Trying to compute all the polynomial terms would not be fun, which would be needed to actually optimize for each parameter. So while the EM algorithm would likely be much faster in raw speed terms, the amount of time needed to program and verify it meant that I was far better off using a different method for optimization. ","version":null,"tagName":"h3"},{"title":"Event studies and earnings releases","type":0,"sectionRef":"#","url":"/2016/06/event-studies-and-earnings-releases","content":"","keywords":"","version":null},{"title":"The Market Just Knew​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#the-market-just-knew","content":" I recently saw two examples of stock charts that have kept me thinking for a while. And now that the semester is complete, I finally have enough time to really look at them and give them the treatment they deserve. The first is good old Apple: Code from secrets import QUANDL_KEY import matplotlib.pyplot as plt from matplotlib.dates import date2num from matplotlib.finance import candlestick_ohlc from matplotlib.dates import DateFormatter, WeekdayLocator,\\ DayLocator, MONDAY import quandl from datetime import datetime import pandas as pd %matplotlib inline def fetch_ticker(ticker, start, end): # Quandl is currently giving me issues with returning # the entire dataset and not slicing server-side. # So instead, we'll do it client-side! q_format = '%Y-%m-%d' ticker_data = quandl.get('YAHOO/' + ticker, start_date=start.strftime(q_format), end_date=end.strftime(q_format), authtoken=QUANDL_KEY) return ticker_data def ohlc_dataframe(data, ax=None): # Much of this code re-used from: # http://matplotlib.org/examples/pylab_examples/finance_demo.html if ax is None: f, ax = plt.subplots() vals = [(date2num(date), *(data.loc[date])) for date in data.index] candlestick_ohlc(ax, vals) mondays = WeekdayLocator(MONDAY) alldays = DayLocator() weekFormatter = DateFormatter('%b %d') ax.xaxis.set_major_locator(mondays) ax.xaxis.set_minor_locator(alldays) ax.xaxis.set_major_formatter(weekFormatter) return ax AAPL = fetch_ticker('AAPL', datetime(2016, 3, 1), datetime(2016, 5, 1)) ax = ohlc_dataframe(AAPL) plt.vlines(date2num(datetime(2016, 4, 26, 12)), ax.get_ylim()[0], ax.get_ylim()[1], color='b', label='Earnings Release') plt.legend(loc=3) plt.title("Apple Price 3/1/2016 - 5/1/2016"); The second chart is from Facebook: FB = fetch_ticker('FB', datetime(2016, 3, 1), datetime(2016, 5, 5)) ax = ohlc_dataframe(FB) plt.vlines(date2num(datetime(2016, 4, 27, 12)), ax.get_ylim()[0], ax.get_ylim()[1], color='b', label='Earnings Release') plt.title('Facebook Price 3/5/2016 - 5/5/2016') plt.legend(loc=2); These two charts demonstrate two very specific phonomena: how the market prepares for earnings releases. Let's look at those charts again, but with some extra information. As we're about the see, the market "knew" in advance that Apple was going to perform poorly. The market expected that Facebook was going to perform poorly, and instead shot the lights out. Let's see that trend in action: Code def plot_hilo(ax, start, end, data): ax.plot([date2num(start), date2num(end)], [data.loc[start]['High'], data.loc[end]['High']], color='b') ax.plot([date2num(start), date2num(end)], [data.loc[start]['Low'], data.loc[end]['Low']], color='b') f, axarr = plt.subplots(1, 2) ax_aapl = axarr[0] ax_fb = axarr[1] # Plot the AAPL trend up and down ohlc_dataframe(AAPL, ax=ax_aapl) plot_hilo(ax_aapl, datetime(2016, 3, 1), datetime(2016, 4, 15), AAPL) plot_hilo(ax_aapl, datetime(2016, 4, 18), datetime(2016, 4, 26), AAPL) ax_aapl.vlines(date2num(datetime(2016, 4, 26, 12)), ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1], color='g', label='Earnings Release') ax_aapl.legend(loc=2) ax_aapl.set_title('AAPL Price History') # Plot the FB trend down and up ohlc_dataframe(FB, ax=ax_fb) plot_hilo(ax_fb, datetime(2016, 3, 30), datetime(2016, 4, 27), FB) plot_hilo(ax_fb, datetime(2016, 4, 28), datetime(2016, 5, 5), FB) ax_fb.vlines(date2num(datetime(2016, 4, 27, 12)), ax_fb.get_ylim()[0], ax_fb.get_ylim()[1], color='g', label='Earnings Release') ax_fb.legend(loc=2) ax_fb.set_title('FB Price History') f.set_size_inches(18, 6) As we can see above, the market broke a prevailing trend on Apple in order to go down, and ultimately predict the earnings release. For Facebook, the opposite happened. While the trend was down, the earnings were fantastic and the market corrected itself much higher. ","version":null,"tagName":"h2"},{"title":"Formulating the Question​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#formulating-the-question","content":" While these are two specific examples, there are plenty of other examples you could cite one way or another. Even if the preponderance of evidence shows that the market correctly predicts earnings releases, we need not accuse people of collusion; for a company like Apple with many suppliers we can generally forecast how Apple has done based on those same suppliers. The question then, is this: how well does the market predict the earnings releases? It's an incredibly broad question that I want to disect in a couple of different ways: Given a stock that has been trending down over the past N days before an earnings release, how likely does it continue downward after the release?Given a stock trending up, how likely does it continue up?Is there a difference in accuracy between large- and small-cap stocks?How often, and for how long, do markets trend before an earnings release? I want to especially thank Alejandro Saltiel for helping me retrieve the data. He's great. And now for all of the interesting bits. ","version":null,"tagName":"h2"},{"title":"Event Studies​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-studies","content":" Before we go too much further, I want to introduce the actual event study. Each chart intends to capture a lot of information and present an easy-to-understand pattern: Code import numpy as np import pandas as pd from pandas.tseries.holiday import USFederalHolidayCalendar from pandas.tseries.offsets import CustomBusinessDay from datetime import datetime, timedelta # If you remove rules, it removes them from *all* calendars # To ensure we don't pop rules we don't want to, first make # sure to fully copy the object trade_calendar = USFederalHolidayCalendar() trade_calendar.rules.pop(6) # Remove Columbus day trade_calendar.rules.pop(7) # Remove Veteran's day TradeDay = lambda days: CustomBusinessDay(days, calendar=trade_calendar) def plot_study(array): # Given a 2-d array, we assume the event happens at index `lookback`, # and create all of our summary statistics from there. lookback = int((array.shape[1] - 1) / 2) norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1) centered_data = array / norm_factor - 1 lookforward = centered_data.shape[1] - lookback means = centered_data.mean(axis=0) lookforward_data = centered_data[:,lookforward:] std_dev = np.hstack([0, lookforward_data.std(axis=0)]) maxes = lookforward_data.max(axis=0) mins = lookforward_data.min(axis=0) f, axarr = plt.subplots(1, 2) range_begin = -lookback range_end = lookforward axarr[0].plot(range(range_begin, range_end), means) axarr[1].plot(range(range_begin, range_end), means) axarr[0].fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") axarr[1].fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") max_err = maxes - means[-lookforward+1:] min_err = means[-lookforward+1:] - mins axarr[0].errorbar(range(1, range_end), means[-lookforward+1:], yerr=[min_err, max_err], label='Max & Min') axarr[0].legend(loc=2) axarr[1].legend(loc=2) axarr[0].set_xlim((-lookback-1, lookback+1)) axarr[1].set_xlim((-lookback-1, lookback+1)) def plot_study_small(array): # Given a 2-d array, we assume the event happens at index `lookback`, # and create all of our summary statistics from there. lookback = int((array.shape[1] - 1) / 2) norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1) centered_data = array / norm_factor - 1 lookforward = centered_data.shape[1] - lookback means = centered_data.mean(axis=0) lookforward_data = centered_data[:,lookforward:] std_dev = np.hstack([0, lookforward_data.std(axis=0)]) maxes = lookforward_data.max(axis=0) mins = lookforward_data.min(axis=0) range_begin = -lookback range_end = lookforward plt.plot(range(range_begin, range_end), means) plt.fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") max_err = maxes - means[-lookforward+1:] min_err = means[-lookforward+1:] - mins plt.errorbar(range(1, range_end), means[-lookforward+1:], yerr=[min_err, max_err], label='Max & Min') plt.legend(loc=2) plt.xlim((-lookback-1, lookback+1)) def fetch_event_data(ticker, events, horizon=5): # Use horizon+1 to account for including the day of the event, # and half-open interval - that is, for a horizon of 5, # we should be including 11 events. Additionally, using the # CustomBusinessDay means we automatically handle issues if # for example a company reports Friday afternoon - the date # calculator will turn this into a "Saturday" release, but # we effectively shift that to Monday with the logic below. td_back = TradeDay(horizon+1) td_forward = TradeDay(horizon+1) start_date = min(events) - td_back end_date = max(events) + td_forward total_data = fetch_ticker(ticker, start_date, end_date) event_data = [total_data.ix[event-td_back:event+td_forward]\\ [0:horizon*2+1]\\ ['Adjusted Close'] for event in events] return np.array(event_data) # Generate a couple of random events event_dates = [datetime(2016, 5, 27) - timedelta(days=1) - TradeDay(x*20) for x in range(1, 40)] data = fetch_event_data('CELG', event_dates) plot_study_small(data) plt.legend(loc=3) plt.gcf().set_size_inches(12, 6); plt.annotate('Mean price for days leading up to each event', (-5, -.01), (-4.5, .025), arrowprops=dict(facecolor='black', shrink=0.05)) plt.annotate('', (-.1, .005), (-.5, .02), arrowprops={'facecolor': 'black', 'shrink': .05}) plt.annotate('$\\pm$ 1 std. dev. each day', (5, .055), (2.5, .085), arrowprops={'facecolor': 'black', 'shrink': .05}) plt.annotate('Min/Max each day', (.9, -.07), (-1, -.1), arrowprops={'facecolor': 'black', 'shrink': .05}); And as a quick textual explanation as well: The blue line represents the mean price for each day, represented as a percentage of the price on the '0-day'. For example, if we defined an 'event' as whenever the stock price dropped for three days, we would see a decreasing blue line to the left of the 0-day.The blue shaded area represents one standard deviation above and below the mean price for each day following an event. This is intended to give us an idea of what the stock price does in general following an event.The green bars are the minimum and maximum price for each day following an event. This instructs us as to how much it's possible for the stock to move. ","version":null,"tagName":"h2"},{"title":"Event Type 1: Trending down over the past N days​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-type-1-trending-down-over-the-past-n-days","content":" The first type of event I want to study is how stocks perform when they've been trending down over the past couple of days prior to a release. However, we need to clarify what exactly is meant by "trending down." To do so, we'll use the following metric: the midpoint between each day's opening and closing price goes down over a period of N days. It's probably helpful to have an example: Code f, axarr = plt.subplots(1, 2) f.set_size_inches(18, 6) FB_plot = axarr[0] ohlc_dataframe(FB[datetime(2016, 4, 18):], FB_plot) FB_truncated = FB[datetime(2016, 4, 18):datetime(2016, 4, 27)] midpoint = FB_truncated['Open']/2 + FB_truncated['Close']/2 FB_plot.plot(FB_truncated.index, midpoint, label='Midpoint') FB_plot.vlines(date2num(datetime(2016, 4, 27, 12)), ax_fb.get_ylim()[0], ax_fb.get_ylim()[1], color='g', label='Earnings Release') FB_plot.legend(loc=2) FB_plot.set_title('FB Midpoint Plot') AAPL_plot = axarr[1] ohlc_dataframe(AAPL[datetime(2016, 4, 10):], AAPL_plot) AAPL_truncated = AAPL[datetime(2016, 4, 10):datetime(2016, 4, 26)] midpoint = AAPL_truncated['Open']/2 + AAPL_truncated['Close']/2 AAPL_plot.plot(AAPL_truncated.index, midpoint, label='Midpoint') AAPL_plot.vlines(date2num(datetime(2016, 4, 26, 12)), ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1], color='g', label='Earnings Release') AAPL_plot.legend(loc=3) AAPL_plot.set_title('AAPL Midpoint Plot'); Given these charts, we can see that FB was trending down for the four days preceding the earnings release, and AAPL was trending down for a whopping 8 days (we don't count the peak day). This will define the methodology that we will use for the study. So what are the results? For a given horizon, how well does the market actually perform? Code # Read in the events for each stock; # The file was created using the first code block in the Appendix import yaml from dateutil.parser import parse from progressbar import ProgressBar data_str = open('earnings_dates.yaml', 'r').read() # Need to remove invalid lines filtered = filter(lambda x: '{' not in x, data_str.split('\\n')) earnings_data = yaml.load('\\n'.join(filtered)) # Convert our earnings data into a list of (ticker, date) pairs # to make it easy to work with. # This is horribly inefficient, but should get us what we need ticker_dates = [] for ticker, date_list in earnings_data.items(): for iso_str in date_list: ticker_dates.append((ticker, parse(iso_str))) def does_trend_down(ticker, event, horizon): # Figure out if the `event` has a downtrend for # the `horizon` days preceding it # As an interpretation note: it is assumed that # the closing price of day `event` is the reference # point, and we want `horizon` days before that. # The price_data.hdf was created in the second appendix code block try: ticker_data = pd.read_hdf('price_data.hdf', ticker) data = ticker_data[event-TradeDay(horizon):event] midpoints = data['Open']/2 + data['Close']/2 # Shift dates one forward into the future and subtract # Effectively: do we trend down over all days? elems = midpoints - midpoints.shift(1) return len(elems)-1 == len(elems.dropna()[elems <= 0]) except KeyError: # If the stock doesn't exist, it doesn't qualify as trending down # Mostly this is here to make sure the entire analysis doesn't # blow up if there were issues in data retrieval return False def study_trend(horizon, trend_function): five_day_events = np.zeros((1, horizon*2 + 1)) invalid_events = [] for ticker, event in ProgressBar()(ticker_dates): if trend_function(ticker, event, horizon): ticker_data = pd.read_hdf('price_data.hdf', ticker) event_data = ticker_data[event-TradeDay(horizon):event+TradeDay(horizon)]['Close'] try: five_day_events = np.vstack([five_day_events, event_data]) except ValueError: # Sometimes we don't get exactly the right number of values due to calendar # issues. I've fixed most everything I can, and the few issues that are left # I assume don't systemically bias the results (i.e. data could be missing # because it doesn't exist, etc.). After running through, ~1% of events get # discarded this way invalid_events.append((ticker, event)) # Remove our initial zero row five_day_events = five_day_events[1:,:] plot_study(five_day_events) plt.gcf().suptitle('Action over {} days: {} events' .format(horizon,five_day_events.shape[0])) plt.gcf().set_size_inches(18, 6) # Start with a 5 day study study_trend(5, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:21:38 Time: 0:21:38 When a stock has been trending down for 5 days, once the earnings are announced it really doesn't move on average. However, the variability is incredible. This implies two important things: The market is just as often wrong about an earnings announcement before it happens as it is correctThe incredible width of the min/max bars and standard deviation area tell us that the market reacts violently after the earnings are released. Let's repeat the same study, but over a time horizon of 8 days and 3 days. Presumably if a stock has been going down for 8 days at a time before the earnings, the market should be more accurate. Code # 8 day study next study_trend(8, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:29 Time: 0:20:29 However, looking only at stocks that trended down for 8 days prior to a release, the same pattern emerges: on average, the stock doesn't move, but the market reaction is often incredibly violent. Code # 3 day study after that study_trend(3, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:26 Time: 0:26:26 Finally, when we look at a 3-day horizon, we start getting some incredible outliers. Stocks have a potential to move over ~300% up, and the standard deviation width is again, incredible. The results for a 3-day horizon follow the same pattern we've seen in the 5- and 8-day horizons. ","version":null,"tagName":"h2"},{"title":"Event Type 2: Trending up for N days​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-type-2-trending-up-for-n-days","content":" We're now going to repeat the analysis, but do it for uptrends instead. That is, instead of looking at stocks that have been trending down over the past number of days, we focus only on stocks that have been trending up. Code def does_trend_up(ticker, event, horizon): # Figure out if the `event` has an uptrend for # the `horizon` days preceding it # As an interpretation note: it is assumed that # the closing price of day `event` is the reference # point, and we want `horizon` days before that. # The price_data.hdf was created in the second appendix code block try: ticker_data = pd.read_hdf('price_data.hdf', ticker) data = ticker_data[event-TradeDay(horizon):event] midpoints = data['Open']/2 + data['Close']/2 # Shift dates one forward into the future and subtract # Effectively: do we trend down over all days? elems = midpoints - midpoints.shift(1) return len(elems)-1 == len(elems.dropna()[elems >= 0]) except KeyError: # If the stock doesn't exist, it doesn't qualify as trending down # Mostly this is here to make sure the entire analysis doesn't # blow up if there were issues in data retrieval return False study_trend(5, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:22:51 Time: 0:22:51 The patterns here are very similar. With the exception of noting that stocks can go to nearly 400% after an earnings announcement (most likely this included a takeover announcement, etc.), we still see large min/max bars and wide standard deviation of returns. We'll repeat the pattern for stocks going up for both 8 and 3 days straight, but at this point, the results should be very predictable: Code study_trend(8, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:51 Time: 0:20:51 Code study_trend(3, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:56 Time: 0:26:56 ","version":null,"tagName":"h2"},{"title":"Conclusion and Summary​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#conclusion-and-summary","content":" I guess the most important thing to summarize with is this: looking at the entire market, stock performance prior to an earnings release has no bearing on the stock's performance. Honestly: given the huge variability of returns after an earnings release, even when the stock has been trending for a long time, you're best off divesting before an earnings release and letting the market sort itself out. However, there is a big caveat. These results are taken when we look at the entire market. So while we can say that the market as a whole knows nothing and just reacts violently, I want to take a closer look into this data. Does the market typically perform poorly on large-cap/high liquidity stocks? Do smaller companies have investors that know them better and can thus predict performance better? Are specific market sectors better at prediction? Presumably technology stocks are more volatile than the industrials. So there are some more interesting questions I still want to ask with this data. Knowing that the hard work of data processing is largely already done, it should be fairly simple to continue this analysis and get much more refined with it. Until next time. Appendix Export event data for Russell 3000 companies: Code import pandas as pd from html.parser import HTMLParser from datetime import datetime, timedelta import requests import re from dateutil import parser import progressbar from concurrent import futures import yaml class EarningsParser(HTMLParser): store_dates = False earnings_offset = None dates = [] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dates = [] def handle_starttag(self, tag, attrs): if tag == 'table': self.store_dates = True def handle_data(self, data): if self.store_dates: match = re.match(r'\\d+/\\d+/\\d+', data) if match: self.dates.append(match.group(0)) # If a company reports before the bell, record the earnings date # being at midnight the day before. Ex: WMT reports 5/19/2016, # but we want the reference point to be the closing price on 5/18/2016 if 'After Close' in data: self.earnings_offset = timedelta(days=0) elif 'Before Open' in data: self.earnings_offset = timedelta(days=-1) def handle_endtag(self, tag): if tag == 'table': self.store_dates = False def earnings_releases(ticker): #print("Looking up ticker {}".format(ticker)) user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) '\\ 'Gecko/20100101 Firefox/46.0' headers = {'user-agent': user_agent} base_url = 'http://www.streetinsider.com/ec_earnings.php?q={}'\\ .format(ticker) e = EarningsParser() s = requests.Session() a = requests.adapters.HTTPAdapter(max_retries=0) s.mount('http://', a) e.feed(str(s.get(base_url, headers=headers).content)) if e.earnings_offset is not None: dates = map(lambda x: parser.parse(x) + e.earnings_offset, e.dates) past = filter(lambda x: x < datetime.now(), dates) return list(map(lambda d: d.isoformat(), past)) # Use a Russell-3000 ETF tracker (ticker IWV) to get a list of holdings r3000 = pd.read_csv('https://www.ishares.com/us/products/239714/' 'ishares-russell-3000-etf/1449138789749.ajax?' 'fileType=csv&fileName=IWV_holdings&dataType=fund', header=10) r3000_equities = r3000[(r3000['Exchange'] == 'NASDAQ') | (r3000['Exchange'] == 'New York Stock Exchange Inc.')] dates_file = open('earnings_dates.yaml', 'w') with futures.ThreadPoolExecutor(max_workers=8) as pool: fs = {pool.submit(earnings_releases, r3000_equities.ix[t]['Ticker']): t for t in r3000_equities.index} pbar = progressbar.ProgressBar(term_width=80, max_value=r3000_equities.index.max()) for future in futures.as_completed(fs): i = fs[future] pbar.update(i) dates_file.write(yaml.dump({r3000_equities.ix[i]['Ticker']: future.result()})) Downloading stock price data needed for the event studies: Code from secrets import QUANDL_KEY import pandas as pd import yaml from dateutil.parser import parse from datetime import timedelta import quandl from progressbar import ProgressBar def fetch_ticker(ticker, start, end): # Quandl is currently giving me issues with returning # the entire dataset and not slicing server-side. # So instead, we'll do it client-side! q_format = '%Y-%m-%d' ticker_data = quandl.get('YAHOO/' + ticker, start_date=start.strftime(q_format), end_date=end.strftime(q_format), authtoken=QUANDL_KEY) return ticker_data data_str = open('earnings_dates.yaml', 'r').read() # Need to remove invalid lines filtered = filter(lambda x: '{' not in x, data_str.split('\\n')) earnings_data = yaml.load('\\n'.join(filtered)) # Get the first 1500 keys - split up into two statements # because of Quandl rate limits tickers = list(earnings_data.keys()) price_dict = {} invalid_tickers = [] for ticker in ProgressBar()(tickers[0:1500]): try: # Replace '.' with '-' in name for some tickers fixed = ticker.replace('.', '-') event_strs = earnings_data[ticker] events = [parse(event) for event in event_strs] td = timedelta(days=20) price_dict[ticker] = fetch_ticker(fixed, min(events)-td, max(events)+td) except quandl.NotFoundError: invalid_tickers.append(ticker) # Execute this after 10 minutes have passed for ticker in ProgressBar()(tickers[1500:]): try: # Replace '.' with '-' in name for some tickers fixed = ticker.replace('.', '-') event_strs = earnings_data[ticker] events = [parse(event) for event in event_strs] td = timedelta(days=20) price_dict[ticker] = fetch_ticker(fixed, min(events)-td, max(events)+td) except quandl.NotFoundError: invalid_tickers.append(ticker) prices_store = pd.HDFStore('price_data.hdf') for ticker, prices in price_dict.items(): prices_store[ticker] = prices ","version":null,"tagName":"h2"},{"title":"A Rustic re-podcasting server","type":0,"sectionRef":"#","url":"/2016/10/rustic-repodcasting","content":"","keywords":"","version":null},{"title":"The Setup​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#the-setup","content":" We'll be using the iron library to handle the server, and hyper to fetch the data we need from elsewhere on the interwebs. HTML5Ever allows us to ingest the content that will be coming from Bassdrive, and finally, output is done with handlebars-rust. It will ultimately be interesting to see how much more work must be done to actually get this working over another language like Python. Coming from a dynamic state of mind it's super easy to just chain stuff together, ship it out, and call it a day. I think I'm going to end up getting much dirtier trying to write all of this out. ","version":null,"tagName":"h2"},{"title":"Issue 1: Strings​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#issue-1-strings","content":" Strings in Rust are hard. I acknowledge Python can get away with some things that make strings super easy (and Python 3 has gotten better at cracking down on some bad cases, str <-> bytes specifically), but Rust is hard. Let's take for example the 404 error handler I'm trying to write. The result should be incredibly simple: All I want is to echo backDidn't find URL: <url>. Shouldn't be that hard right? In Python I'd just do something like: def echo_handler(request): return "You're visiting: {}".format(request.uri) And we'd call it a day. Rust isn't so simple. Let's start with the trivial examples people post online: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, "You found the server!"))) } Doesn't look too bad right? In fact, it's essentially the same as the Python version! All we need to do is just send back a string of some form. So, we look up the documentation for Request and see a url field that will contain what we want. Let's try the first iteration: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, "You found the URL: " + req.url))) } Which yields the error: error[E0369]: binary operation `+` cannot be applied to type `&'static str` OK, what's going on here? Time to start Googling for "concatenate strings in Rust". That's what we want to do right? Concatenate a static string and the URL. After Googling, we come across a helpful concat! macro that looks really nice! Let's try that one: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, concat!("You found the URL: ", req.url)))) } And the error: error: expected a literal Turns out Rust actually blows up because the concat! macro expects us to know at compile time what req.url is. Which, in my outsider opinion, is a bit strange. println! and format!, etc., all handle values they don't know at compile time. Why can't concat!? By any means, we need a new plan of attack. How about we try formatting strings? fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, format!("You found the URL: {}", req.url)))) } And at long last, it works. Onwards! ","version":null,"tagName":"h2"},{"title":"Issue 2: Fighting with the borrow checker​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#issue-2-fighting-with-the-borrow-checker","content":" Rust's single coolest feature is how the compiler can guarantee safety in your program. As long as you don't use unsafe pointers in Rust, you're guaranteed safety. And not having truly manual memory management is really cool; I'm totally OK with never having to write malloc() again. That said, even the Rust documentation makes a specific note: Many new users to Rust experience something we like to call ‘fighting with the borrow checker’, where the Rust compiler refuses to compile a program that the author thinks is valid. If you have to put it in the documentation, it's not a helpful note: it's hazing. So now that we have a handler which works with information from the request, we want to start making something that looks like an actual web application. The router provided by iron isn't terribly difficult so I won't cover it. Instead, the thing that had me stumped for a couple hours was trying to dynamically create routes. The unfortunate thing with Rust (in my limited experience at the moment) is that there is a severe lack of non-trivial examples. Using the router is easy when you want to give an example of a static function. But how do you you start working on things that are a bit more complex? We're going to cover that here. Our first try: creating a function which returns other functions. This is a principle called currying. We set up a function that allows us to keep some data in scope for another function to come later. fn build_handler(message: String) -> Fn(&mut Request) -> IronResult<Response> { move |_: &mut Request| { Ok(Response::with((status::Ok, message))) } } We've simply set up a function that returns another anonymous function with themessage parameter scoped in. If you compile this, you get not 1, not 2, but 5 new errors. 4 of them are the same though: error[E0277]: the trait bound `for<'r, 'r, 'r> std::ops::Fn(&'r mut iron::Request<'r, 'r>) -> std::result::Result<iron::Response, iron::IronError> + 'static: std::marker::Sized` is not satisfied ...oookay. I for one, am not going to spend time trying to figure out what's going on there. And it is here that I will save the audience many hours of frustrated effort. At this point, I decided to switch from iron to pure hyper since usinghyper would give me a much simpler API. All I would have to do is build a function that took two parameters as input, and we're done. That said, it ultimately posed many more issues because I started getting into a weird fight with the 'static lifetimeand being a Rust newbie I just gave up on trying to understand it. Instead, we will abandon (mostly) the curried function attempt, and instead take advantage of something Rust actually intends us to use: struct andtrait. Remember when I talked about a lack of non-trivial examples on the Internet? This is what I was talking about. I could only find one example of this available online, and it was incredibly complex and contained code we honestly don't need or care about. There was no documentation of how to build routes that didn't use static functions, etc. But, I'm assuming you don't really care about my whining, so let's get to it. The iron documentation mentions the Handler trait as being something we can implement. Does the function signature for that handle() method look familiar? It's what we've been working with so far. The principle is that we need to define a new struct to hold our data, then implement that handle() method to return the result. Something that looks like this might do: struct EchoHandler { message: String } impl Handler for EchoHandler { fn handle(&self, _: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, self.message))) } } // Later in the code when we set up the router... let echo = EchoHandler { message: "Is it working yet?" } router.get("/", echo.handle, "index"); We attempt to build a struct, and give its handle method off to the router so the router knows what to do. You guessed it, more errors: error: attempted to take value of method `handle` on type `EchoHandler` Now, the Rust compiler is actually a really nice fellow, and offers us help: help: maybe a `()` to call it is missing? If not, try an anonymous function We definitely don't want to call that function, so maybe try an anonymous function as it recommends? router.get("/", |req: &mut Request| echo.handle(req), "index"); Another error: error[E0373]: closure may outlive the current function, but it borrows `echo`, which is owned by the current function Another helpful message: help: to force the closure to take ownership of `echo` (and any other referenced variables), use the `move` keyword We're getting closer though! Let's implement this change: router.get("/", move |req: &mut Request| echo.handle(req), "index"); And here's where things get strange: error[E0507]: cannot move out of borrowed content --> src/main.rs:18:40 | 18 | Ok(Response::with((status::Ok, self.message))) | ^^^^ cannot move out of borrowed content Now, this took me another couple hours to figure out. I'm going to explain it, but keep this in mind: Rust only allows one reference at a time (exceptions apply of course). When we attempt to use self.message as it has been created in the earlierstruct, we essentially are trying to give it away to another piece of code. Rust's semantics then state that we may no longer access it unless it is returned to us (which iron's code does not do). There are two ways to fix this: Only give away references (i.e. &self.message instead of self.message) instead of transferring ownershipMake a copy of the underlying value which will be safe to give away I didn't know these were the two options originally, so I hope this helps the audience out. Because iron won't accept a reference, we are forced into the second option: making a copy. To do so, we just need to change the function to look like this: Ok(Response::with((status::Ok, self.message.clone()))) Not so bad, huh? My only complaint is that it took so long to figure out exactly what was going on. And now we have a small server that we can configure dynamically. At long last. Final sidenote: You can actually do this without anonymous functions. Just change the router line to:router.get("/", echo, "index"); Rust's type system seems to figure out that we want to use the handle() method. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#conclusion","content":" After a good long days' work, we now have the routing functionality set up on our application. We should be able to scale this pretty well in the future: the RSS content we need to deliver in the future can be treated as a string, so the building blocks are in place. There are two important things I learned starting with Rust today: Rust is a new language, and while the code is high-quality, the mindshare is coming.I'm a terrible programmer. Number 1 is pretty obvious and not surprising to anyone. Number two caught me off guard. I've gotten used to having either a garbage collector (Java, Python, etc.) or playing a little fast and loose with scoping rules (C, C++). You don't have to worry about object lifetime there. With Rust, it's forcing me to fully understand and use well the memory in my applications. In the final mistake I fixed (using .clone()) I would have been fine in C++ to just give away that reference and never use it again. I wouldn't have run into a "use-after-free" error, but I would have potentially been leaking memory. Rust forced me to be incredibly precise about how I use it. All said I'm excited for using Rust more. I think it's super cool, it's just going to take me a lot longer to do this than I originally thought. ","version":null,"tagName":"h2"},{"title":"PCA audio compression","type":0,"sectionRef":"#","url":"/2016/11/pca-audio-compression","content":"","keywords":"","version":null},{"title":"Towards a new (and pretty poor) compression scheme​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#towards-a-new-and-pretty-poor-compression-scheme","content":" I'm going to be working with some audio data for a while as I get prepared for a term project this semester. I'll be working (with a partner) to design a system for separating voices from music. Given my total lack of experience with Digital Signal Processing I figured that now was as good a time as ever to work on a couple of fun projects that would get me back up to speed. The first project I want to work on: Designing a new compression scheme for audio data. ","version":null,"tagName":"h2"},{"title":"A Brief Introduction to Audio Compression​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-brief-introduction-to-audio-compression","content":" Audio files when uncompressed (files ending with .wav) are huge. Like, 10.5 Megabytes per minute huge. Storage is cheap these days, but that's still an incredible amount of data that we don't really need. Instead, we'd like to compress that data so that it's not taking up so much space. There are broadly two ways to accomplish this: Lossless compression - Formats like FLAC, ALAC, and Monkey's Audio (.ape) all go down this route. The idea is that when you compress and uncompress a file, you get exactly the same as what you started with. Lossy compression - Formats like MP3, Ogg, and AAC (.m4a) are far more popular, but make a crucial tradeoff: We can reduce the file size even more during compression, but the decompressed file won't be the same. There is a fundamental tradeoff at stake: Using lossy compression sacrifices some of the integrity of the resulting file to save on storage space. Most people (I personally believe it's everybody) can't hear the difference, so this is an acceptable tradeoff. You have files that take up a 10th of the space, and nobody can tell there's a difference in audio quality. ","version":null,"tagName":"h2"},{"title":"A PCA-based Compression Scheme​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-pca-based-compression-scheme","content":" What I want to try out is a PCA approach to encoding audio. The PCA technique comes from Machine Learning, where it is used for a process called Dimensionality Reduction. Put simply, the idea is the same as lossy compression: if we can find a way that represents the data well enough, we can save on space. There are a lot of theoretical concerns that lead me to believe this compression style will not end well, but I'm interested to try it nonetheless. PCA works as follows: Given a dataset with a number of features, I find a way to approximate those original features using some "new features" that are statistically as close as possible to the original ones. This is comparable to a scheme like MP3: Given an original signal, I want to find a way of representing it that gets approximately close to what the original was. The difference is that PCA is designed for statistical data, and not signal data. But we won't let that stop us. The idea is as follows: Given a signal, reshape it into 1024 columns by however many rows are needed (zero-padded if necessary). Run the PCA algorithm, and do dimensionality reduction with a couple different settings. The number of components I choose determines the quality: If I use 1024 components, I will essentially be using the original signal. If I use a smaller number of components, I start losing some of the data that was in the original file. This will give me an idea of whether it's possible to actually build an encoding scheme off of this, or whether I'm wasting my time. ","version":null,"tagName":"h2"},{"title":"Running the Algorithm​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#running-the-algorithm","content":" The audio I will be using comes from the song Tabulasa, by Broke for Free. I'll be loading in the audio signal to Python and using Scikit-Learn to actually run the PCA algorithm. We first need to convert the FLAC file I have to a WAV: !ffmpeg -hide_banner -loglevel panic -i "Broke For Free/XXVII/01 Tabulasa.flac" "Tabulasa.wav" -c wav Then, let's go ahead and load a small sample so you can hear what is going on. from IPython.display import Audio from scipy.io import wavfile samplerate, tabulasa = wavfile.read('Tabulasa.wav') start = samplerate * 14 # 10 seconds in end = start + samplerate * 10 # 5 second duration Audio(data=tabulasa[start:end, 0], rate=samplerate) Next, we'll define the code we will be using to do PCA. It's very short, as the PCA algorithm is very simple. from sklearn.decomposition import PCA import numpy as np def pca_reduce(signal, n_components, block_size=1024): # First, zero-pad the signal so that it is divisible by the block_size samples = len(signal) hanging = block_size - np.mod(samples, block_size) padded = np.lib.pad(signal, (0, hanging), 'constant', constant_values=0) # Reshape the signal to have 1024 dimensions reshaped = padded.reshape((len(padded) // block_size, block_size)) # Second, do the actual PCA process pca = PCA(n_components=n_components) pca.fit(reshaped) transformed = pca.transform(reshaped) reconstructed = pca.inverse_transform(transformed).reshape((len(padded))) return pca, transformed, reconstructed Now that we've got our functions set up, let's try actually running something. First, we'll use n_components == block_size, which implies that we should end up with the same signal we started with. tabulasa_left = tabulasa[:,0] _, _, reconstructed = pca_reduce(tabulasa_left, 1024, 1024) Audio(data=reconstructed[start:end], rate=samplerate) OK, that does indeed sound like what we originally had. Let's drastically cut down the number of components we're doing this with as a sanity check: the audio quality should become incredibly poor. _, _, reconstructed = pca_reduce(tabulasa_left, 32, 1024) Audio(data=reconstructed[start:end], rate=samplerate) As expected, our reconstructed audio does sound incredibly poor! But there's something else very interesting going on here under the hood. Did you notice that the bassline comes across very well, but that there's no midrange or treble? The drums are almost entirely gone. ","version":null,"tagName":"h2"},{"title":"Drop the (Treble)​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#drop-the-treble","content":" It will help to understand PCA more fully when trying to read this part, but I'll do my best to break it down. PCA tries to find a way to best represent the dataset using "components." Think of each "component" as containing some of the information you need in order to reconstruct the full audio. For example, you might have a "low frequency" component that contains all the information you need in order to hear the bassline. There might be other components that explain the high frequency things like singers, or melodies, that you also need. What makes PCA interesting is that it attempts to find the "most important" components in explaining the signal. In a signal processing world, this means that PCA is trying to find the signal amongst the noise in your data. In our case, this means that PCA, when forced to work with small numbers of components, will chuck out the noisy components first. It's doing it's best job to reconstruct the signal, but it has to make sacrifices somewhere. So I've mentioned that PCA identifies the "noisy" components in our dataset. This is equivalent to saying that PCA removes the "high frequency" components in this case: it's very easy to represent a low-frequency signal like a bassline. It's far more difficult to represent a high-frequency signal because it's changing all the time. When you force PCA to make a tradeoff by using a small number of components, the best it can hope to do is replicate the low-frequency sections and skip the high-frequency things. This is a very interesting insight, and it also has echos (pardon the pun) of how humans understand music in general. Other encoding schemes (like MP3, etc.) typically chop off a lot of the high-frequency range as well. There is typically a lot of high-frequency noise in audio that is nearly impossible to hear, so it's easy to remove it without anyone noticing. PCA ends up doing something similar, and while that certainly wasn't the intention, it is an interesting effect. ","version":null,"tagName":"h2"},{"title":"A More Realistic Example​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-more-realistic-example","content":" So we've seen the edge cases so far: Using a large number of components results in audio very close to the original, and using a small number of components acts as a low-pass filter. How about we develop something that sounds "good enough" in practice, that we can use as a benchmark for size? We'll use ourselves as judges of audio quality, and build another function to help us estimate how much space we need to store everything in. from bz2 import compress import pandas as pd def raw_estimate(transformed, pca): # We assume that we'll be storing things as 16-bit WAV, # meaning two bytes per sample signal_bytes = transformed.tobytes() # PCA stores the components as floating point, we'll assume # that means 32-bit floats, so 4 bytes per element component_bytes = transformed.tobytes() # Return a result in megabytes return (len(signal_bytes) + len(component_bytes)) / (2**20) # Do an estimate for lossless compression applied on top of our # PCA reduction def bz2_estimate(transformed, pca): bytestring = transformed.tobytes() + b';' + pca.components_.tobytes() compressed = compress(bytestring) return len(compressed) / (2**20) compression_attempts = [ (1, 1), (1, 2), (1, 4), (4, 32), (16, 256), (32, 256), (64, 256), (128, 1024), (256, 1024), (512, 1024), (128, 2048), (256, 2048), (512, 2048), (1024, 2048) ] def build_estimates(signal, n_components, block_size): pca, transformed, recon = pca_reduce(tabulasa_left, n_components, block_size) raw_pca_estimate = raw_estimate(transformed, pca) bz2_pca_estimate = bz2_estimate(transformed, pca) raw_size = len(recon.tobytes()) / (2**20) return raw_size, raw_pca_estimate, bz2_pca_estimate pca_compression_results = pd.DataFrame([ build_estimates(tabulasa_left, n, bs) for n, bs in compression_attempts ]) pca_compression_results.columns = ["Raw", "PCA", "PCA w/ BZ2"] pca_compression_results.index = compression_attempts pca_compression_results \tRaw\tPCA\tPCA w/ BZ2(1, 1)\t69.054298\t138.108597\t16.431797 (1, 2)\t69.054306\t69.054306\t32.981380 (1, 4)\t69.054321\t34.527161\t16.715032 (4, 32)\t69.054443\t17.263611\t8.481735 (16, 256)\t69.054688\t8.631836\t4.274846 (32, 256)\t69.054688\t17.263672\t8.542909 (64, 256)\t69.054688\t34.527344\t17.097543 (128, 1024)\t69.054688\t17.263672\t9.430644 (256, 1024)\t69.054688\t34.527344\t18.870387 (512, 1024)\t69.054688\t69.054688\t37.800940 (128, 2048)\t69.062500\t8.632812\t6.185015 (256, 2048)\t69.062500\t17.265625\t12.366942 (512, 2048)\t69.062500\t34.531250\t24.736506 (1024, 2048)\t69.062500\t69.062500\t49.517493 As we can see, there are a couple of instances where we do nearly 20 times better on storage space than the uncompressed file. Let's here what that sounds like: _, _, reconstructed = pca_reduce(tabulasa_left, 16, 256) Audio(data=reconstructed[start:end], rate=samplerate) It sounds incredibly poor though. Let's try something that's a bit more realistic: _, _, reconstructed = pca_reduce(tabulasa_left, 1, 4) Audio(data=reconstructed[start:end], rate=samplerate) And just out of curiosity, we can try something that has the same ratio of components to block size. This should be close to an apples-to-apples comparison. _, _, reconstructed = pca_reduce(tabulasa_left, 64, 256) Audio(data=reconstructed[start:end], rate=samplerate) The smaller block size definitely has better high-end response, but I personally think the larger block size sounds better overall. ","version":null,"tagName":"h2"},{"title":"Conclusions​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#conclusions","content":" So, what do I think about audio compression using PCA? Strangely enough, it actually works pretty well relative to what I expected. That said, it's a terrible idea in general. First off, you don't really save any space. The component matrix needed to actually run the PCA algorithm takes up a lot of space on its own, so it's very difficult to save space without sacrificing a huge amount of audio quality. And even then, codecs like AAC sound very nice even at bitrates that this PCA method could only dream of. Second, there's the issue of audio streaming. PCA relies on two components: the datastream, and a matrix used to reconstruct the original signal. While it is easy to stream the data, you can't stream that matrix. And even if you divided the stream up into small blocks to give you a small matrix, you must guarantee that the matrix arrives; if you don't have that matrix, the data stream will make no sense whatsoever. All said, this was an interesting experiment. It's really cool seeing PCA used for signal analysis where I haven't seen it applied before, but I don't think it will lead to any practical results. Look forward to more signal processing stuff in the future! ","version":null,"tagName":"h2"},{"title":"Captain's Cookbook: Project setup","type":0,"sectionRef":"#","url":"/2018/01/captains-cookbook-part-1","content":"","keywords":"","version":null},{"title":"Step 1: Installing capnp​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-1-installing-capnp","content":" The capnp binary itself is needed for taking the schema files you write and turning them into a format that can be used by the code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed. I'll refer you to Cap'N Proto's installation instructions here. As a quick TLDR though: Linux users will likely have a binary shipped by their package manager - On Ubuntu, apt install capnproto is enoughOS X users can use Homebrew as an easy install path. Just brew install capnpWindows users are a bit more complicated. If you're using Chocolatey, there's a package available. If that doesn't work however, you need to download a release zip and make sure that the capnp.exe binary is in your %PATH% environment variable The way you know you're done with this step is if the following command works in your shell: capnp id ","version":null,"tagName":"h2"},{"title":"Step 2: Starting a Cap'N Proto Rust project​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-2-starting-a-capn-proto-rust-project","content":" After the capnp binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple mkdir capnp_cookbook_1 cd capnp_cookbook_1 cargo init --bin We'll put the following content into Cargo.toml: [package] name = "capnp_cookbook_1" version = "0.1.0" authors = ["Bradlee Speice <bspeice@kcg.com>"] [build-dependencies] capnpc = "0.8" # 1 [dependencies] capnp = "0.8" # 2 This sets up: The Rust code generator (CAPNProto Compiler)The Cap'N Proto runtime library (CAPNProto runtime) We've now got everything prepared that we need for writing a Cap'N Proto project. ","version":null,"tagName":"h2"},{"title":"Step 3: Writing a basic schema​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-3-writing-a-basic-schema","content":" We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure you get familiar with how to start from a basic project. First, we're going to create a top-level directory for storing the schema files in: # Assuming we're starting from the `capnp_cookbook_1` directory created earlier mkdir schema cd schema Now, we're going to put the following content in point.capnp: @0xab555145c708dad2; struct Point { x @0 :Int32; y @1 :Int32; } Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format. ","version":null,"tagName":"h2"},{"title":"Step 4: Setting up the build process​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-4-setting-up-the-build-process","content":" Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using. This is typically done through a build.rs file to invoke the schema compiler. In the same folder as your Cargo.toml file, please put the following content in build.rs: extern crate capnpc; fn main() { ::capnpc::CompilerCommand::new() .src_prefix("schema") // 1 .file("schema/point.capnp") // 2 .run().expect("compiling schema"); } This sets up the protocol compiler (capnpc from earlier) to compile the schema we've built so far. Because Cap'N Proto schema files can re-use types specified in other files, the src_prefix() tells the compiler where to look for those extra files at.We specify the schema file we're including by hand. In a much larger project, you could presumably build the CompilerCommanddynamically, but we won't worry too much about that one for now. ","version":null,"tagName":"h2"},{"title":"Step 5: Running the build​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-5-running-the-build","content":" If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code. Run a cargo build command, and if you don't see cargo complaining, you're doing just fine! So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives somewhere in the target/ directory. The long answer is that you're best off running a find command to get the actual file path: # Assuming we're running from the capnp_cookbook_1 project folder find . -name point_capnp.rs Alternately, if the find command isn't available, the path will look something like: ./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs See if there are any paths in your target directory that look similar. Now, the file content looks pretty nasty. I've included an example hereif you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how the schema we wrote for the "Point" message is tied to the generated code. First, the Cap'N Proto library splits things up into Builder and Reader structs. These are best thought of the same way Rust separates mut from non-mut code. Builders are mut versions of your message, and Readers are immutable versions. For example, the Builder impl for point defines get_x(), set_x(), get_y(), and set_y() methods. In comparison, the Reader impl only defines get_x() and get_y() methods. So now we know that there are some get and set methods available for our x and y coordinates; but what do we actually do with those? ","version":null,"tagName":"h2"},{"title":"Step 6: Making a point​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-6-making-a-point","content":" So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code should go in src/main.rs: // Note that we use `capnp` here, NOT `capnpc` extern crate capnp; // We create a module here to define how we are to access the code // being included. pub mod point_capnp { // The environment variable OUT_DIR is set by Cargo, and // is the location of all the code that was built as part // of the codegen step. // point_capnp.rs is the actual file to include include!(concat!(env!("OUT_DIR"), "/point_capnp.rs")); } fn main() { // The process of building a Cap'N Proto message is a bit tedious. // We start by creating a generic Builder; it acts as the message // container that we'll later be filling with content of our `Point` let mut builder = capnp::message::Builder::new_default(); // Because we need a mutable reference to the `builder` later, // we fence off this part of the code to allow sequential mutable // borrows. As I understand it, non-lexical lifetimes: // https://github.com/rust-lang/rust-roadmap/issues/16 // will make this no longer necessary { // And now we can set up the actual message we're trying to create let mut point_msg = builder.init_root::<point_capnp::point::Builder>(); // Stuff our message with some content point_msg.set_x(12); point_msg.set_y(14); } // It's now time to serialize our message to binary. Let's set up a buffer for that: let mut buffer = Vec::new(); // And actually fill that buffer with our data capnp::serialize::write_message(&mut buffer, &builder).unwrap(); // Finally, let's deserialize the data let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); // `deserialized` is currently a generic reader; it understands // the content of the message we gave it (i.e. that there are two // int32 values) but doesn't really know what they represent (the Point). // This is where we map the generic data back into our schema. let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); // We can now get our x and y values back, and make sure they match assert_eq!(point_reader.get_x(), 12); assert_eq!(point_reader.get_y(), 14); } And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up some practical examples of Cap'N Proto in action: ","version":null,"tagName":"h2"},{"title":"Captain's Cookbook: Practical usage","type":0,"sectionRef":"#","url":"/2018/01/captains-cookbook-part-2","content":"","keywords":"","version":null},{"title":"Attempt 1: Move the reference​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-1-move-the-reference","content":" As a first attempt, we're going to try and let Rust move the reference. Our code will look something like: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from // somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); // By using `point_reader` inside the new thread, we're hoping that Rust can // safely move the reference and invalidate the original thread's usage. // Since the original thread doesn't use `point_reader` again, this should // be safe, right? let handle = std::thread:spawn(move || { assert_eq!(point_reader.get_x(), 12); assert_eq!(point_reader.get_y(), 14); }); handle.join().unwrap() } Well, the Rust compiler doesn't really like this. We get four distinct errors back: error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely | error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely | error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely | error: aborting due to 4 previous errors Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating. Pay attention to the text that keeps on getting repeated though: XYZ cannot be sent between threads safely. This is a bit frustrating: we own the buffer from which all the content was derived, and we don't have any unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust preventing us from doing something that really should be legal? This is what is known as fighting the borrow checker. Let our crusade begin. ","version":null,"tagName":"h2"},{"title":"Attempt 2: Put the Reader in a Box​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-2-put-the-reader-in-a-box","content":" The Box type allows us to convert a pointer we have (in our case the point_reader) into an "owned" value, which should be easier to send across threads. Our next attempt looks something like this: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content // from somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); let boxed_reader = Box::new(point_reader); // Now that the reader is `Box`ed, we've proven ownership, and Rust can // move the ownership to the new thread, right? let handle = std::thread::spawn(move || { assert_eq!(boxed_reader.get_x(), 12); assert_eq!(boxed_reader.get_y(), 14); }); handle.join().unwrap(); } Spoiler alert: still doesn't work. Same errors still show up. error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely | error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely | error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely | error: aborting due to 4 previous errors Let's be a little bit smarter about the exceptions this time though. What is thatstd::marker::Send thing the compiler keeps telling us about? The documentation is pretty clear; Send is used to denote: Types that can be transferred across thread boundaries. In our case, we are seeing the error messages for two reasons: Pointers (*const u8) are not safe to send across thread boundaries. While we're nice in our code making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make that assumption, and so complains that we're not using this in a safe manner. The point_capnp::point::Reader type is itself not safe to send across threads because it doesn't implement the Send trait. Which is to say, the things that make up a Reader are themselves not thread-safe, so the Reader is also not thread-safe. So, how are we to actually transfer a parsed Cap'N Proto message between threads? ","version":null,"tagName":"h2"},{"title":"Attempt 3: The TypedReader​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-3-the-typedreader","content":" The TypedReader is a new API implemented in the Cap'N Proto Rust code. We're interested in it here for two reasons: It allows us to define an object where the object owns the underlying data. In previous attempts, the current context owned the data, but the Reader itself had no such control. We can compose the TypedReader using objects that are safe to Send across threads, guaranteeing that we can transfer parsed messages across threads. The actual type info for the TypedReaderis a bit complex. And to be honest, I'm still really not sure what the whole point of thePhantomData thing is either. My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto message represents. That is, technically the only thing we're storing is the untyped binary message;PhantomData just enforces the principle that the binary represents some specific object that has been parsed. Either way, we can carefully construct something which is safe to move between threads: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> = capnp::message::TypedReader::new(deserialized); // Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message // (which is 'static lifetime), this is now safe let handle = std::thread::spawn(move || { // The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader // object from it let point_root = point_reader.get().unwrap(); assert_eq!(point_root.get_x(), 12); assert_eq!(point_root.get_y(), 14); }); handle.join().unwrap(); } And while we've left Rust to do the dirty work of actually moving the point_reader into the new thread, we could also use things like mpsc channels to achieve a similar effect. So now we're able to define basic Cap'N Proto messages, and send them all around our programs. ","version":null,"tagName":"h2"},{"title":"Hello!","type":0,"sectionRef":"#","url":"/2018/05/hello","content":"I'll do what I can to keep this short, there's plenty of other things we both should be doing right now. If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you covered: And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven. Okay, just one: Thanks, and keep it amazing.","keywords":"","version":null},{"title":"What I learned porting dateutil to Rust","type":0,"sectionRef":"#","url":"/2018/06/dateutil-parser-to-rust","content":"","keywords":"","version":null},{"title":"Slow down, what?​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#slow-down-what","content":" OK, fine, I guess I should start with why someone would do this. Dateutil is a Python library for handling dates. The standard library support for time in Python is kinda dope, but there are a lot of extras that go into making it useful beyond just the datetimemodule. dateutil.parser specifically is code to take all the super-weird time formats people come up with and turn them into something actually useful. Date/time parsing, it turns out, is just like everything else involvingcomputers andtime: it feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people suck and this is whywe can't we have nice things. But alas, we'll try and make contemporary art out of the rubble and give it a pretentious name likeTime. Time What makes dateutil.parser great is that there's single function with a single argument that drives what programmers interact with:parse(timestr). It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can possibly do to make sense of your input" value. It doesn't expect much of you. And now it's in Rust. ","version":null,"tagName":"h2"},{"title":"Lost in Translation​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#lost-in-translation","content":" Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better experiences thanthis guywho attempted the same thing for D. These are the actual take-aways: When transcribing code, stay as close to the original library as possible. I'm talking about using the same variable names, same access patterns, the whole shebang. It's way too easy to make a couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference manual for verbatim what your code should be means that you don't spend that long debugging complicated logic, you're more looking for typos. Also, don't use nice Rust things like enums. Whileone time it worked out OK for me, I also managed to shoot myself in the foot a couple times because dateutil stores AM/PM as a boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In general, writing nice code should not be a first-pass priority when you're just trying to recreate the same functionality. Exceptions are a pain. Make peace with it. Python code is just allowed to skip stack frames. So when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns outhe's not quite right, and I'm OK with that. And whiledateutil is pretty well-behaved about not skipping multiple stack frames,130-line try-catch blockstake a while to verify. As another Python quirk, be very careful aboutlong nested if-elif-else blocks. I used to think that Python's whitespace was just there to get you to format your code correctly. I think that no longer. It's way too easy to close a block too early and have incredibly weird issues in the logic. Make sure you use an editor that displays indentation levels so you can keep things straight. Rust macros are not free. I originally had themain test bodywrapped up in a macro using pyo3. It took two minutes to compile. Aftermoving things to a functioncompile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually functions that need to be liberated, man. Finally, I really miss list comprehensions and dictionary comprehensions. As a quick comparison, seethis dateutil codeandthe implementation in Rust. I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be added through macros or syntax extensions. Either way, they're expressive, save typing, and are super-readable. Let's get more of that. ","version":null,"tagName":"h2"},{"title":"Using a young language​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#using-a-young-language","content":" Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On more than one occasion though, I've had issues navigating the Rust ecosystem. What I'll call the "canonical library" is still being built. In Python, if you need datetime parsing, you use dateutil. If you want decimal types, it's already in thestandard library. While I might've gotten away with f64, dateutil uses decimals, and I wanted to follow the principle of staying as close to the original library as possible. Thus began my quest to find a decimal library in Rust. What I quickly found was summarized in a comment: Writing a BigDecimal is easy. Writing a good BigDecimal is hard. -cmr In practice, this means that there are at least 4differentimplementations available. And that's a lot of decisions to worry about when all I'm thinking is "why can'tcalendar reform be a thing" and I'm forced to dig through a coupledifferentthreads to figure out if the library I'm look at is dead or just stable. And even when the "canonical library" exists, there's no guarantees that it will be well-maintained.Chrono is the de facto date/time library in Rust, and just released version 0.4.4 like two days ago. Meanwhile,chrono-tz appears to be dead in the water even thoughthere are people happy to help maintain it. I know relatively little about it, but it appears that most of the release process is automated; keeping that up to date should be a no-brainer. ","version":null,"tagName":"h2"},{"title":"Trial Maintenance Policy​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#trial-maintenance-policy","content":" Specifically given "maintenance" being anoft-discussedissue, I'm going to try out the following policy to keep things moving on dtparse: Issues/PRs needing maintainer feedback will be updated at least weekly. I want to make sure nobody's blocking on me. To keep issues/PRs needing contributor feedback moving, I'm going to (kindly) ask the contributor to check in after two weeks, and close the issue without resolution if I hear nothing back after a month. The second point I think has the potential to be a bit controversial, so I'm happy to receive feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And second: I don't mind keeping those requests going indefinitely. I just want to try and balance keeping things moving with giving people the necessary time they need. I should also note that I'm still getting some best practices in place - CONTRIBUTING and CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are perfect. ","version":null,"tagName":"h2"},{"title":"Roadmap and Conclusion​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#roadmap-and-conclusion","content":" So if I've now built a dateutil-compatible parser, we're done, right? Of course not! That's not nearly ambitious enough. Ultimately, I'd love to have a library that's capable of parsing everything the Linux date command can do (and not date on OSX, because seriously, BSD coreutils are the worst). I know Rust has a coreutils rewrite going on, and dtparse would potentially be an interesting candidate since it doesn't bring in a lot of extra dependencies. humantimecould help pick up some of the (current) slack in dtparse, so maybe we can share and care with each other? All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going to take it hard. And in the mean time, I'm looking forward to building more. Onwards. ","version":null,"tagName":"h2"},{"title":"Isomorphic desktop apps with Rust","type":0,"sectionRef":"#","url":"/2018/09/isomorphic-apps","content":"I both despise Javascript and am stunned by its success doing some really cool things. It'sthis duality that's led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I bootstrap a simple desktop application. See, as much asWebassembly isn't trying to replace Javascript,I want Javascript gone. There are plenty of people who don't share my views, and they are probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think it's hilarious that thelanguage specificationdramatically outpaces anyone'sactual implementation. The answer to this conundrum is of course to recompile code from newer versions of the language to older versions of the same language before running. At least Babel is a nice tongue-in-cheek reference. Yet for as much hate as Electron receives, it does a stunningly good job at solving a really hard problem: how the hell do I put a button on the screen and react when the user clicks it? GUI programming is hard, straight up. But if browsers are already able to run everywhere, why don't we take advantage of someone else solving the hard problems for us? I don't like that I have to use Javascript for it, but I really don't feel inclined to whip out good ol' wxWidgets. Now there are other native solutions (libui-rs, conrod, oh hey wxWdidgets again!), but those also have their own issues with distribution, styling, etc. With Electron, I canyarn create electron-app my-app and just get going, knowing that packaging/upgrades/etc. are built in. My question is: given recent innovations with WASM, are we Electron yet? No, not really. Instead, what would it take to get to a point where we can skip Javascript in Electron apps? Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to try and organize what I did manage to discover. I should also mention that the content and things I'm talking about here are not intended to be prescriptive, but more "if someone else is interested, what do we already know doesn't work?" I expect everything in this post to be obsolete within two months. Even over the course of writing this, a separate blog post had to be modified because upstream changes broke aRust tool the post tried to use. The post ultimatelygot updated, but all this happened within the span of a week. Things are moving quickly. I'll also note that we're going to skip asm.js and emscripten. Truth be told, I couldn't get either of these to output anything, and so I'm just going to sayhere be dragons. Everything I'm discussing here uses the wasm32-unknown-unknown target. The code that I did get running is availableover here. Feel free to use it as a starting point, but I'm mostly including the link as a reference for the things that were attempted. An Example Running Application So, I did technically get a running application: ...which you can also try out if you want: git clone https://github.com/speice-io/isomorphic-rust.git cd isomorphic_rust/percy yarn install && yarn start ...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly there to prove this is possible in the first place. And that's something to be proud of! There's a huge amount of engineering that went into showing a window with the text "It's alive!". There's also a lot of usability issues that prevent me from recommending anyone try Electron and WASM apps at the moment, and I think that's the more important thing to discuss. Issue the First: Complicated Toolchains I quickly established that wasm-bindgen was necessary to "link" my Rust code to Javascript. At that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM blob. To keep things simple, the goal was to package everything using webpack so that I could just load a bundle.js file on the page. That decision was to be the last thing that kinda worked in this process. The first issueI ran intowhile attempting to bundle everything via webpack is a detail in the WASM spec: This function accepts a Response object, or a promise for one, and ... [if > it] does not match the application/wasm MIME type, the returned promise will be rejected with a TypeError; WebAssembly - Additional Web Embedding API Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the web this isn't a huge issue, as the server can set MIME types when delivering the blob. With Electron, you're resolving things with a file:// URL and thus can't control the MIME type: There are a couple of solutions depending on how far into the deep end you care to venture: Embed a static file server in your Electron applicationUse a custom protocol and custom protocol handlerHost your WASM blob on a website that you resolve at runtime But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. Instead, my workaround was toopen a PR with webpack and use regex to remove calls to instantiateStreaming in thebuild script: cargo +nightly build --target=wasm32-unknown-unknown && \\ wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\ # Have to use --mode=development so we can patch out the call to instantiateStreaming "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \\ sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js" Once that lands, thebuild processbecomes much simpler: cargo +nightly build --target=wasm32-unknown-unknown && \\ wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\ "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (viawasm-bindgen and webpack), we still have to make an Electron app. For this purpose I used a starter app from Electron Forge, and then aprestart scriptto actually handle starting the application. Thefinal toolchainlooks something like this: yarn start triggers the prestart scriptprestart checks for missing tools (wasm-bindgen-cli, etc.) and then: Uses cargo to compile the Rust code into WASMUses wasm-bindgen to link the WASM blob into a Javascript file with exported symbolsUses webpack to bundle the page start script with the Javascript we just generated Uses babel under the hood to compile the wasm-bindgen code down from ES6 into something browser-compatible The start script runs an Electron Forge handler to do some sanity checksElectron actually starts ...which is complicated. I think more work needs to be done to either build a high-quality starter app that can manage these steps, or another tool that "just handles" the complexity of linking a compiled WASM file into something the Electron browser can run. Issue the Second: WASM tools in Rust For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that leads to a fragmented ecosystem. Here's what I can recommend as a starting point: Don't check in your Cargo.lock files to version control. If there's a disagreement between the version of wasm-bindgen-cli you have installed and the wasm-bindgen you're compiling with inCargo.lock, you get a nasty error: it looks like the Rust project used to create this wasm file was linked against a different version of wasm-bindgen than this binary: rust wasm file: 0.2.21 this binary: 0.2.17 Currently the bindgen format is unstable enough that these two version must exactly match, so it's required that these two version are kept in sync by either updating the wasm-bindgen dependency or this binary. Not that I ever managed to run into this myself (coughs nervously). There are two projects attempting to be "application frameworks": percy and yew. Between those, I managed to get twoexamples running using percy, but was unable to get anexample running with yew because of issues with "missing modules" during the webpack step: ERROR in ./dist/electron_yew_wasm_bg.wasm Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist' @ ./dist/electron_yew_wasm_bg.wasm @ ./dist/electron_yew_wasm.js @ ./dist/app.js @ ./dist/app_loader.js If you want to work with the browser APIs directly, your choices are percy-webapis or stdweb (or eventually web-sys). See above for my percy examples, but when I triedan example with stdweb, I was unable to get it running: ERROR in ./dist/stdweb_electron_bg.wasm Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist' @ ./dist/stdweb_electron_bg.wasm @ ./dist/stdweb_electron.js @ ./dist/app_loader.js At this point I'm pretty convinced that stdweb is causing issues for yew as well, but can't prove it. I did also get a minimal examplerunning that doesn't depend on any tools besides wasm-bindgen. However, it requires manually writing "extern C" blocks for everything you need from the browser. Es no bueno. Finally, from a tools and platform view, there are two up-and-coming packages that should be mentioned: js-sys and web-sys. Their purpose is to be fundamental building blocks that exposes the browser's APIs to Rust. If you're interested in building an app framework from scratch, these should give you the most flexibility. I didn't touch either in my research, though I expect them to be essential long-term. So there's a lot in play from the Rust side of things, and it's just going to take some time to figure out what works and what doesn't. Issue the Third: Known Unknowns Alright, so after I managed to get an application started, I stopped there. It was a good deal of effort to chain together even a proof of concept, and at this point I'd rather learn Typescriptthan keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know... The important point I want to make is that there's a lot unknown about how any of this holds up outside proofs of concept. Things I didn't attempt: TestingPackagingUpdatesLiterally anything related to why I wanted to use Electron in the first place What it Would Take Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an application in production a couple months from now. But at the moment, I'm personally going to stay away. Let's finish with a wishlist then - here are the things that I think need to happen before Electron/WASM/Rust can become a thing: Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet (#7983)Browser API libraries (web-sys and stdweb) need to make sure they can support running in Electron (see module error above)Projects need to stabilize. There's talk of stdweb being turned into a Rust APIon top of web-sys, and percymoving to web-sys, both of which are big changeswasm-bindgen is great, but still in the "move fast and break things" phaseA good "boilerplate" app would dramatically simplify the start-up costs;electron-react-boilerplate comes to mind as a good project to imitateMore blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm doing","keywords":"","version":null},{"title":"Primitives in Rust are weird (and cool)","type":0,"sectionRef":"#","url":"/2018/09/primitives-in-rust-are-weird","content":"","keywords":"","version":null},{"title":"Defining primitives (Java)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#defining-primitives-java","content":" The reason I'm using the name primitive comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special name for some specific types of values: bool char byte short int long float double They are referred to as primitives. And relative to the other bits of Java, they have two unique features. First, they don't have to worry about thebillion-dollar mistake; primitives in Java can never be null. Second: they can't have instance methods. Remember that Rust program from earlier? Java has no idea what to do with it: class Main { public static void main(String[] args) { int x = 8; System.out.println(x.toString()); // Triggers a compiler error } } The error is: Main.java:5: error: int cannot be dereferenced System.out.println(x.toString()); ^ 1 error Specifically, Java's Objectand things that inherit from it are pointers under the hood, and we have to dereference them before the fields and methods they define can be used. In contrast, primitive types are just values - there's nothing to be dereferenced. In memory, they're just a sequence of bits. If we really want, we can turn the int into anInteger and then dereference it, but it's a bit wasteful: class Main { public static void main(String[] args) { int x = 8; Integer y = Integer.valueOf(x); System.out.println(y.toString()); } } This creates the variable y of type Integer (which inherits Object), and at run time we dereference y to locate the toString() function and call it. Rust obviously handles things a bit differently, but we have to dig into the low-level details to see it in action. ","version":null,"tagName":"h2"},{"title":"Low Level Handling of Primitives (C)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#low-level-handling-of-primitives-c","content":" We first need to build a foundation for reading and understanding the assembly code the final answer requires. Let's begin with showing how the C language (and your computer) thinks about "primitive" values in memory: void my_function(int num) {} int main() { int x = 8; my_function(x); } The compiler explorer gives us an easy way of showing off the assembly-level code that's generated: whose output has been lightly edited main: push rbp mov rbp, rsp sub rsp, 16 ; We assign the value `8` to `x` here mov DWORD PTR [rbp-4], 8 ; And copy the bits making up `x` to a location ; `my_function` can access (`edi`) mov eax, DWORD PTR [rbp-4] mov edi, eax ; Call `my_function` and give it control call my_function mov eax, 0 leave ret my_function: push rbp mov rbp, rsp ; Copy the bits out of the pre-determined location (`edi`) ; to somewhere we can use mov DWORD PTR [rbp-4], edi nop pop rbp ret At a really low level of memory, we're copying bits around using the mov instruction; nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C to Rust: fn my_function(x: i32) {} fn main() { let x = 8; my_function(x) } And the assembly generated when we stick it in thecompiler explorer: again, lightly edited example::main: push rax ; Look familiar? We're copying bits to a location for `my_function` ; The compiler just optimizes out holding `x` in memory mov edi, 8 ; Call `my_function` and give it control call example::my_function pop rax ret example::my_function: sub rsp, 4 ; And copying those bits again, just like in C mov dword ptr [rsp], edi add rsp, 4 ret The generated Rust assembly is functionally pretty close to the C assembly: When working with primitives, we're just dealing with bits in memory. In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to dereference. So what exactly is going on with this .to_string() function call? ","version":null,"tagName":"h2"},{"title":"impl primitive (and Python)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#impl-primitive-and-python","content":" Now it's time to reveal my trap card show the revelation that tied all this together: Rust has implementations for its primitive types. That's right, impl blocks aren't only for structs and traits, primitives get them too. Don't believe me? Check outu32,f64 andchar as examples. But the really interesting bit is how Rust turns those impl blocks into assembly. Let's break out the compiler explorer once again: pub fn main() { 8.to_string() } And the interesting bits in the assembly: heavily trimmed down example::main: sub rsp, 24 mov rdi, rsp lea rax, [rip + .Lbyte_str.u] mov rsi, rax ; Cool stuff right here call <T as alloc::string::ToString>::to_string@PLT mov rdi, rsp call core::ptr::drop_in_place add rsp, 24 ret Now, this assembly is a bit more complicated, but here's the big revelation: we're callingto_string() as a function that exists all on its own, and giving it the instance of 8. Instead of thinking of the value 8 as an instance of u32 and then peeking in to find the location of the function we want to call (like Java), we have a function that exists outside of the instance and just give that function the value 8. This is an incredibly technical detail, but the interesting idea I had was this: if to_string()is a static function, can I refer to the unbound function and give it an instance? Better explained in code (and a compiler explorer link because I seriously love this thing): struct MyVal { x: u32 } impl MyVal { fn to_string(&self) -> String { self.x.to_string() } } pub fn main() { let my_val = MyVal { x: 8 }; // THESE ARE THE SAME my_val.to_string(); MyVal::to_string(&my_val); } Rust is totally fine "binding" the function call to the instance, and also as a static. MIND == BLOWN. Python does the same thing where I can both call functions bound to their instances and also call as an unbound function where I give it the instance: class MyClass(): x = 24 def my_function(self): print(self.x) m = MyClass() m.my_function() MyClass.my_function(m) And Python tries to make you think that primitives can have instance methods... >>> dir(8) ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', ... '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', ...] >>> # Theoretically `8.__str__()` should exist, but: >>> 8.__str__() File "<stdin>", line 1 8.__str__() ^ SyntaxError: invalid syntax >>> # It will run if we assign it first though: >>> x = 8 >>> x.__str__() '8' ...but in practice it's a bit complicated. So while Python handles binding instance methods in a way similar to Rust, it's still not able to run the example we started with. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#conclusion","content":" This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor details like primitives leads to really cool effects. Primitives are optimized like C in how they have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python (like both instance and late binding). And when you put it together, there are areas where Rust does cool things nobody else can; as a quirky feature of Rust's type system, 8.to_string() is actually valid code. Now go forth and fool your friends into thinking you know assembly. This is all I've got. ","version":null,"tagName":"h2"},{"title":"A case study in heaptrack","type":0,"sectionRef":"#","url":"/2018/10/case-study-optimization","content":"","keywords":"","version":null},{"title":"Curiosity​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#curiosity","content":" When I first started building the dtparse crate, my intention was to mirror as closely as possible the equivalent Python library. Python, as you may know, is garbage collected. Very rarely is memory usage considered in Python, and I likewise wasn't paying too much attention whendtparse was first being built. This lackadaisical approach to memory works well enough, and I'm not planning on making dtparsehyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the advent of Rust 1.28 and theGlobal Allocator trait, I had a really great idea: build a custom allocator that allows you to track your own allocations. That way, you can do things like writing tests for both correct results and correct memory usage. I gave it ashot, but learned very quickly: never write your own allocator. It went from "fun weekend project" to "I have literally no idea what my computer is doing" at breakneck speed. Instead, I'll highlight a separate path I took to make sense of my memory usage: heaptrack. ","version":null,"tagName":"h2"},{"title":"Turning on the System Allocator​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#turning-on-the-system-allocator","content":" This is the hardest part of the post. Because Rust usesits own allocator by default,heaptrack is unable to properly record unmodified Rust code. To remedy this, we'll make use of the#[global_allocator] attribute. Specifically, in lib.rs or main.rs, add this: use std::alloc::System; #[global_allocator] static GLOBAL: System = System; ...and that's it. Everything else comes essentially for free. ","version":null,"tagName":"h2"},{"title":"Running heaptrack​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#running-heaptrack","content":" Assuming you've installed heaptrack (Homebrew in Mac, package manager in Linux, ??? in Windows), all that's left is to fire up your application: heaptrack my_application It's that easy. After the program finishes, you'll see a file in your local directory with a name like heaptrack.my_appplication.XXXX.gz. If you load that up in heaptrack_gui, you'll see something like this: And even these pretty colors: ","version":null,"tagName":"h2"},{"title":"Reading Flamegraphs​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#reading-flamegraphs","content":" To make sense of our memory usage, we're going to focus on that last picture - it's called a"flamegraph". These charts are typically used to show how much time your program spends executing each function, but they're used here to show how much memory was allocated during those functions instead. For example, we can see that all executions happened during the main function: ...and within that, all allocations happened during dtparse::parse: ...and within that, allocations happened in two different places: Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue:what the heck is the Default thing doing? ","version":null,"tagName":"h2"},{"title":"Optimizing dtparse​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#optimizing-dtparse","content":" See, I knew that there were some allocations during calls to dtparse::parse, but I was totally wrong about where the bulk of allocations occurred in my program. Let me post the code and see if you can spot the mistake: /// Main entry point for using `dtparse`. pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> { let res = Parser::default().parse( timestr, None, None, false, false, None, false, &HashMap::new(), )?; Ok((res.0, res.1)) } dtparse Because Parser::parse requires a mutable reference to itself, I have to create a newParser::default every time it receives a string. This is excessive! We'd rather have an immutable parser that can be re-used, and avoid allocating memory in the first place. Armed with that information, I put some time in tomake the parser immutable. Now that I can re-use the same parser over and over, the allocations disappear: In total, we went from requiring 2 MB of memory inversion 1.0.2: All the way down to 300KB in version 1.0.3: ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#conclusion","content":" In the end, you don't need to write a custom allocator to be efficient with memory, great tools already exist to help you understand what your program is doing. Use them. Given that Moore's Law isdead, we've all got to do our part to take back what Microsoft stole. ","version":null,"tagName":"h2"},{"title":"QADAPT - debug_assert! for allocations","type":0,"sectionRef":"#","url":"/2018/12/allocation-safety","content":"","keywords":"","version":null},{"title":"Why an Allocator?​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#why-an-allocator","content":" So why, after complaining about allocators, would I still want to write one? There are three reasons for that: Allocation/dropping is slowIt's difficult to know exactly when Rust will allocate or drop, especially when using code that you did not writeI want automated tools to verify behavior, instead of inspecting by hand When I say "slow," it's important to define the terms. If you're writing web applications, you'll spend orders of magnitude more time waiting for the database than you will the allocator. However, there's still plenty of code where micro- or nano-seconds matter; thinkfinance,real-time audio,self-driving cars, andnetworking. In these situations it's simply unacceptable for you to spend time doing things that are not your program, and waiting on the allocator is not cool. As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. So, I propose we play a quick trivia game: Does this code invoke the allocator? ","version":null,"tagName":"h2"},{"title":"Example 1​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-1","content":" fn my_function() { let v: Vec<u8> = Vec::new(); } No: Rust knows how big the Vec type is, and reserves a fixed amount of memory on the stack for the v vector. However, if we wanted to reserve extra space (using Vec::with_capacity) the allocator would get invoked. ","version":null,"tagName":"h3"},{"title":"Example 2​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-2","content":" fn my_function() { let v: Box<Vec<u8>> = Box::new(Vec::new()); } Yes: Because Boxes allow us to work with things that are of unknown size, it has to allocate on the heap. While the Box is unnecessary in this snippet (release builds will optimize out the allocation), reserving heap space more generally is needed to pass a dynamically sized type to another function. ","version":null,"tagName":"h3"},{"title":"Example 3​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-3","content":" fn my_function(v: Vec<u8>) { v.push(5); } Maybe: Depending on whether the Vector we were given has space available, we may or may not allocate. Especially when dealing with code that you did not author, it's difficult to verify that things behave as you expect them to. ","version":null,"tagName":"h3"},{"title":"Blowing Things Up​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#blowing-things-up","content":" So, how exactly does QADAPT solve these problems? Whenever an allocation or drop occurs in code marked allocation-safe, QADAPT triggers a thread panic. We don't want to let the program continue as if nothing strange happened, we want things to explode. However, you don't want code to panic in production because of circumstances you didn't predict. Just like debug_assert!, QADAPT will strip out its own code when building in release mode to guarantee no panics and no performance impact. Finally, there are three ways to have QADAPT check that your code will not invoke the allocator: ","version":null,"tagName":"h2"},{"title":"Using a procedural macro​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-a-procedural-macro","content":" The easiest method, watch an entire function for allocator invocation: use qadapt::no_alloc; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; #[no_alloc] fn push_vec(v: &mut Vec<u8>) { // This triggers a panic if v.len() == v.capacity() v.push(5); } fn main() { let v = Vec::with_capacity(1); // This will *not* trigger a panic push_vec(&v); // This *will* trigger a panic push_vec(&v); } ","version":null,"tagName":"h3"},{"title":"Using a regular macro​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-a-regular-macro","content":" For times when you need more precision: use qadapt::assert_no_alloc; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; fn main() { let v = Vec::with_capacity(1); // No allocations here, we already have space reserved assert_no_alloc!(v.push(5)); // Even though we remove an item, it doesn't trigger a drop // because it's a scalar. If it were a `Box<_>` type, // a drop would trigger. assert_no_alloc!({ v.pop().unwrap(); }); } ","version":null,"tagName":"h3"},{"title":"Using function calls​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-function-calls","content":" Both the most precise and most tedious: use qadapt::enter_protected; use qadapt::exit_protected; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; fn main() { // This triggers an allocation (on non-release builds) let v = Vec::with_capacity(1); enter_protected(); // This does not trigger an allocation because we've reserved size v.push(0); exit_protected(); // This triggers an allocation because we ran out of size, // but doesn't panic because we're no longer protected. v.push(1); } ","version":null,"tagName":"h3"},{"title":"Caveats​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#caveats","content":" It's important to point out that QADAPT code is synchronous, so please be careful when mixing in asynchronous functions: use futures::future::Future; use futures::future::ok; #[no_alloc] fn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> { ok(12).and_then(|e| Ok(Vec::with_capacity(e))) } fn main() { // This doesn't trigger a panic because the `and_then` closure // wasn't run during the function call. async_capacity(); // Still no panic assert_no_alloc!(async_capacity()); // This will panic because the allocation happens during `unwrap` // in the `assert_no_alloc!` macro assert_no_alloc!(async_capacity().poll().unwrap()); } ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#conclusion","content":" While there's a lot more to writing high-performance code than managing your usage of the allocator, it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for most allocators. Version 1.0 was released today, and you can check it out over atcrates.io or on github. I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will help guide that. If there are topics you're interested in, let me know in the comments below! ","version":null,"tagName":"h2"},{"title":"More \"what companies really mean\"","type":0,"sectionRef":"#","url":"/2018/12/what-small-business-really-means","content":"","keywords":"","version":null},{"title":"How do you feel about production support?​","type":1,"pageTitle":"More \"what companies really mean\"","url":"/2018/12/what-small-business-really-means#how-do-you-feel-about-production-support","content":" Translation: We're a fairly small team, and when things break on an evening/weekend/Christmas Day, can we call on you to be there? I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make it out the door before the zombie apocalypse. Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people who either enjoy that, or play along nicely enough that our systems keep working. Small teams have no such luck. If you're interviewing at a small company, especially as a "data scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the most inopportune moments. Terrible-but-popular answers include: It's a part of the job, and I'm happy to contribute. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Compiler optimizations","type":0,"sectionRef":"#","url":"/2019/02/08/compiler-optimizations","content":"","keywords":"","version":null},{"title":"The Case of the Disappearing Box​","type":1,"pageTitle":"Allocations in Rust: Compiler optimizations","url":"/2019/02/08/compiler-optimizations#the-case-of-the-disappearing-box","content":" Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the stack instead! The way this interacts with #[inline] attributes is a bit opaque, but the important part is that LLVM can sometimes do better than the baseline Rust language: use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{AtomicBool, Ordering}; pub fn cmp(x: u32) { // Turn on panicking if we allocate on the heap DO_PANIC.store(true, Ordering::SeqCst); // The compiler is able to see through the constant `Box` // and directly compare `x` to 24 - assembly line 73 let y = Box::new(24); let equals = x == *y; // This call to drop is eliminated drop(y); // Need to mark the comparison result as volatile so that // LLVM doesn't strip out all the code. If `y` is marked // volatile instead, allocation will be forced. unsafe { std::ptr::read_volatile(&equals) }; // Turn off panicking, as there are some deallocations // when we exit main. DO_PANIC.store(false, Ordering::SeqCst); } fn main() { cmp(12) } #[global_allocator] static A: PanicAllocator = PanicAllocator; static DO_PANIC: AtomicBool = AtomicBool::new(false); struct PanicAllocator; unsafe impl GlobalAlloc for PanicAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected allocation."); } System.alloc(layout) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected deallocation."); } System.dealloc(ptr, layout); } } -- Compiler Explorer -- Rust Playground ","version":null,"tagName":"h2"},{"title":"Dr. Array or: how I learned to love the optimizer​","type":1,"pageTitle":"Allocations in Rust: Compiler optimizations","url":"/2019/02/08/compiler-optimizations#dr-array-or-how-i-learned-to-love-the-optimizer","content":" Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if you're not careful, they can make your benchmarks lookimpossibly good. In Rust, theblack_box function (implemented in bothlibtest andcriterion) will tell the compiler to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up running programs that previously caused errors: #[derive(Default)] struct TwoFiftySix { _a: [u64; 32] } #[derive(Default)] struct EightK { _a: [TwoFiftySix; 32] } #[derive(Default)] struct TwoFiftySixK { _a: [EightK; 32] } #[derive(Default)] struct EightM { _a: [TwoFiftySixK; 32] } pub fn main() { // Normally this blows up because we can't reserve size on stack // for the `EightM` struct. But because the compiler notices we // never do anything with `_x`, it optimizes out the stack storage // and the program completes successfully. let _x = EightM::default(); } -- Compiler Explorer -- Rust Playground ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Dynamic memory","type":0,"sectionRef":"#","url":"/2019/02/a-heaping-helping","content":"","keywords":"","version":null},{"title":"Smart pointers​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#smart-pointers","content":" The first thing to note are the "smart pointer" types. When you have data that must outlive the scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these types. The term smart pointer comes from C++, and while it's closely linked to a general design pattern of"Resource Acquisition Is Initialization", we'll use it here specifically to describe objects that are responsible for managing ownership of data allocated on the heap. The smart pointers available in the alloc crate should look mostly familiar: BoxRcArcCow The standard library also defines some smart pointers to manage heap objects, though more than can be covered here. Some examples are: RwLockMutex Finally, there is one "gotcha": cell types(like RefCell) look and behave similarly, but don't involve heap allocation. Thecore::cell docs have more information. When a smart pointer is created, the data it is given is placed in heap memory and the location of that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to deallocate that memory (when a Box hasgone out of scope or a reference countgoes to zero), the heap space is reclaimed. We can prove these types use heap memory by looking at code: use std::rc::Rc; use std::sync::Arc; use std::borrow::Cow; pub fn my_box() { // Drop at assembly line 1640 Box::new(0); } pub fn my_rc() { // Drop at assembly line 1650 Rc::new(0); } pub fn my_arc() { // Drop at assembly line 1660 Arc::new(0); } pub fn my_cow() { // Drop at assembly line 1672 Cow::from("drop"); } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Collections​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#collections","content":" Collection types use heap memory because their contents have dynamic size; they will request more memory when needed, and canrelease memory when it's no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In a way, collections are smart pointers for many objects at a time. Common types that fall under this umbrella are Vec,HashMap, andString (notstr). While collections store the objects they own in heap memory, creating new collections will not allocate on the heap. This is a bit weird; if we call Vec::new(), the assembly shows a corresponding call to real_drop_in_place: pub fn my_vec() { // Drop in place at line 481 Vec::<u8>::new(); } -- Compiler Explorer But because the vector has no elements to manage, no calls to the allocator will ever be dispatched: use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{AtomicBool, Ordering}; fn main() { // Turn on panicking if we allocate on the heap DO_PANIC.store(true, Ordering::SeqCst); // Interesting bit happens here let x: Vec<u8> = Vec::new(); drop(x); // Turn panicking back off, some deallocations occur // after main as well. DO_PANIC.store(false, Ordering::SeqCst); } #[global_allocator] static A: PanicAllocator = PanicAllocator; static DO_PANIC: AtomicBool = AtomicBool::new(false); struct PanicAllocator; unsafe impl GlobalAlloc for PanicAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected allocation."); } System.alloc(layout) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected deallocation."); } System.dealloc(ptr, layout); } } --Rust Playground Other standard library types follow the same behavior; make sure to check outHashMap::new(), and String::new(). ","version":null,"tagName":"h2"},{"title":"Heap Alternatives​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#heap-alternatives","content":" While it is a bit strange to speak of the stack after spending time with the heap, it's worth pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by other crates. If you have need of the functionality, but want to avoid allocating, there are typically alternatives available. When it comes to some standard library smart pointers (RwLock andMutex), stack-based alternatives are provided in crates like parking_lot andspin. You can check outlock_api::RwLock,lock_api::Mutex, andspin::Once if you're in need of synchronization primitives. thread_id may be necessary if you're implementing an allocator because thread::current().id() uses athread_local! structurethat needs heap allocation. ","version":null,"tagName":"h2"},{"title":"Tracing Allocators​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#tracing-allocators","content":" When writing performance-sensitive code, there's no alternative to measuring your code. If you didn't write a benchmark,you don't care about it's performanceYou should never rely on your instincts whena microsecond is an eternity. Similarly, there's great work going on in Rust with allocators that keep track of what they're doing (like alloc_counter). When it comes to tracking heap behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard against future issues. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Summary","type":0,"sectionRef":"#","url":"/2019/02/summary","content":"While there's a lot of interesting detail captured in this series, it's often helpful to have a document that answers some "yes/no" questions. You may not care about what an Iterator looks like in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust will prioritize the fastest behavior it can, here are the rules for each memory type: Global Allocation: const is a fixed value; the compiler is allowed to copy it wherever useful.static is a fixed reference; the compiler will guarantee it is unique. Stack Allocation: Everything not using a smart pointer will be allocated on the stack.Structs, enums, iterators, arrays, and closures are all stack allocated.Cell types (RefCell) behave like smart pointers, but are stack-allocated.Inlining (#[inline]) will not affect allocation behavior for better or worse.Types that are marked Copy are guaranteed to have their contents stack-allocated. Heap Allocation: Smart pointers (Box, Rc, Mutex, etc.) allocate their contents in heap memory.Collections (HashMap, Vec, String, etc.) allocate their contents in heap memory.Some smart pointers in the standard library have counterparts in other crates that don't need heap memory. If possible, use those. -- Raph Levien","keywords":"","version":null},{"title":"Allocations in Rust: Foreword","type":0,"sectionRef":"#","url":"/2019/02/understanding-allocations-in-rust","content":"There's an alchemy of distilling complex technical topics into articles and videos that change the way programmers see the tools they interact with on a regular basis. I knew what a linker was, but there's a staggering amount of complexity in betweenthe OS and main(). Rust programmers use theBox type all the time, but there's a rich history of the Rust language itself wrapped up inhow special it is. In a similar vein, this series attempts to look at code and understand how memory is used; the complex choreography of operating system, compiler, and program that frees you to focus on functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the cognitive burden associated with memory management, but we're going to step into its world for a while. Let's learn a bit about memory in Rust. Rust's three defining features ofPerformance, Reliability, and Productivity are all driven to a great degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, Python), Rustdoesn't reallygarbage collect; instead, it uses anownership system to reason about how long objects will last in your program. In some cases, if the life of an object is fairly transient, Rust can make use of a very fast region called the "stack." When that's not possible, Rust usesdynamic (heap) memoryand the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it is important to have available. That said, there are specific situations in Rust where you'd never need to worry about the stack/heap distinction! If you: Never use unsafeNever use #![feature(alloc)] or the alloc crate ...then it's not possible for you to use dynamic memory! For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited memory, and the program binary size itself may significantly affect what's available! There's no operating system able to manage this"virtual memory" thing, but that's not an issue because there's only one running application. Theembedonomicon is ever in mind, and interacting with the "real world" through extra peripherals is accomplished by reading and writing to specific memory addresses. Most Rust programs find these requirements overly burdensome though. C++ developers would struggle without access to std::vector (except those hardcore no-STL people), and Rust developers would struggle withoutstd::vec. But with the constraints above,std::vec is actually a part of thealloc crate, and thus off-limits. Box,Rc, etc., are also unusable for the same reason. Whether writing code for embedded devices or not, the important thing in both situations is how much you know before your application starts about what its memory usage will look like. In embedded devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how largegoogle.com's home page is until you start trying to download it. The compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code runs faster when the compiler can guarantee exactly how much memory your program needs while it's running. This series is all about understanding how the compiler reasons about your program, with an emphasis on the implications for performance. Now let's address some conditions and caveats before going much further: We'll focus on "safe" Rust only; unsafe lets you use platform-specific allocation API's (malloc) that we'll ignore.We'll assume a "debug" build of Rust code (what you get with cargo run and cargo test) and address (pun intended) release mode at the end (cargo run --release and cargo test --release).All content will be run using Rust 1.32, as that's the highest currently supported in theCompiler Exporer. As such, we'll avoid upcoming innovations likecompile-time evaluation of staticthat are available in nightly.Because of the nature of the content, being able to read assembly is helpful. We'll keep it simple, but I found arefresher on the push and popinstructions was helpful while writing this.I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are available, but if there's something said in error it will be corrected expeditiously. Please let me know at bradlee@speice.io Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth repeating: Rust does not currently have a rigorously and formally defined memory model. -- the docs","keywords":"","version":null},{"title":"Making bread","type":0,"sectionRef":"#","url":"/2019/05/making-bread","content":"Having recently started my "gardening leave" between positions, I have some more personal time available. I'm planning to stay productive, contributing to some open-source projects, but it also occurred to me that despite talking about bread pics, this blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites and Bytes"? Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on some lighter material. I recently learned two critically important lessons: first, the temperature of the dough when you put the yeast in makes a huge difference. Previously, when I wasn't paying attention to dough temperature: Compared with what happens when I put the dough in the microwave for a defrost cycle because the water I used wasn't warm enough: I mean, just look at the bubbles! After shaping the dough, I've got two loaves ready: Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot to add the water and learned my second lesson: never add room-temperature water to a glass dish that's currently at 500 degrees. Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected to be doing during my garden leave. In the end, the bread crust wasn't great, but the bread itself turned out pretty alright: I've been writing a lot more during this break, so I'm looking forward to sharing that in the future. In the mean-time, I'm planning on making a sandwich.","keywords":"","version":null},{"title":"Binary format shootout","type":0,"sectionRef":"#","url":"/2019/09/binary-format-shootout","content":"","keywords":"","version":null},{"title":"Prologue: Binary Parsing with Nom​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#prologue-binary-parsing-with-nom","content":" Our benchmark system will be a simple data processor; given depth-of-book market data fromIEX, serialize each message into the schema format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. This test isn't complex, but is representative of the project I need a binary format for. But before we make it to that point, we have to actually read in the market data. To do so, I'm using a library called nom. Version 5.0 was recently released and brought some big changes, so this was an opportunity to build a non-trivial program and get familiar. If you don't already know about nom, it's a "parser generator". By combining different smaller parsers, you can assemble a parser to handle complex structures without writing tedious code by hand. For example, when parsingPCAP files: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------------------------------------------------------+ 0 | Block Type = 0x00000006 | +---------------------------------------------------------------+ 4 | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 | Interface ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 | Timestamp (High) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 | Timestamp (Low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 | Captured Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Data | | ... | ...you can build a parser in nom that looks likethis: const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00]; pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> { let ( remaining, ( block_type, block_len, interface_id, timestamp_high, timestamp_low, captured_len, packet_len, ), ) = tuple(( tag(ENHANCED_PACKET), le_u32, le_u32, le_u32, le_u32, le_u32, le_u32, ))(input)?; let (remaining, packet_data) = take(captured_len)(remaining)?; Ok((remaining, packet_data)) } While this example isn't too interesting, more complex formats (like IEX market data) are wherenom really shines. Ultimately, because the nom code in this shootout was the same for all formats, we're not too interested in its performance. Still, it's worth mentioning that building the market data parser was actually fun; I didn't have to write tons of boring code by hand. ","version":null,"tagName":"h2"},{"title":"Cap'n Proto​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#capn-proto","content":" Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried because of how long it has supported Rust (thanks to dwrensha for maintaining the Rust port since2014!). However, I had a ton of performance concerns once I started using it. To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the heap to hold the message content, but because builderscan't be re-used, we have to allocate a new buffer for every single message. I was able to work around this with aspecial builderthat could re-use the buffer, but it required reading through Cap'n Proto'sbenchmarksto find an example, and usedstd::mem::transmute to bypass Rust's borrow checker. The process of reading messages was better, but still had issues. Cap'n Proto has two message encodings: a "packed" representation, and an "unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n Proto shines; its main selling point is that there's no decoding step. However, accomplishing zero-copy deserialization required code in the private API (since fixed), and we allocate a vector on every read for the segment table. In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too many issues for me to feel comfortable using it long-term. ","version":null,"tagName":"h2"},{"title":"Flatbuffers​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#flatbuffers","content":" This is the new kid on the block. After afirst attempt didn't pan out, official support was recently launched. Flatbuffers intends to address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The difference is that Flatbuffers claims to have a simpler wire format andmore flexibility. On the whole, I enjoyed using Flatbuffers; the tooling is nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, there were still some issues. First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats like the following: table Message { symbol: string; } table MultiMessage { messages:[Message]; } We want to create a MultiMessage which contains a vector of Message, and each Message itself contains a vector (the string type). I was able to work around this bycaching Message elementsin a SmallVec before building the final MultiMessage, but it was a painful process that I believe contributed to poor serialization performance. Second, streaming support in Flatbuffers seems to be something of anafterthought. Where Cap'n Proto in Rust handles reading messages from a stream as part of the API, Flatbuffers just sticks a u32 at the front of each message to indicate the size. Not specifically a problem, but calculating message size without that tag is nigh on impossible. Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform well. ","version":null,"tagName":"h2"},{"title":"Simple Binary Encoding​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#simple-binary-encoding","content":" Support for SBE was added by the author of one of my favoriteRust blog posts. I've talked previously about how important variance is in high-performance systems, so it was encouraging to read about a format thatdirectly addressed my concerns. SBE has by far the simplest binary format, but it does make some tradeoffs. Both Cap'n Proto and Flatbuffers use message offsetsto handle variable-length data, unions, and various other features. In contrast, messages in SBE are essentiallyjust structs; variable-length data is supported, but there's no union type. As mentioned in the beginning, the Rust port of SBE works well, but isessentially unmaintained. However, if you don't need union types, and can accept that schemas are XML documents, it's still worth using. SBE's implementation had the best streaming support of all formats I tested, and doesn't trigger allocation during de/serialization. ","version":null,"tagName":"h2"},{"title":"Results​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#results","content":" After building a test harnessforeachformat, it was time to actually take them for a spin. I usedthis script to run the benchmarks, and the raw results arehere. All data reported below is the average of 10 runs on a single day of IEX data. Results were validated to make sure that each format parsed the data correctly. ","version":null,"tagName":"h2"},{"title":"Serialization​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#serialization","content":" This test measures, on aper-message basis, how long it takes to serialize the IEX message into the desired format and write to a pre-allocated buffer. Schema\tMedian\t99th Pctl\t99.9th Pctl\tTotalCap'n Proto Packed\t413ns\t1751ns\t2943ns\t14.80s Cap'n Proto Unpacked\t273ns\t1828ns\t2836ns\t10.65s Flatbuffers\t355ns\t2185ns\t3497ns\t14.31s SBE\t91ns\t1535ns\t2423ns\t3.91s ","version":null,"tagName":"h3"},{"title":"Deserialization​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#deserialization","content":" This test measures, on aper-message basis, how long it takes to read the previously-serialized message and perform some basic aggregation. The aggregation code is the same for each format, so any performance differences are due solely to the format implementation. Schema\tMedian\t99th Pctl\t99.9th Pctl\tTotalCap'n Proto Packed\t539ns\t1216ns\t2599ns\t18.92s Cap'n Proto Unpacked\t366ns\t737ns\t1583ns\t12.32s Flatbuffers\t173ns\t421ns\t1007ns\t6.00s SBE\t116ns\t286ns\t659ns\t4.05s ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#conclusion","content":" Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" type isn't important to me, I can be confident that SBE best addresses my needs. While SBE was the fastest in terms of both median and worst-case performance, its worst case performance was proportionately far higher than any other format. It seems to be that de/serialization time scales with message size, but I'll need to do some more research to understand what exactly is going on. ","version":null,"tagName":"h2"},{"title":"On building high performance systems","type":0,"sectionRef":"#","url":"/2019/06/high-performance-systems","content":"","keywords":"","version":null},{"title":"Language-specific​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#language-specific","content":" Garbage Collection: How often does garbage collection happen? When is it triggered? What are the impacts? In Python, individual objects are collected if the reference count reaches 0, and each generation is collected ifnum_alloc - num_dealloc > gc_threshold whenever an allocation happens. The GIL is acquired for the duration of generational collection.Java hasmanydifferentcollectionalgorithmsto choose from, each with different characteristics. The default algorithms (Parallel GC in Java 8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms (ZGC andShenandoah) are designed to keep "stop the world" to a minimum by doing collection work in parallel. Allocation: Every language has a different way of interacting with "heap" memory, but the principle is the same: running the allocator to allocate/deallocate memory takes time that can often be put to better use. Understanding when your language interacts with the allocator is crucial, and not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java does (meaning potential GC pauses). Take time to understand heap behavior (I made aa guide for Rust), and look into alternative allocators (jemalloc,tcmalloc) that might run faster than the operating system default. Data Layout: How your data is arranged in memory matters;data-oriented design andcache locality can have huge impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't make. Cachegrind and kernelperf counters are both great for understanding how performance relates to memory layout. Just-In-Time Compilation: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are great because they optimize your program for how it's actually being used, rather than how a compiler expects it to be used. However, there's a variance problem if the program stops executing while waiting for translation from VM bytecode to native code. As a remedy, many languages support ahead-of-time compilation in addition to the JIT versions (CoreRT in C# and GraalVM in Java). On the other hand, LLVM supportsProfile Guided Optimization, which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT compiler kicked in. Programming Tricks: These won't make or break performance, but can be useful in specific circumstances. For example, C++ can usetemplates instead of branchesin critical sections. ","version":null,"tagName":"h2"},{"title":"Kernel​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#kernel","content":" Code you wrote is almost certainly not the only code running on your hardware. There are many ways the operating system interacts with your program, from interrupts to system calls, that are important to watch for. These are written from a Linux perspective, but Windows does typically have equivalent functionality. Scheduling: The kernel is normally free to schedule any process on any core, so it's important to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, limit the CPU cores that non-critical processes are allowed to run on by excluding cores from scheduling (isolcpuskernel command-line option), or by setting the init process CPU affinity (systemd example). Second, set critical processes to run on the isolated cores by setting theprocessor affinity usingtaskset. Finally, useNO_HZ orchrt to disable scheduling interrupts. Turning off hyper-threading is also likely beneficial. System calls: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long the I/O operation takes, these all trigger expensivesystem calls (syscalls). To handle these, the CPU mustcontext switch to the kernel, let the kernel operation complete, then context switch back to your program. We'd rather keep theseto a minimum (see timestamp 18:20). Strace is your friend for understanding when and where syscalls happen. Signal Handling: Far less likely to be an issue, but signals do trigger a context switch if your code has a handler registered. This will be highly dependent on the application, but you canblock signalsif it's an issue. Interrupts: System interrupts are how devices connected to your computer notify the CPU that something has happened. The CPU will then choose a processor core to pause and context switch to the OS to handle the interrupt. Make sure thatSMP affinity is set so that interrupts are handled on a CPU core not running the program you care about. NUMA: While NUMA is good at making multi-cell systems transparent, there are variance implications; if the kernel moves a process across nodes, future memory accesses must wait for the controller on the original node. Usenumactl to handle memory-/cpu-cell pinning so this doesn't happen. ","version":null,"tagName":"h2"},{"title":"Hardware​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#hardware","content":" CPU Pipelining/Speculation: Speculative execution in modern processors gave us vulnerabilities like Spectre, but it also gave us performance improvements likebranch prediction. And if the CPU mis-speculates your code, there's variance associated with rewind and replay. While the compiler knows a lot about how your CPU pipelines instructions, code can bestructured to help the branch predictor. Paging: For most systems, virtual memory is incredible. Applications live in their own worlds, and the CPU/MMU figures out the details. However, there's a variance penalty associated with memory paging and caching; if you access more memory pages than the TLB can store, you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an issue, but using huge pages can reduce TLB burdens. Alternately, running applications in a hypervisor likeJailhouse allows one to skip virtual memory entirely, but this is probably more work than the benefits are worth. Network Interfaces: When more than one computer is involved, variance can go up dramatically. Tuning kernelnetwork parameters may be helpful, but modern systems more frequently opt to skip the kernel altogether with a technique called kernel bypass. This typically requires specialized hardware and drivers, but even industries liketelecom are finding the benefits. ","version":null,"tagName":"h2"},{"title":"Networks​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#networks","content":" Routing: There's a reason financial firms are willing to paymillions of eurosfor rights to a small plot of land - having a straight-line connection from point A to point B means the path their data takes is the shortest possible. In contrast, there are currently 6 computers in between me and Google, but that may change at any moment if my ISP realizes amore efficient route is available. Whether it's usingresearch-quality equipmentfor shortwave radio, or just making sure there's no data inadvertently going between data centers, routing matters. Protocol: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, and congestion control all built in. But these attributes make the most sense when networking infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may make sense in these contexts as it avoids the chatter needed to track connection state, andgap-fillstrategiescan handle the rest. Switching: Many routers/switches handle packets using "store-and-forward" behavior: wait for the whole packet, validate checksums, and then send to the next device. In variance terms, the time needed to move data between two nodes is proportional to the size of that data; the switch must "store" all data before it can calculate checksums and "forward" to the next node. With"cut-through"designs, switches will begin forwarding data as soon as they know where the destination is, checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter the size. ","version":null,"tagName":"h2"},{"title":"Final Thoughts​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#final-thoughts","content":" High-performance systems, regardless of industry, are not magical. They do require extreme precision and attention to detail, but they're designed, built, and operated by regular people, using a lot of tools that are publicly available. Interested in seeing how context switching affects performance of your benchmarks? taskset should be installed in all modern Linux distributions, and can be used to make sure the OS never migrates your process. Curious how often garbage collection triggers during a crucial operation? Your language of choice will typically expose details of its operations (Python,Java). Want to know how hard your program is stressing the TLB? Use perf record and look fordtlb_load_misses.miss_causes_a_walk. Two final guiding questions, then: first, before attempting to apply some of the technology above to your own systems, can you first identifywhere/when you care about "high-performance"? As an example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are they being designed in a way that's actually helpful? Tools likeCriterion (also inRust) and Google'sBenchmark output not only average run time, but variance as well; your benchmarking environment is subject to the same concerns your production environment is. Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate it; once that's at an acceptable level, then optimize for speed. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Global memory","type":0,"sectionRef":"#","url":"/2019/02/the-whole-world","content":"","keywords":"","version":null},{"title":"const values​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#const-values","content":" When a value is guaranteed to be unchanging in your program (where "value" may be scalars,structs, etc.), you can declare it const. This tells the compiler that it's safe to treat the value as never changing, and enables some interesting optimizations; not only is there no initialization cost to creating the value (it is loaded at the same time as the executable parts of your program), but the compiler can also copy the value around if it speeds up the code. The points we need to address when talking about const are: Const values are stored in read-only memory - it's impossible to modify.Values resulting from calling a const fn are materialized at compile-time.The compiler may (or may not) copy const values wherever it chooses. ","version":null,"tagName":"h2"},{"title":"Read-Only​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#read-only","content":" The first point is a bit strange - "read-only memory."The Rust bookmentions in a couple places that using mut with constants is illegal, but it's also important to demonstrate just how immutable they are. Typically in Rust you can useinterior mutability to modify things that aren't declared mut.RefCell provides an example of this pattern in action: use std::cell::RefCell; fn my_mutator(cell: &RefCell<u8>) { // Even though we're given an immutable reference, // the `replace` method allows us to modify the inner value. cell.replace(14); } fn main() { let cell = RefCell::new(25); // Prints out 25 println!("Cell: {:?}", cell); my_mutator(&cell); // Prints out 14 println!("Cell: {:?}", cell); } --Rust Playground When const is involved though, interior mutability is impossible: use std::cell::RefCell; const CELL: RefCell<u8> = RefCell::new(25); fn my_mutator(cell: &RefCell<u8>) { cell.replace(14); } fn main() { // First line prints 25 as expected println!("Cell: {:?}", &CELL); my_mutator(&CELL); // Second line *still* prints 25 println!("Cell: {:?}", &CELL); } --Rust Playground And a second example using Once: use std::sync::Once; const SURPRISE: Once = Once::new(); fn main() { // This is how `Once` is supposed to be used SURPRISE.call_once(|| println!("Initializing...")); // Because `Once` is a `const` value, we never record it // having been initialized the first time, and this closure // will also execute. SURPRISE.call_once(|| println!("Initializing again???")); } --Rust Playground When theconst specificationrefers to "rvalues", this behavior is what they refer to. Clippy will treat this as an error, but it's still something to be aware of. ","version":null,"tagName":"h3"},{"title":"Initialization​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#initialization","content":" The next thing to mention is that const values are loaded into memory as part of your program binary. Because of this, any const values declared in your program will be "realized" at compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may be able to prefetch the value), but that's it. use std::cell::RefCell; const CELL: RefCell<u32> = RefCell::new(24); pub fn multiply(value: u32) -> u32 { // CELL is stored at `.L__unnamed_1` value * (*CELL.get_mut()) } -- Compiler Explorer The compiler creates one RefCell, uses it everywhere, and never needs to call the RefCell::newfunction. ","version":null,"tagName":"h3"},{"title":"Copying​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#copying","content":" If it's helpful though, the compiler can choose to copy const values. const FACTOR: u32 = 1000; pub fn multiply(value: u32) -> u32 { // See assembly line 4 for the `mov edi, 1000` instruction value * FACTOR } pub fn multiply_twice(value: u32) -> u32 { // See assembly lines 22 and 29 for `mov edi, 1000` instructions value * FACTOR * FACTOR } -- Compiler Explorer In this example, the FACTOR value is turned into the mov edi, 1000 instruction in both themultiply and multiply_twice functions; the "1000" value is never "stored" anywhere, as it's small enough to inline into the assembly instructions. Finally, getting the address of a const value is possible, but not guaranteed to be unique (because the compiler can choose to copy values). I was unable to get non-unique pointers in my testing (even using different crates), but the specifications are clear enough: don't rely on pointers to const values being consistent. To be frank, caring about locations for const values is almost certainly a code smell. ","version":null,"tagName":"h3"},{"title":"static values​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#static-values","content":" Static variables are related to const variables, but take a slightly different approach. When we declare that a reference is unique for the life of a program, you have a static variable (unrelated to the 'static lifetime). Because of the reference/value distinction withconst/static, static variables behave much more like typical "global" variables. But to understand static, here's what we'll look at: static variables are globally unique locations in memory.Like const, static variables are loaded at the same time as your program being read into memory.All static variables must implement theSync marker trait.Interior mutability is safe and acceptable when using static variables. ","version":null,"tagName":"h2"},{"title":"Memory Uniqueness​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#memory-uniqueness","content":" The single biggest difference between const and static is the guarantees provided about uniqueness. Where const variables may or may not be copied in code, static variables are guarantee to be unique. If we take a previous const example and change it to static, the difference should be clear: static FACTOR: u32 = 1000; pub fn multiply(value: u32) -> u32 { // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used value * FACTOR } pub fn multiply_twice(value: u32) -> u32 { // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used value * FACTOR * FACTOR } -- Compiler Explorer Where previously there were plenty of references to multiplying by 1000, the new assembly refers to FACTOR as a named memory location instead. No initialization work needs to be done, but the compiler can no longer prove the value never changes during execution. ","version":null,"tagName":"h3"},{"title":"Initialization​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#initialization-1","content":" Next, let's talk about initialization. The simplest case is initializing static variables with either scalar or struct notation: #[derive(Debug)] struct MyStruct { x: u32 } static MY_STRUCT: MyStruct = MyStruct { // You can even reference other statics // declared later x: MY_VAL }; static MY_VAL: u32 = 24; fn main() { println!("Static MyStruct: {:?}", MY_STRUCT); } --Rust Playground Things can get a bit weirder when using const fn though. In most cases, it just works: #[derive(Debug)] struct MyStruct { x: u32 } impl MyStruct { const fn new() -> MyStruct { MyStruct { x: 24 } } } static MY_STRUCT: MyStruct = MyStruct::new(); fn main() { println!("const fn Static MyStruct: {:?}", MY_STRUCT); } --Rust Playground However, there's a caveat: you're currently not allowed to use const fn to initialize static variables of types that aren't marked Sync. For example,RefCell::new() is aconst fn, but becauseRefCell isn't Sync, you'll get an error at compile time: use std::cell::RefCell; // error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely static MY_LOCK: RefCell<u8> = RefCell::new(0); --Rust Playground It's likely that this willchange in the future though. ","version":null,"tagName":"h3"},{"title":"The Sync marker​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#the-sync-marker","content":" Which leads well to the next point: static variable types must implement theSync marker. Because they're globally unique, it must be safe for you to access static variables from any thread at any time. Moststruct definitions automatically implement the Sync trait because they contain only elements which themselves implement Sync (read more in theNomicon). This is why earlier examples could get away with initializing statics, even though we never included an impl Sync for MyStruct in the code. To demonstrate this property, Rust refuses to compile our earlier example if we add a non-Sync element to the struct definition: use std::cell::RefCell; struct MyStruct { x: u32, y: RefCell<u8>, } // error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely static MY_STRUCT: MyStruct = MyStruct { x: 8, y: RefCell::new(8) }; --Rust Playground ","version":null,"tagName":"h3"},{"title":"Interior mutability​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#interior-mutability","content":" Finally, while static mut variables are allowed, mutating them is an unsafe operation. If we want to stay in safe Rust, we can use interior mutability to accomplish similar goals: use std::sync::Once; // This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once static INIT: Once = Once::new(); fn main() { // Note that while `INIT` is declared immutable, we're still allowed // to mutate its interior INIT.call_once(|| println!("Initializing...")); // This code won't panic, as the interior of INIT was modified // as part of the previous `call_once` INIT.call_once(|| panic!("INIT was called twice!")); } --Rust Playground ","version":null,"tagName":"h3"},{"title":"Release the GIL","type":0,"sectionRef":"#","url":"/2019/12/release-the-gil","content":"","keywords":"","version":null},{"title":"Cython​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#cython","content":" Put simply, Cython is a programming language that looks a lot like Python, gets transpiled to C/C++, and integrates well with the CPython API. It's great for building Python wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And when it comes to managing the GIL, there are two special features: The nogilfunction annotationasserts that a Cython function is safe to use without the GIL, and compilation will fail if it interacts with Python in an unsafe mannerThe with nogilcontext managerexplicitly unlocks the CPython GIL while active Whenever Cython code runs inside a with nogil block on a separate thread, the Python interpreter is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that demonstrates this principle in action: %%cython # Annotating a function with `nogil` indicates only that it is safe # to call in a `with nogil` block. It *does not* release the GIL. cdef unsigned long fibonacci(unsigned long n) nogil: if n <= 1: return n cdef unsigned long a = 0, b = 1, c = 0 c = a + b for _i in range(2, n): a = b b = c c = a + b return c def cython_nogil(unsigned long n): # Explicitly release the GIL while running `fibonacci` with nogil: value = fibonacci(n) return value def cython_gil(unsigned long n): # Because the GIL is not explicitly released, it implicitly # remains acquired when running the `fibonacci` function return fibonacci(n) First, let's time how long it takes Cython to calculate the billionth Fibonacci number: %%time _ = cython_gil(N); CPU times: user 365 ms, sys: 0 ns, total: 365 ms Wall time: 372 ms %%time _ = cython_nogil(N); CPU times: user 381 ms, sys: 0 ns, total: 381 ms Wall time: 388 ms Both versions (with and without GIL) take effectively the same amount of time to run. Even when running this calculation in parallel on separate threads, it is expected that the run time will double because only one thread can be active at a time: %%time from threading import Thread # Create the two threads to run on t1 = Thread(target=cython_gil, args=[N]) t2 = Thread(target=cython_gil, args=[N]) # Start the threads t1.start(); t2.start() # Wait for the threads to finish t1.join(); t2.join() CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms Wall time: 645 ms However, if the first thread releases the GIL, the second thread is free to acquire it and run in parallel: %%time t1 = Thread(target=cython_nogil, args=[N]) t2 = Thread(target=cython_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 717 ms, sys: 372 µs, total: 718 ms Wall time: 358 ms Because user time represents the sum of processing time on all threads, it doesn't change much. The "wall time" has been cut roughly in half because each function is running simultaneously. Keep in mind that the order in which threads are started makes a difference! %%time # Note that the GIL-locked version is started first t1 = Thread(target=cython_gil, args=[N]) t2 = Thread(target=cython_nogil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 667 ms, sys: 0 ns, total: 667 ms Wall time: 672 ms Even though the second thread releases the GIL while running, it can't start until the first has completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads. Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash theinterpreter, not just the thread attempting the unlock: %%cython cdef int cython_recurse(int n) nogil: if n <= 0: return 0 with nogil: return cython_recurse(n - 1) cython_recurse(2) Fatal Python error: PyEval_SaveThread: NULL tstate Thread 0x00007f499effd700 (most recent call first): File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap In practice, avoiding this issue is simple. First, nogil functions probably shouldn't containwith nogil blocks. Second, Cython canconditionally acquire/releasethe GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation forexternal C codecontains more detail on how to safely manage the GIL. To conclude: use Cython's nogil annotation to assert that functions are safe for calling when the GIL is unlocked, and with nogil to actually unlock the GIL and run those functions. ","version":null,"tagName":"h2"},{"title":"Numba​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#numba","content":" Like Cython, Numba is a "compiled Python." Where Cython works by compiling a Python-like language to C/C++, Numba compiles Python bytecode directly to machine codeat runtime. Behavior is controlled with a special @jit decorator; calling a decorated function first compiles it to machine code before running. Calling the function a second time re-uses that machine code unless the argument types have changed. Numba works best when a nopython=True argument is added to the @jit decorator; functions compiled in nopython mode avoid the CPython API and have performance comparable to C. Further, adding nogil=True to the@jit decorator unlocks the GIL while that function is running. Note that nogil and nopythonare separate arguments; while it is necessary for code to be compiled in nopython mode in order to release the lock, the GIL will remain locked if nogil=False (the default). Let's repeat the same experiment, this time using Numba instead of Cython: # The `int` type annotation is only for humans and is ignored # by Numba. @jit(nopython=True, nogil=True) def numba_nogil(n: int) -> int: if n <= 1: return n a = 0 b = 1 c = a + b for _i in range(2, n): a = b b = c c = a + b return c # Run using `nopython` mode to receive a performance boost, # but GIL remains locked due to `nogil=False` by default. @jit(nopython=True) def numba_gil(n: int) -> int: if n <= 1: return n a = 0 b = 1 c = a + b for _i in range(2, n): a = b b = c c = a + b return c # Call each function once to force compilation; we don't want # the timing statistics to include how long it takes to compile. numba_nogil(N) numba_gil(N); We'll perform the same tests as above; first, figure out how long it takes the function to run: %%time _ = numba_gil(N) CPU times: user 253 ms, sys: 258 µs, total: 253 ms Wall time: 251 ms Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be effectively identical after compilation. When running two GIL-locked threads, the result (as expected) takes around twice as long to compute: %%time t1 = Thread(target=numba_gil, args=[N]) t2 = Thread(target=numba_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms Wall time: 541 ms But if the GIL-unlocking thread starts first, both threads run in parallel: %%time t1 = Thread(target=numba_nogil, args=[N]) t2 = Thread(target=numba_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms Wall time: 279 ms Just like Cython, starting the GIL-locked thread first leads to poor performance: %%time t1 = Thread(target=numba_gil, args=[N]) t2 = Thread(target=numba_nogil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 524 ms, sys: 0 ns, total: 524 ms Wall time: 522 ms Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; recursively calling @jit(nogil=True) functions is perfectly safe: from numba import jit @jit(nopython=True, nogil=True) def numba_recurse(n: int) -> int: if n <= 0: return 0 return numba_recurse(n - 1) numba_recurse(2); ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#conclusion","content":" Before finishing, it's important to address pain points that will show up if these techniques are used in a more realistic project: First, code running in a GIL-free context will likely also need non-trivial data structures; GIL-free functions aren't useful if they're constantly interacting with Python objects whose access requires the GIL. Cython providesextension types and Numba provides a @jitclass decorator to address this need. Second, building and distributing applications that make use of Cython/Numba can be complicated. Cython packages require running the compiler, (potentially) linking/packaging external dependencies, and distributing a binary wheel. Numba is generally simpler because the code being distributed is pure Python, but can be tricky since errors aren't detected until runtime. Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba provide tools to directly manage the GIL when appropriate. This enables true parallelism (not justconcurrency) that is impossible in vanilla Python. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Fixed memory","type":0,"sectionRef":"#","url":"/2019/02/stacking-up","content":"","keywords":"","version":null},{"title":"Structs​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#structs","content":" The simplest case comes first. When creating vanilla struct objects, we use stack memory to hold their contents: struct Point { x: u64, y: u64, } struct Line { a: Point, b: Point, } pub fn make_line() { // `origin` is stored in the first 16 bytes of memory // starting at location `rsp` let origin = Point { x: 0, y: 0 }; // `point` makes up the next 16 bytes of memory let point = Point { x: 1, y: 2 }; // When creating `ray`, we just move the content out of // `origin` and `point` into the next 32 bytes of memory let ray = Line { a: origin, b: point }; } -- Compiler Explorer Note that while some extra-fancy instructions are used for memory manipulation in the assembly, thesub rsp, 64 instruction indicates we're still working with the stack. ","version":null,"tagName":"h2"},{"title":"Function arguments​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#function-arguments","content":" Have you ever wondered how functions communicate with each other? Like, once the variables are given to you, everything's fine. But how do you "give" those variables to another function? How do you get the results back afterward? The answer: the compiler arranges memory and assembly instructions using a pre-determined calling convention. This convention governs the rules around where arguments needed by a function will be located (either in memory offsets relative to the stack pointer rsp, or in other registers), and where the results can be found once the function has finished. And when multiple languages agree on what the calling conventions are, you can do things like having Go call Rust code! Put simply: it's the compiler's job to figure out how to call other functions, and you can assume that the compiler is good at its job. We can see this in action using a simple example: struct Point { x: i64, y: i64, } // We use integer division operations to keep // the assembly clean, understanding the result // isn't accurate. fn distance(a: &Point, b: &Point) -> i64 { // Immediately subtract from `rsp` the bytes needed // to hold all the intermediate results - this is // the stack allocation step // The compiler used the `rdi` and `rsi` registers // to pass our arguments, so read them in let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; // Do the actual math work let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared // Our final result will be stored in the `rax` register // so that our caller knows where to retrieve it. // Finally, add back to `rsp` the stack memory that is // now ready to be used by other functions. } pub fn total_distance() { let start = Point { x: 1, y: 2 }; let middle = Point { x: 3, y: 4 }; let end = Point { x: 5, y: 6 }; let _dist_1 = distance(&start, &middle); let _dist_2 = distance(&middle, &end); } -- Compiler Explorer As a consequence of function arguments never using heap memory, we can also infer that functions using the #[inline] attributes also do not heap allocate. But better than inferring, we can look at the assembly to prove it: struct Point { x: i64, y: i64, } // Note that there is no `distance` function in the assembly output, // and the total line count goes from 229 with inlining off // to 306 with inline on. Even still, no heap allocations occur. #[inline(always)] fn distance(a: &Point, b: &Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (a.x - b.x) * (a.x - b.x); let y_pow = (a.y - b.y) * (a.y - b.y); let squared = x_pow + y_pow; squared / squared } pub fn total_distance() { let start = Point { x: 1, y: 2 }; let middle = Point { x: 3, y: 4 }; let end = Point { x: 5, y: 6 }; let _dist_1 = distance(&start, &middle); let _dist_2 = distance(&middle, &end); } -- Compiler Explorer Finally, passing by value (arguments with typeCopy) and passing by reference (either moving ownership or passing a pointer) may have slightly different layouts in assembly, but will still use either stack memory or CPU registers: pub struct Point { x: i64, y: i64, } // Moving values pub fn distance_moved(a: Point, b: Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared } // Borrowing values has two extra `mov` instructions on lines 21 and 22 pub fn distance_borrowed(a: &Point, b: &Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Enums​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#enums","content":" If you've ever worried that wrapping your types inOption orResult would finally make them large enough that Rust decides to use heap allocation instead, fear no longer: enum and union types don't use heap allocation: enum MyEnum { Small(u8), Large(u64) } struct MyStruct { x: MyEnum, y: MyEnum, } pub fn enum_compare() { let x = MyEnum::Small(0); let y = MyEnum::Large(0); let z = MyStruct { x, y }; let opt = Option::Some(z); } -- Compiler Explorer Because the size of an enum is the size of its largest element plus a flag, the compiler can predict how much memory is used no matter which variant of an enum is currently stored in a variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great way to show this in assembly, so I'll instead point you to thecore::mem::size_ofdocumentation. ","version":null,"tagName":"h2"},{"title":"Arrays​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#arrays","content":" The array type is guaranteed to be stack allocated, which is why the array size must be declared. Interestingly enough, this can be used to cause safe Rust programs to crash: // 256 bytes #[derive(Default)] struct TwoFiftySix { _a: [u64; 32] } // 8 kilobytes #[derive(Default)] struct EightK { _a: [TwoFiftySix; 32] } // 256 kilobytes #[derive(Default)] struct TwoFiftySixK { _a: [EightK; 32] } // 8 megabytes - exceeds space typically provided for the stack, // though the kernel can be instructed to allocate more. // On Linux, you can check stack size using `ulimit -s` #[derive(Default)] struct EightM { _a: [TwoFiftySixK; 32] } fn main() { // Because we already have things in stack memory // (like the current function call stack), allocating another // eight megabytes of stack memory crashes the program let _x = EightM::default(); } --Rust Playground There aren't any security implications of this (no memory corruption occurs), but it's good to note that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to overflow the stack. ","version":null,"tagName":"h2"},{"title":"Closures​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#closures","content":" Rules for how anonymous functions capture their arguments are typically language-specific. In Java,Lambda Expressions are actually objects created on the heap that capture local primitives by copying, and capture local non-primitives as (final) references.Python andJavaScriptboth bind everything by reference normally, but Python can alsocapture values and JavaScript hasArrow functions. In Rust, arguments to closures are the same as arguments to other functions; closures are simply functions that don't have a declared name. Some weird ordering of the stack may be required to handle them, but it's the compiler's responsiblity to figure that out. Each example below has the same effect, but a different assembly implementation. In the simplest case, we immediately run a closure returned by another function. Because we don't store a reference to the closure, the stack memory needed to store the captured values is contiguous: fn my_func() -> impl FnOnce() { let x = 24; // Note that this closure in assembly looks exactly like // any other function; you even use the `call` instruction // to start running it. move || { x; } } pub fn immediate() { my_func()(); my_func()(); } -- Compiler Explorer, 25 total assembly instructions If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory of the original function. Getting the details right is a bit harder, so the instruction count goes up even though this code is functionally equivalent to our original example: pub fn simple_reference() { let x = my_func(); let y = my_func(); y(); x(); } -- Compiler Explorer, 55 total assembly instructions Even things like variable order can make a difference in instruction count: pub fn complex() { let x = my_func(); let y = my_func(); x(); y(); } -- Compiler Explorer, 70 total assembly instructions In every circumstance though, the compiler ensured that no heap allocations were necessary. ","version":null,"tagName":"h2"},{"title":"Generics​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#generics","content":" Traits in Rust come in two broad forms: static dispatch (monomorphization, impl Trait) and dynamic dispatch (trait objects, dyn Trait). While dynamic dispatch is often associated with trait objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well: trait GetInt { fn get_int(&self) -> u64; } // vtable stored at section L__unnamed_1 struct WhyNotU8 { x: u8 } impl GetInt for WhyNotU8 { fn get_int(&self) -> u64 { self.x as u64 } } // vtable stored at section L__unnamed_2 struct ActualU64 { x: u64 } impl GetInt for ActualU64 { fn get_int(&self) -> u64 { self.x } } // `&dyn` declares that we want to use dynamic dispatch // rather than monomorphization, so there is only one // `retrieve_int` function that shows up in the final assembly. // If we used generics, there would be one implementation of // `retrieve_int` for each type that implements `GetInt`. pub fn retrieve_int(u: &dyn GetInt) { // In the assembly, we just call an address given to us // in the `rsi` register and hope that it was set up // correctly when this function was invoked. let x = u.get_int(); } pub fn do_call() { // Note that even though the vtable for `WhyNotU8` and // `ActualU64` includes a pointer to // `core::ptr::real_drop_in_place`, it is never invoked. let a = WhyNotU8 { x: 0 }; let b = ActualU64 { x: 0 }; retrieve_int(&a); retrieve_int(&b); } -- Compiler Explorer It's hard to imagine practical situations where dynamic dispatch would be used for objects that aren't heap allocated, but it technically can be done. ","version":null,"tagName":"h2"},{"title":"Copy types​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#copy-types","content":" Understanding move semantics and copy semantics in Rust is weird at first. The Rust docsgo into detail far better than can be addressed here, so I'll leave them to do the job. From a memory perspective though, their guideline is reasonable:if your type can implemement Copy, it should. While there are potential speed tradeoffs to benchmark when discussing Copy (move semantics for stack objects vs. copying stack pointers vs. copying stack structs), it's impossible for Copyto introduce a heap allocation. But why is this the case? Fundamentally, it's because the language controls what Copy means -"the behavior of Copy is not overloadable"because it's a marker trait. From there we'll note that a typecan implement Copyif (and only if) its components implement Copy, and thatno heap-allocated types implement Copy. Thus, assignments involving heap types are always move semantics, and new heap allocations won't occur because of implicit operator behavior. #[derive(Clone)] struct Cloneable { x: Box<u64> } // error[E0204]: the trait `Copy` may not be implemented for this type #[derive(Copy, Clone)] struct NotCopyable { x: Box<u64> } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Iterators​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#iterators","content":" In managed memory languages (likeJava), there's a subtle difference between these two code samples: public static int sum_for(List<Long> vals) { long sum = 0; // Regular for loop for (int i = 0; i < vals.length; i++) { sum += vals[i]; } return sum; } public static int sum_foreach(List<Long> vals) { long sum = 0; // "Foreach" loop - uses iteration for (Long l : vals) { sum += l; } return sum; } In the sum_for function, nothing terribly interesting happens. In sum_foreach, an object of typeIteratoris allocated on the heap, and will eventually be garbage-collected. This isn't a great design; iterators are often transient objects that you need during a function and can discard once the function ends. Sounds exactly like the issue stack-allocated objects address, no? In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in heap memory, but the iterator itself (Iter) doesn't need to use the heap. In each of the examples below we iterate over a collection, but never use heap allocation: use std::collections::HashMap; // There's a lot of assembly generated, but if you search in the text, // there are no references to `real_drop_in_place` anywhere. pub fn sum_vec(x: &Vec<u32>) { let mut s = 0; // Basic iteration over vectors doesn't need allocation for y in x { s += y; } } pub fn sum_enumerate(x: &Vec<u32>) { let mut s = 0; // More complex iterators are just fine too for (_i, y) in x.iter().enumerate() { s += y; } } pub fn sum_hm(x: &HashMap<u32, u32>) { let mut s = 0; // And it's not just Vec, all types will allocate the iterator // on stack memory for y in x.values() { s += y; } } -- Compiler Explorer ","version":null,"tagName":"h2"}],"options":{"id":"default"}} \ No newline at end of file diff --git a/search-doc.json b/search-doc.json new file mode 100644 index 0000000..6825e18 --- /dev/null +++ b/search-doc.json @@ -0,0 +1 @@ +{"searchDocs":[{"title":"The webpack industrial complex","type":0,"sectionRef":"#","url":"/2011/11/webpack-industrial-complex","content":"","keywords":"","version":null},{"title":"Starting strong​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#starting-strong","content":" The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser." Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an onEvent handler and a function easy. Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical." ","version":null,"tagName":"h2"},{"title":"Continuing on​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#continuing-on","content":" Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead? The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API was missing. After searching out Github issues and (unsuccessfully) tweaking the .tsconfig settings, I settled on installing a package and moving on. The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use new URL(<local path>, import.meta.url) and it worked! Well, kind of: That file has the audio processor code, so why does it get served with Content-Type: video/mp2t? ","version":null,"tagName":"h2"},{"title":"Floundering about​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#floundering-about","content":" Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to just use JavaScript and stuck by the original TypeScript requirement. I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package. I tried three different CRA tools - react-app-rewired, craco, customize-react-app - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well. I tried changing the webpack configuration: using new loaders, setting asset rules, even changing how webpack detects worker resources. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up. I tried so many application frameworks. Next.js looked like a good candidate, but added its own bespoke webpack complexity to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work. ","version":null,"tagName":"h2"},{"title":"Learning and reflecting​","type":1,"pageTitle":"The webpack industrial complex","url":"/2011/11/webpack-industrial-complex#learning-and-reflecting","content":" I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned. For myself: I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important workI tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts For the tools: Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexityWebpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaksThere's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down. ","version":null,"tagName":"h2"},{"title":"Autocallable Bonds","type":0,"sectionRef":"#","url":"/2015/11/autocallable","content":"","keywords":"","version":null},{"title":"Underlying simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#underlying-simulation","content":" In order to price the autocallable bonds, we need to simulate the underlying assets. Let's go ahead and set up the simulation first, as this lays the foundation for what we're trying to do. We're going to use JNJ as the basis for our simulation. This implies the following parameters: S0S_0S0​ = $102.2 (as of time of writing)qqq = 2.84%rrr = [.49, .9, 1.21, 1.45, 1.69] (term structure as of time of writing, linear interpolation)μ\\muμ = r−qr - qr−q (note that this implies a negative drift because of current low rates)σ\\sigmaσ = σimp\\sigma_{imp}σimp​ = 15.62% (from VIX implied volatility) We additionally define some parameters for simulation: T: The number of years to simulatem: The number of paths to simulaten: The number of steps to simulate in a year S0 = 102.2 nominal = 100 q = 2.84 / 100 σ = 15.37 / 100 term = [0, .49, .9, 1.21, 1.45, 1.69] / 100 + 1 ### # Potential: Based on PEP # S0 = 100.6 # σ = 14.86 # q = 2.7 ### # Simulation parameters T = 5 # Using years as the unit of time n = 250 # simulations per year m = 100000 # paths num_simulations = 5; # simulation rounds per price ","version":null,"tagName":"h2"},{"title":"Defining the simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#defining-the-simulation","content":" To make things simpler, we simulate a single year at a time. This allows us to easily add in a dividend policy without too much difficulty, and update the simulation every year to match the term structure. The underlying uses GBM for simulation between years. simulate_gbm = function(S0, μ, σ, T, n) # Set the initial state m = length(S0) t = T / n motion = zeros(m, n) motion[:,1] = S0 # Build out all states for i=1:(n-1) motion[:,i+1] = motion[:,i] .* exp((μ - σ^2/2)*t) .* exp(sqrt(t) * σ .* randn(m)) end return motion end function display_motion(motion, T) # Given a matrix of paths, display the motion n = length(motion[1,:]) m = length(motion[:,1]) x = repmat(1:n, m) # Calculate the ticks we're going to use. We'd like to # have an xtick every month, so calculate where those # ticks will actually be at. if (T > 3) num_ticks = T xlabel = "Years" else num_ticks = T * 12 xlabel = "Months" end tick_width = n / num_ticks x_ticks = [] for i=1:round(num_ticks) x_ticks = vcat(x_ticks, i*tick_width) end # Use one color for each path. I'm not sure if there's # a better way to do this without going through DataFrames colors = [] for i = 1:m colors = vcat(colors, ones(n)*i) end plot(x=x, y=motion', color=colors, Geom.line, Guide.xticks(ticks=x_ticks, label=false), Guide.xlabel(xlabel), Guide.ylabel("Value")) end; ","version":null,"tagName":"h3"},{"title":"Example simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#example-simulation","content":" Let's go ahead and run a sample simulation to see what the functions got us! initial = ones(5) * S0 # Using μ=0, T=.25 for now, we'll use the proper values later motion = simulate_gbm(initial, 0, σ, .25, 200) display_motion(motion, .25) ","version":null,"tagName":"h3"},{"title":"Computing the term structure​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#computing-the-term-structure","content":" Now that we've got the basic motion set up, let's start making things a bit more sophisticated for the model. We're going to assume that the drift of the stock is the difference between the implied forward rate and the quarterly dividend rate. We're given the yearly term structure, and need to calculate the quarterly forward rate to match this structure. The term structure is assumed to follow: d(0,t)=d(0,t−1)⋅fi−1,id(0, t) = d(0,t-1)\\cdot f_{i-1, i}d(0,t)=d(0,t−1)⋅fi−1,i​ Where fi−1,if_{i-1, i}fi−1,i​ is the quarterly forward rate. forward_term = function(yearly_term) # It is assumed that we have a yearly term structure passed in, and starts at year 0 # This implies a nominal rate above 0 for the first year! years = length(term)-1 # because we start at 0 structure = [(term[i+1] / term[i]) for i=1:years] end; ","version":null,"tagName":"h3"},{"title":"Illustrating the term structure​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#illustrating-the-term-structure","content":" Now that we've got our term structure, let's validate that we're getting the correct results! If we've done this correctly, then: term[2] == term[1] * structure[1] # Example term structure taken from: # http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield # Linear interpolation used years in-between periods, assuming real-dollar # interest rates forward_yield = forward_term(term) calculated_term2 = term[1] * forward_yield[1] println("Actual term[2]: $(term[2]); Calculated term[2]: $(calculated_term2)") Actual term[2]: 1.0049; Calculated term[2]: 1.0049 ","version":null,"tagName":"h3"},{"title":"The full underlying simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#the-full-underlying-simulation","content":" Now that we have the term structure set up, we can actually start doing some real simulation! Let's construct some paths through the full 5-year time frame. In order to do this, we will simulate 1 year at a time, and use the forward rates at those times to compute the drift. Thus, there will be 5 total simulations batched together. full_motion = ones(5) * S0 full_term = vcat(term[1], forward_yield) for i=1:T μ = (full_term[i] - 1 - q) year_motion = simulate_gbm(full_motion[:,end], μ, σ, 1, n) full_motion = hcat(full_motion, year_motion) end display_motion(full_motion, T) ","version":null,"tagName":"h3"},{"title":"Final simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#final-simulation","content":" We're now going to actually build out the full motion that we'll use for computing the pricing of our autocallable products. It will be largely the same, but we will use far more sample paths for the simulation. full_simulation = function(S0, T, n, m, term) forward = vcat(term[1], forward_term(term)) # And an S0 to kick things off. final_motion = ones(m) * S0 for i=1:T μ = (forward[i] - 1 - q) year_motion = simulate_gbm(final_motion[:,end], μ, σ, 1, n) final_motion = hcat(final_motion, year_motion) end return final_motion end tic() full_simulation(S0, T, n, m, term) time = toq() @printf("Time to run simulation: %.2fs", time) Time to run simulation: 5.34s ","version":null,"tagName":"h3"},{"title":"Athena Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#athena-simulation","content":" Now that we've defined our underlying simulation, let's actually try and price an Athena note. Athena has the following characteristics: Automatically called if the underlying is above the call barrier at observationAccelerated coupon paid if the underlying is above the call barrier at observation The coupon paid is c⋅ic \\cdot ic⋅i with iii as the current year, and ccc the coupon rate Principle protection up until a protection barrier at observation; All principle at risk if this barrier not metObserved yearly call_barrier = S0 strike = S0 protection_barrier = S0 * .6 coupon = nominal * .07 price_athena = function(initial_price, year_prices, call_barrier, protection_barrier, coupon, forward_structure) total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price ≥ call_barrier return (nominal + coupon*i) * exp((prod(forward_structure[i:end])-1)*(t-i)) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_athena(S0, year_prices, call_barrier, protection_barrier, coupon, forward_structure) athena = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = athena() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * (exp(-(prod(forward_structure)-1)*T)) @printf("Present value of Athena note: \\$%.2f, notional: \\$%.2f", pv, nominal) Mean of simulation 1: $103.2805; Simulation time: 5.59s Mean of simulation 2: $103.3796; Simulation time: 5.05s Mean of simulation 3: $103.4752; Simulation time: 5.18s Mean of simulation 4: $103.4099; Simulation time: 5.37s Mean of simulation 5: $103.3260; Simulation time: 5.32s Mean over 5 simulations: 103.37421610015554 Present value of Athena note: $95.00, notional: $100.00 ","version":null,"tagName":"h2"},{"title":"Phoenix without Memory Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#phoenix-without-memory-simulation","content":" Let's move into pricing a Phoenix without memory. It's very similar to the Athena production, with the exception that we introduce a coupon barrier so coupons are paid even when the underlying is below the initial price. The Phoenix product has the following characteristics (example here): Automatically called if the underlying is above the call barrier at observationCoupon paid if the underlying is above a coupon barrier at observationPrinciple protection up until a protection barrier at observation; All principle at risk if this barrier not metObserved yearly Some example paths (all assume that a call barrier of the current price, and coupon barrier some level below that): At the end of year 1, the stock is above the call barrier; the note is called and you receive the value of the stock plus the coupon being paid.At the end of year 1, the stock is above the coupon barrier, but not the call barrier; you receive the coupon. At the end of year 2, the stock is below the coupon barrier; you receive nothing. At the end of year 3, the stock is above the call barrier; the note is called and you receive the value of the stock plus a coupon for year 3. We're going to re-use the same simulation, with the following parameters: Call barrier: 100%Coupon barrier: 70%Coupon: 6%Capital protection until 70% (at maturity) call_barrier = S0 coupon_barrier = S0 * .8 protection_barrier = S0 * .6 coupon = nominal * .06 price_phoenix_no_memory = function(initial_price, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price ≥ call_barrier return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i)) elseif price ≥ coupon_barrier total_coupons = total_coupons * exp(forward_structure[i]-1) + coupon else total_coupons *= exp(forward_structure[i]-1) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal + total_coupons else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_phoenix_no_memory(S0, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) phoenix_no_memory = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = phoenix_no_memory() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * exp(-(prod(forward_structure)-1)*(T)) @printf("Present value of Phoenix without memory note: \\$%.2f", pv) Mean of simulation 1: $106.0562; Simulation time: 5.72s Mean of simulation 2: $106.0071; Simulation time: 5.85s Mean of simulation 3: $105.9959; Simulation time: 5.87s Mean of simulation 4: $106.0665; Simulation time: 5.93s Mean of simulation 5: $106.0168; Simulation time: 5.81s Mean over 5 simulations: 106.02850857209883 Present value of Phoenix without memory note: $97.44 ","version":null,"tagName":"h2"},{"title":"Phoenix with Memory Simulation​","type":1,"pageTitle":"Autocallable Bonds","url":"/2015/11/autocallable#phoenix-with-memory-simulation","content":" The Phoenix with Memory structure is very similar to the Phoenix, but as the name implies, has a special "memory" property: It remembers any coupons that haven't been paid at prior observation times, and pays them all if the underlying crosses the coupon barrier. For example: Note issued with 100% call barrier, 70% coupon barrier. At year 1, the underlying is at 50%, so no coupons are paid. At year 2, the underlying is at 80%, so coupons for both year 1 and 2 are paid, resulting in a double coupon. You can also find an example here. Let's go ahead and set up the simulation! The parameters will be the same, but we can expect that the value will go up because of the memory attribute call_barrier = S0 coupon_barrier = S0 * .8 protection_barrier = S0 * .6 coupon = nominal * .07 price_phoenix_with_memory = function(initial_price, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) last_coupon = 0 total_coupons = 0 t = length(year_prices) for i=1:t price = year_prices[i] if price > call_barrier return (nominal + coupon + total_coupons)*exp((prod(forward_structure[i:end])-1)*(t-i)) elseif price > coupon_barrier #################################################################### # The only difference between with/without memory is the below lines memory_coupons = (i - last_coupon) * coupon last_coupon = i total_coupons = total_coupons * exp(forward_structure[i]-1) + memory_coupons #################################################################### else total_coupons *= exp(forward_structure[i]-1) end end # We've reached maturity, time to check capital protection if year_prices[end] > protection_barrier return nominal + total_coupons else put = (strike - year_prices[end]) / strike return nominal*(1-put) end end forward_structure = forward_term(term) price_function = (year_prices) -> price_phoenix_with_memory(S0, year_prices, call_barrier, coupon_barrier, protection_barrier, coupon, forward_structure) phoenix_with_memory = function() year_indexes = [n*i for i=1:T] motion = full_simulation(S0, T, n, m, term) payoffs = [price_function(motion[i, year_indexes]) for i=1:m] return mean(payoffs) end mean_payoffs = zeros(num_simulations) for i=1:num_simulations tic() mean_payoffs[i] = phoenix_with_memory() time = toq() @printf("Mean of simulation %i: \\$%.4f; Simulation time: %.2fs\\n", i, mean_payoffs[i], time) end final_mean = mean(mean_payoffs) println("Mean over $num_simulations simulations: $(mean(mean_payoffs))") pv = final_mean * exp(-(prod(forward_structure)-1)*(T)) @printf("Present value of Phoenix with memory note: \\$%.2f", pv) Mean of simulation 1: $108.8612; Simulation time: 5.89s Mean of simulation 2: $109.0226; Simulation time: 5.90s Mean of simulation 3: $108.9175; Simulation time: 5.92s Mean of simulation 4: $108.9426; Simulation time: 5.94s Mean of simulation 5: $108.8087; Simulation time: 6.06s Mean over 5 simulations: 108.91052564051816 Present value of Phoenix with memory note: $100.09 ","version":null,"tagName":"h2"},{"title":"Welcome, and an algorithm","type":0,"sectionRef":"#","url":"/2015/11/welcome","content":"","keywords":"","version":null},{"title":"Trading Competition Optimization​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#trading-competition-optimization","content":" Goal: Max return given maximum Sharpe and Drawdown from IPython.display import display import Quandl from datetime import datetime, timedelta tickers = ['XOM', 'CVX', 'CLB', 'OXY', 'SLB'] market_ticker = 'GOOG/NYSE_VOO' lookback = 30 d_col = 'Close' data = {tick: Quandl.get('YAHOO/{}'.format(tick))[-lookback:] for tick in tickers} market = Quandl.get(market_ticker) ","version":null,"tagName":"h2"},{"title":"Calculating the Return​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-return","content":" We first want to know how much each ticker returned over the prior period. returns = {tick: data[tick][d_col].pct_change() for tick in tickers} display({tick: returns[tick].mean() for tick in tickers}) {'CLB': -0.0016320202164526894, 'CVX': 0.0010319531629488911, 'OXY': 0.00093418904454400551, 'SLB': 0.00098431254720448159, 'XOM': 0.00044165797556096868} ","version":null,"tagName":"h2"},{"title":"Calculating the Sharpe ratio​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-sharpe-ratio","content":" Sharpe: R−RMσ{R - R_M \\over \\sigma}σR−RM​​ We use the average return over the lookback period, minus the market average return, over the ticker standard deviation to calculate the Sharpe. Shorting a stock turns a negative Sharpe positive. market_returns = market.pct_change() sharpe = lambda ret: (ret.mean() - market_returns[d_col].mean()) / ret.std() sharpes = {tick: sharpe(returns[tick]) for tick in tickers} display(sharpes) {'CLB': -0.10578734457846127, 'CVX': 0.027303529817677398, 'OXY': 0.022622210057414487, 'SLB': 0.026950946344858676, 'XOM': -0.0053519259698605499} ","version":null,"tagName":"h2"},{"title":"Calculating the drawdown​","type":1,"pageTitle":"Welcome, and an algorithm","url":"/2015/11/welcome#calculating-the-drawdown","content":" This one is easy - what is the maximum daily change over the lookback period? That is, because we will allow short positions, we are not concerned strictly with maximum downturn, but in general, what is the largest 1-day change? drawdown = lambda ret: ret.abs().max() drawdowns = {tick: drawdown(returns[tick]) for tick in tickers} display(drawdowns) {'CLB': 0.043551495607375035, 'CVX': 0.044894389686214398, 'OXY': 0.051424517867144637, 'SLB': 0.034774627850375328, 'XOM': 0.035851524605672758} Performing the optimization max μ⋅ωs.t. 1⃗ω=1S⃗ω≥sD⃗⋅∣ω∣≤d∣ω∣≤l\\begin{align*} max\\ \\ & \\mu \\cdot \\omega\\\\ s.t.\\ \\ & \\vec{1} \\omega = 1\\\\ & \\vec{S} \\omega \\ge s\\\\ & \\vec{D} \\cdot | \\omega | \\le d\\\\ & \\left|\\omega\\right| \\le l\\\\ \\end{align*}max s.t. ​μ⋅ω1ω=1Sω≥sD⋅∣ω∣≤d∣ω∣≤l​ We want to maximize average return subject to having a full portfolio, Sharpe above a specific level, drawdown below a level, and leverage not too high - that is, don't have huge long/short positions. import numpy as np from scipy.optimize import minimize #sharpe_limit = .1 drawdown_limit = .05 leverage = 250 # Use the map so we can guarantee we maintain the correct order # So we can write as upper-bound # sharpe_a = np.array(list(map(lambda tick: sharpes[tick], tickers))) * -1 dd_a = np.array(list(map(lambda tick: drawdowns[tick], tickers))) # Because minimizing returns_a = np.array(list(map(lambda tick: returns[tick].mean(), tickers))) meets_sharpe = lambda x: sum(abs(x) * sharpe_a) - sharpe_limit def meets_dd(x): portfolio = sum(abs(x)) if portfolio < .1: # If there are no stocks in the portfolio, # we can accidentally induce division by 0, # or division by something small enough to cause infinity return 0 return drawdown_limit - sum(abs(x) * dd_a) / sum(abs(x)) is_portfolio = lambda x: sum(x) - 1 def within_leverage(x): return leverage - sum(abs(x)) objective = lambda x: sum(x * returns_a) * -1 # Because we're minimizing bounds = ((None, None),) * len(tickers) x = np.zeros(len(tickers)) constraints = [ { 'type': 'eq', 'fun': is_portfolio }, { 'type': 'ineq', 'fun': within_leverage #}, { # 'type': 'ineq', # 'fun': meets_sharpe }, { 'type': 'ineq', 'fun': meets_dd } ] optimal = minimize(objective, x, bounds=bounds, constraints=constraints, options={'maxiter': 500}) # Optimization time! display(optimal.message) display("Holdings: {}".format(list(zip(tickers, optimal.x)))) # multiply by -100 to scale, and compensate for minimizing expected_return = optimal.fun * -100 display("Expected Return: {:.3f}%".format(expected_return)) expected_drawdown = sum(abs(optimal.x) * dd_a) / sum(abs(optimal.x)) * 100 display("Expected Max Drawdown: {0:.2f}%".format(expected_drawdown)) # TODO: Calculate expected Sharpe 'Optimization terminated successfully.' "Holdings: [('XOM', 5.8337945679814904), ('CVX', 42.935064321851307), ('CLB', -124.5), ('OXY', 36.790387773552119), ('SLB', 39.940753336615096)]" 'Expected Return: 32.375%' 'Expected Max Drawdown: 4.34%' ","version":null,"tagName":"h2"},{"title":"Testing Cramer","type":0,"sectionRef":"#","url":"/2015/12/testing-cramer","content":"","keywords":"","version":null},{"title":"Downloading Futures data from Seeking Alpha​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#downloading-futures-data-from-seeking-alpha","content":" We're going to define two HTML parsing classes - one to get the article URL's from a page, and one to get the actual data from each article. class ArticleListParser(HTMLParser): """Given a web page with articles on it, parse out the article links""" articles = [] def handle_starttag(self, tag, attrs): #if tag == 'div' and ("id", "author_articles_wrapper") in attrs: # self.fetch_links = True if tag == 'a' and ('class', 'dashboard_article_link') in attrs: href = list(filter(lambda x: x[0] == 'href', attrs))[0][1] self.articles.append(href) base_url = "http://seekingalpha.com/author/wall-street-breakfast/articles" article_page_urls = [base_url] + [base_url + '/{}'.format(i) for i in range(2, 20)] global_articles = [] for page in article_page_urls: # We need to switch the user agent, as SA blocks the standard requests agent articles_html = requests.get(page, headers={"User-Agent": "Wget/1.13.4"}) parser = ArticleListParser() parser.feed(articles_html.text) global_articles += (parser.articles) class ArticleReturnParser(HTMLParser): "Given an article, parse out the futures returns in it" record_font_tags = False in_font_tag = False counter = 0 # data = {} # See __init__ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = {} def handle_starttag(self, tag, attrs): if tag == 'span' and ('itemprop', 'datePublished') in attrs: date_string = list(filter(lambda x: x[0] == 'content', attrs))[0][1] date = dtparser.parse(date_string) self.data['date'] = date self.in_font_tag = tag == 'font' def safe_float(self, string): try: return float(string[:-1]) / 100 except ValueError: return np.NaN def handle_data(self, content): if not self.record_font_tags and "Futures at 6" in content: self.record_font_tags = True if self.record_font_tags and self.in_font_tag: if self.counter == 0: self.data['DOW'] = self.safe_float(content) elif self.counter == 1: self.data['S&P'] = self.safe_float(content) elif self.counter == 2: self.data['NASDAQ'] = self.safe_float(content) elif self.counter == 3: self.data['Crude'] = self.safe_float(content) elif self.counter == 4: self.data['Gold'] = self.safe_float(content) self.counter += 1 def handle_endtag(self, tag): self.in_font_tag = False def retrieve_data(url): sa = "http://seekingalpha.com" article_html = requests.get(sa + url, headers={"User-Agent": "Wget/1.13.4"}) parser = ArticleReturnParser() parser.feed(article_html.text) parser.data.update({"url": url}) parser.data.update({"text": article_html.text}) return parser.data # This copy **MUST** be in place. I'm not sure why, # as you'd think that the data being returned would already # represent a different memory location. Even so, it blows up # if you don't do this. article_list = list(set(global_articles)) article_data = [copy(retrieve_data(url)) for url in article_list] # If there's an issue downloading the article, drop it. article_df = pd.DataFrame.from_dict(article_data).dropna() ","version":null,"tagName":"h2"},{"title":"Fetching the Returns data​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#fetching-the-returns-data","content":" Now that we have the futures data, we're going to compare across 4 different indices - the S&P 500 index, Dow Jones Industrial, Russell 2000, and NASDAQ 100. Let's get the data off of Quandl to make things easier! # article_df is sorted by date, so we get the first row. start_date = article_df.sort_values(by='date').iloc[0]['date'] - relativedelta(days=1) SPY = Quandl.get("GOOG/NYSE_SPY", trim_start=start_date) DJIA = Quandl.get("GOOG/AMS_DIA", trim_start=start_date) RUSS = Quandl.get("GOOG/AMEX_IWM", trim_start=start_date) NASDAQ = Quandl.get("GOOG/EPA_QQQ", trim_start=start_date) ","version":null,"tagName":"h2"},{"title":"Running the Comparison​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#running-the-comparison","content":" There are two types of tests I want to determine: How accurate each futures category is at predicting the index's opening change over the close before, and predicting the index's daily return. Let's first calculate how good each future is at predicting the opening return over the previous day. I expect that the futures will be more than 50% accurate, since the information is recorded 3 hours before the markets open. def calculate_opening_ret(frame): # I'm not a huge fan of the appending for loop, # but it's a bit verbose for a comprehension data = {} for i in range(1, len(frame)): date = frame.iloc[i].name prior_close = frame.iloc[i-1]['Close'] open_val = frame.iloc[i]['Open'] data[date] = (open_val - prior_close) / prior_close return data SPY_open_ret = calculate_opening_ret(SPY) DJIA_open_ret = calculate_opening_ret(DJIA) RUSS_open_ret = calculate_opening_ret(RUSS) NASDAQ_open_ret = calculate_opening_ret(NASDAQ) def signs_match(list_1, list_2): # This is a surprisingly difficult task - we have to match # up the dates in order to check if opening returns actually match index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()} matches = [] for row in list_1.iterrows(): row_dt = row[1][1] row_value = row[1][0] index_dt = datetime(row_dt.year, row_dt.month, row_dt.day) if index_dt in list_2: index_value = list_2[index_dt] if (row_value > 0 and index_value > 0) or \\ (row_value < 0 and index_value < 0) or \\ (row_value == 0 and index_value == 0): matches += [1] else: matches += [0] #print("{}".format(list_2[index_dt])) return matches prediction_dict = {} matches_dict = {} count_dict = {} index_dict = {"SPY": SPY_open_ret, "DJIA": DJIA_open_ret, "RUSS": RUSS_open_ret, "NASDAQ": NASDAQ_open_ret} indices = ["SPY", "DJIA", "RUSS", "NASDAQ"] futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"] for index in indices: matches_dict[index] = {future: signs_match(article_df[[future, 'date']], index_dict[index]) for future in futures} count_dict[index] = {future: len(matches_dict[index][future]) for future in futures} prediction_dict[index] = {future: np.mean(matches_dict[index][future]) for future in futures} print("Articles Checked: ") print(pd.DataFrame.from_dict(count_dict)) print() print("Prediction Accuracy:") print(pd.DataFrame.from_dict(prediction_dict)) Articles Checked: DJIA NASDAQ RUSS SPY Crude 268 268 271 271 DOW 268 268 271 271 Gold 268 268 271 271 NASDAQ 268 268 271 271 S&P 268 268 271 271 Prediction Accuracy: DJIA NASDAQ RUSS SPY Crude 0.544776 0.522388 0.601476 0.590406 DOW 0.611940 0.604478 0.804428 0.841328 Gold 0.462687 0.455224 0.464945 0.476015 NASDAQ 0.615672 0.608209 0.797048 0.830258 S&P 0.604478 0.597015 0.811808 0.848708 This data is very interesting. Some insights: Both DOW and NASDAQ futures are pretty bad at predicting their actual market openingsNASDAQ and Dow are fairly unpredictable; Russell 2000 and S&P are very predictableGold is a poor predictor in general - intuitively Gold should move inverse to the market, but it appears to be about as accurate as a coin flip. All said though it appears that futures data is important for determining market direction for both the S&P 500 and Russell 2000. Cramer is half-right: futures data isn't very helpful for the Dow and NASDAQ indices, but is great for the S&P and Russell indices. ","version":null,"tagName":"h2"},{"title":"The next step - Predicting the close​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#the-next-step---predicting-the-close","content":" Given the code we currently have, I'd like to predict the close of the market as well. We can re-use most of the code, so let's see what happens: def calculate_closing_ret(frame): # I'm not a huge fan of the appending for loop, # but it's a bit verbose for a comprehension data = {} for i in range(0, len(frame)): date = frame.iloc[i].name open_val = frame.iloc[i]['Open'] close_val = frame.iloc[i]['Close'] data[date] = (close_val - open_val) / open_val return data SPY_close_ret = calculate_closing_ret(SPY) DJIA_close_ret = calculate_closing_ret(DJIA) RUSS_close_ret = calculate_closing_ret(RUSS) NASDAQ_close_ret = calculate_closing_ret(NASDAQ) def signs_match(list_1, list_2): # This is a surprisingly difficult task - we have to match # up the dates in order to check if opening returns actually match index_dict_dt = {key.to_datetime(): list_2[key] for key in list_2.keys()} matches = [] for row in list_1.iterrows(): row_dt = row[1][1] row_value = row[1][0] index_dt = datetime(row_dt.year, row_dt.month, row_dt.day) if index_dt in list_2: index_value = list_2[index_dt] if (row_value > 0 and index_value > 0) or \\ (row_value < 0 and index_value < 0) or \\ (row_value == 0 and index_value == 0): matches += [1] else: matches += [0] #print("{}".format(list_2[index_dt])) return matches matches_dict = {} count_dict = {} prediction_dict = {} index_dict = {"SPY": SPY_close_ret, "DJIA": DJIA_close_ret, "RUSS": RUSS_close_ret, "NASDAQ": NASDAQ_close_ret} indices = ["SPY", "DJIA", "RUSS", "NASDAQ"] futures = ["Crude", "Gold", "DOW", "NASDAQ", "S&P"] for index in indices: matches_dict[index] = {future: signs_match(article_df[[future, 'date']], index_dict[index]) for future in futures} count_dict[index] = {future: len(matches_dict[index][future]) for future in futures} prediction_dict[index] = {future: np.mean(matches_dict[index][future]) for future in futures} print("Articles Checked:") print(pd.DataFrame.from_dict(count_dict)) print() print("Prediction Accuracy:") print(pd.DataFrame.from_dict(prediction_dict)) Articles Checked: DJIA NASDAQ RUSS SPY Crude 268 268 271 271 DOW 268 268 271 271 Gold 268 268 271 271 NASDAQ 268 268 271 271 S&P 268 268 271 271 Prediction Accuracy: DJIA NASDAQ RUSS SPY Crude 0.533582 0.529851 0.501845 0.542435 DOW 0.589552 0.608209 0.535055 0.535055 Gold 0.455224 0.451493 0.483395 0.512915 NASDAQ 0.582090 0.626866 0.531365 0.538745 S&P 0.585821 0.608209 0.535055 0.535055 Well, it appears that the futures data is terrible at predicting market close. NASDAQ predicting NASDAQ is the most interesting data point, but 63% accuracy isn't accurate enough to make money consistently. ","version":null,"tagName":"h2"},{"title":"Final sentiments​","type":1,"pageTitle":"Testing Cramer","url":"/2015/12/testing-cramer#final-sentiments","content":" The data bears out very close to what I expected would happen: Futures data is more accurate than a coin flip for predicting openings, which makes sense since it is recorded only 3 hours before the actual openingFutures data is about as acccurate as a coin flip for predicting closings, which means there is no money to be made in trying to predict the market direction for the day given the futures data. In summary: Cramer is half right: Futures data is not good for predicting the market open of the Dow and NASDAQ indices. Contrary to Cramer though, it is very good for predicting the S&P and Russell indices - we can achieve an accuracy slightly over 80% for each.Making money in the market is hard. We can't just go to the futures and treat them as an oracle for where the market will close. I hope you've enjoyed this, I quite enjoyed taking a deep dive in the analytics this way. I'll be posting more soon! ","version":null,"tagName":"h2"},{"title":"Cloudy in Seattle","type":0,"sectionRef":"#","url":"/2016/01/cloudy-in-seattle","content":"","keywords":"","version":null},{"title":"Examining other cities​","type":1,"pageTitle":"Cloudy in Seattle","url":"/2016/01/cloudy-in-seattle#examining-other-cities","content":" After taking some time to explore how the weather in North Carolina stacked up over the past years, I was interested in doing the same analysis for other cities. Growing up with family from Binghamton, NY I was always told it was very cloudy there. And Seattle has a nasty reputation for being very depressing and cloudy. All said, the cities I want to examine are: Binghamton, NYCary, NCSeattle, WANew York City, NY I'd be interested to try this analysis worldwide at some point - comparing London and Seattle might be an interesting analysis. For now though, we'll stick with trying out the US data. There will be plenty of charts. I want to know: How has average cloud cover and precipitation chance changed over the years for each city mentioned? This will hopefully tell us whether Seattle has actually earned its reputation for being a depressing city. city_forecasts = pickle.load(open('city_forecasts.p', 'rb')) forecasts_df = pd.DataFrame.from_dict(city_forecasts) cities = ['binghamton', 'cary', 'nyc', 'seattle'] city_colors = {cities[i]: Palette[i] for i in range(0, 4)} def safe_cover(frame): if frame and 'cloudCover' in frame: return frame['cloudCover'] else: return np.NaN def monthly_avg_cloudcover(city, year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(forecasts_df[city][x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below. with warnings.catch_warnings(): warnings.simplefilter('ignore') return np.nanmean(cloud_cover_vals), cloud_cover_samples years = range(1990, 2016) def city_avg_cc(city, month): return [monthly_avg_cloudcover(city, y, month) for y in years] months = [ ('July', 7), ('August', 8), ('September', 9), ('October', 10), ('November', 11) ] for month, month_id in months: month_averages = {city: city_avg_cc(city, month_id) for city in cities} f = figure(title="{} Average Cloud Cover".format(month), x_axis_label='Year', y_axis_label='Cloud Cover Percentage') for city in cities: f.line(years, [x[0] for x in month_averages[city]], legend=city, color=city_colors[city]) show(f) Well, as it so happens it looks like there are some data issues. July's data is a bit sporadic, and 2013 seems to be missing from most months as well. I think really only two things can really be confirmed here: Seattle, specifically for the months of October and November, is in fact significantly more cloudy on average than are other citiesAll cities surveyed have seen average cloud cover decline over the months studied. There are data issues, but the trend seems clear. Let's now move from cloud cover data to looking at average rainfall chance. def safe_precip(frame): if frame and 'precipProbability' in frame: return frame['precipProbability'] else: return np.NaN def monthly_avg_precip(city, year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_vals = list(map(lambda x: safe_precip(forecasts_df[city][x]['currently']), dates)) precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals))) # Ignore an issue with nanmean having all NaN values. We'll discuss the data issues below. with warnings.catch_warnings(): warnings.simplefilter('ignore') return np.nanmean(precip_vals), precip_samples def city_avg_precip(city, month): return [monthly_avg_precip(city, y, month) for y in years] for month, month_id in months: month_averages = {city: city_avg_cc(city, month_id) for city in cities} f = figure(title="{} Average Precipitation Chance".format(month), x_axis_label='Year', y_axis_label='Precipitation Chance Percentage') for city in cities: f.line(years, [x[0] for x in month_averages[city]], legend=city, color=city_colors[city]) show(f) The same data issue caveats apply here: 2013 seems to be missing some data, and July has some issues as well. However, this seems to confirm the trends we saw with cloud cover: Seattle, specifically for the months of August, October, and November has had a consistently higher chance of rain than other cities surveyed.Average precipitation chance, just like average cloud cover, has been trending down over time. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Cloudy in Seattle","url":"/2016/01/cloudy-in-seattle#conclusion","content":" I have to admit I was a bit surprised after doing this analysis. Seattle showed a higher average cloud cover and average precipitation chance than did the other cities surveyed. Maybe Seattle is actually an objectively more depressing city to live in. Well that's all for weather data at the moment. It's been a great experiment, but I think this is about as far as I'll be able to get with weather data without some domain knowledge. Talk again soon! ","version":null,"tagName":"h2"},{"title":"Complaining about the weather","type":0,"sectionRef":"#","url":"/2016/01/complaining-about-the-weather","content":"Figuring out whether people should be complaining about the recent weather in North Carolina. from bokeh.plotting import figure, output_notebook, show from bokeh.palettes import PuBuGn9 as Palette import pandas as pd import numpy as np from datetime import datetime import pickle output_notebook() BokehJS successfully loaded. I'm originally from North Carolina, and I've been hearing a lot of people talking about how often it's been raining recently. They're excited for any day that has sun. So I got a bit curious: Has North Carolina over the past few months actually had more cloudy and rainy days recently than in previous years? This shouldn't be a particularly challenging task, but I'm interested to know if people's perceptions actually reflect reality. The data we'll use comes from forecast.io, since they can give us a cloud cover percentage. I've gone ahead and retrieved the data to a pickle file, and included the code that was used to generate it. First up: What was the average cloud cover in North Carolina during August - November, and how many days were cloudy? We're going to assume that a "cloudy" day is defined as any day in which the cloud cover is above 50%. city_forecasts = pickle.load(open('city_forecasts.p', 'rb')) forecast_df = pd.DataFrame.from_dict(city_forecasts) cary_forecast = forecast_df['cary'] years = range(1990, 2016) months = range(7, 12) months_str = ['July', 'August', 'September', 'October', 'November'] def safe_cover(frame): if frame and 'cloudCover' in frame: return frame['cloudCover'] else: return np.NaN def monthly_avg_cloudcover(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) return np.nanmean(cloud_cover_vals), cloud_cover_samples monthly_cover_vals = [[monthly_avg_cloudcover(y, m)[0] for y in years] for m in months] f = figure(title='Monthly Average Cloud Cover', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_cover_vals[x], legend=months_str[x], color=Palette[x]) show(f) As we can see from the chart above, on the whole the monthly average cloud cover has been generally trending down over time. The average cloud cover is also lower than it was last year - it seems people are mostly just complaining. There are some data issues that start in 2012 that we need to be aware of - the cloud cover percentage doesn't exist for all days. Even so, the data that we have seems to reflect the wider trend, so we'll assume for now that the missing data doesn't skew our results. There's one more metric we want to check though - how many cloudy days were there? This is probably a better gauge of sentiment than the average monthly cover. def monthly_cloudy_days(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') cloud_cover_vals = list(map(lambda x: safe_cover(cary_forecast[x]['currently']), dates)) cloud_cover_samples = len(list(filter(lambda x: x is not np.NaN, cloud_cover_vals))) cloudy_days = [cover > .5 for cover in cloud_cover_vals] return np.count_nonzero(cloudy_days), cloud_cover_samples monthly_days_vals = [[monthly_cloudy_days(y, m)[0] for y in years] for m in months] monthly_cover_samples = [[monthly_cloudy_days(y, m)[1] for y in years] for m in months] f = figure(title='Monthly Cloudy Days', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_days_vals[x], legend=months_str[x], color=Palette[x]) show(f) f = figure(title='Monthly Cloud Cover Samples', x_range=(1990, 2015), x_axis_label='Year', height=300) for x in range(0, len(months)): f.line(years, monthly_cover_samples[x], legend=months_str[x], color=Palette[x]) show(f) On the whole, the number of cloudy days seems to reflect the trend with average cloud cover - it's actually becoming more sunny as time progresses. That said, we need to be careful in how we view this number - because there weren't as many samples in 2015 as previous years, the number of days can get thrown off. In context though, even if most days not recorded were in fact cloudy, the overall count for 2015 would still be lower than previous years. In addition to checking cloud cover, I wanted to check precipitation data as well - what is the average precipitation chance over a month, and how many days during a month is rain likely? The thinking is that days with a high-precipitation chance will also be days in which it is cloudy or depressing. def safe_precip(frame): if frame and 'precipProbability' in frame: return frame['precipProbability'] else: return np.NaN def monthly_avg_precip(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates)) precip_samples = len(list(filter(lambda x: x is not np.NaN, precip_vals))) return np.nanmean(precip_vals), precip_samples monthly_avg_precip_vals = [[monthly_avg_precip(y, m)[0] for y in years] for m in months] f = figure(title='Monthly Average Precipitation Chance', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_avg_precip_vals[x], legend=months_str[x], color=Palette[x]) show(f) As we can see from the chart, the average chance of precipitation over a month more or less stays within a band of 0 - .1 for all months over all years. This is further evidence that the past few months are no more cloudy or rainy than previous years. Like the cloud cover though, we still want to get a count of all the rainy days, in addition to the average chance. We'll define a "rainy day" as any day in which the chance of rain is greater than 25%. def monthly_rainy_days(year, month): dates = pd.DatetimeIndex(start=datetime(year, month, 1, 12), end=datetime(year, month + 1, 1, 12), freq='D', closed='left') precip_prob_vals = list(map(lambda x: safe_precip(cary_forecast[x]['currently']), dates)) precip_prob_samples = len(list(filter(lambda x: x is not np.NaN, precip_prob_vals))) precip_days = [prob > .25 for prob in precip_prob_vals] return np.count_nonzero(precip_days), precip_prob_samples monthly_precip_days_vals = [[monthly_rainy_days(y, m)[0] for y in years] for m in months] monthly_precip_samples = [[monthly_rainy_days(y, m)[1] for y in years] for m in months] f = figure(title='Monthly Rainy Days', x_range=(1990, 2015), x_axis_label='Year') for x in range(0, len(months)): f.line(years, monthly_precip_days_vals[x], legend=months_str[x], color=Palette[x]) show(f) f = figure(title='Monthly Rainy Days Samples', x_range=(1990, 2015), x_axis_label='Year', height=300) for x in range(0, len(months)): f.line(years, monthly_precip_samples[x], legend=months_str[x], color=Palette[x]) show(f) After trying to find the number of days that are rainy, we can see that November hit its max value for rainy days in 2015. However, that value is 6, as compared to a previous maximum of 5. While it is a new record, the value isn't actually all that different. And for other months, the values are mostly in-line with the averages. Summary and Conclusions After having looked at forecast data for Cary, it appears that the months of July - November this year in terms of weather were at worst on par with prior years, if not slightly more sunny. This seems to be a case of confirmation bias: someone complains about a string of cloudy or rainy days, and suddenly you start noticing them more. While this analysis doesn't take into account other areas of North Carolina, my initial guess would be to assume that other areas also will show similar results: nothing interesting is happening. Maybe that will be for another blog post later! Coming soon: I'll compare rain/cloud conditions in North Carolina to some other places in the U.S.! Generating the Forecast file The following code was generates the file that was used throughout the blog post. Please note that I'm retrieving data for other cities to use in a future blog post, only Cary data was used for this post. import pandas as pd from functools import reduce import requests from datetime import datetime # Coordinate data from http://itouchmap.com/latlong.html cary_loc = (35.79154,-78.781117) nyc_loc = (40.78306,-73.971249) seattle_loc = (47.60621,-122.332071) binghamton_loc = (42.098687,-75.917974) cities = { 'cary': cary_loc, 'nyc': nyc_loc, 'seattle': seattle_loc, 'binghamton': binghamton_loc } apikey = '' # My super-secret API Key def get_forecast(lat, long, date=None): forecast_base = "https://api.forecast.io/forecast/" if date is None: url = forecast_base + apikey + '/{},{}'.format(lat, long) else: epoch = int(date.timestamp()) url = forecast_base + apikey + '/{},{},{}'.format(lat, long, epoch) return requests.get(url).json() years = range(1990,2016) # For datetimes, the 12 is for getting the weather at noon. # We're doing this over midnight because we're more concerned # with what people see, and people don't typically see the weather # at midnight. dt_indices = [pd.date_range(start=datetime(year, 7, 1, 12), end=datetime(year, 11, 30, 12)) for year in years] dt_merge = reduce(lambda x, y: x.union(y), dt_indices) # Because we have to pay a little bit to use the API, we use for loops here # instead of a comprehension - if something breaks, we want to preserve the # data already retrieved city_forecasts = {} for city, loc in cities.items(): print("Retrieving data for {} starting at {}".format(city, datetime.now().strftime("%I:%M:%S %p"))) for dt in dt_merge: try: city_forecasts[(city, dt)] = get_forecast(*loc, dt) except Exception as e: print(e) city_forecasts[(city, dt)] = None print("End forecast retrieval: {}".format(datetime.now().strftime("%I:%M:%S %p"))) import pickle pickle.dump(city_forecasts, open('city_forecasts.p', 'wb')) ### Output: # Retrieving data for binghamton starting at 05:13:42 PM # Retrieving data for seattle starting at 05:30:51 PM # Retrieving data for nyc starting at 05:48:30 PM # Retrieving data for cary starting at 06:08:32 PM # End forecast retrieval: 06:25:21 PM ","keywords":"","version":null},{"title":"Guaranteed money maker","type":0,"sectionRef":"#","url":"/2016/02/guaranteed-money-maker","content":"","keywords":"","version":null},{"title":"Applying the Martingale Strategy​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#applying-the-martingale-strategy","content":" But we're all realistic people, and once you start talking about "unlimited money" eyebrows should be raised. Even still, this is an interesting strategy to investigate, and I want to apply it to the stock market. As long as we can guarantee there's a single day in which the stock goes up, we should be able to make money right? The question is just how much we have to invest to guarantee this. Now it's time for the math. We'll use the following definitions: oio_ioi​ = the share price at the opening of day iiicic_ici​ = the share price at the close of day iiidid_idi​ = the amount of money we want to invest at the beginning of day iii With those definitions in place, I'd like to present the formula that is guaranteed to make you money. I call it Bradlee's Investment Formula: cn∑i=1ndioi>∑i=1ndic_n \\sum_{i=1}^n \\frac{d_i}{o_i} > \\sum_{i=1}^{n} d_icn​∑i=1n​oi​di​​>∑i=1n​di​ It might not look like much, but if you can manage to make it so that this formula holds true, you will be guaranteed to make money. The intuition behind the formula is this: The closing share price times the number of shares you have purchased ends up greater than the amount of money you invested. That is, on day nnn, if you know what the closing price will be you can set up the amount of money you invest that day to guarantee you make money. I'll even teach you to figure out how much money that is! Take a look: cn∑i=1n−1dioi+cndnon>∑i=1n−1di+dncndnon−dn>∑i=1n−1(di−cndioi)dn(cn−onon)>∑i=1n−1di(1−cnoi)dn>oncn−on∑i=1n−1di(1−1oi)\\begin{align*} c_n \\sum_{i=1}^{n-1} \\frac{d_i}{o_i} + \\frac{c_nd_n}{o_n} &> \\sum_{i=1}^{n-1}d_i + d_n\\\\ \\frac{c_nd_n}{o_n} - d_n &> \\sum_{i=1}^{n-1}(d_i - \\frac{c_nd_i}{o_i})\\\\ d_n (\\frac{c_n - o_n}{o_n}) &> \\sum_{i=1}^{n-1} d_i(1 - \\frac{c_n}{o_i})\\\\ d_n &> \\frac{o_n}{c_n - o_n} \\sum_{i=1}^{n-1} d_i(1 - \\frac{1}{o_i}) \\end{align*}cn​i=1∑n−1​oi​di​​+on​cn​dn​​on​cn​dn​​−dn​dn​(on​cn​−on​​)dn​​>i=1∑n−1​di​+dn​>i=1∑n−1​(di​−oi​cn​di​​)>i=1∑n−1​di​(1−oi​cn​​)>cn​−on​on​​i=1∑n−1​di​(1−oi​1​)​ If you invest exactly dnd_ndn​ that day, you'll break even. But if you can make sure the money you invest is greater than that quantity on the right (which requires that you have a crystal ball tell you the stock's closing price) you are guaranteed to make money! ","version":null,"tagName":"h2"},{"title":"Interesting Implications​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#interesting-implications","content":" On a more serious note though, the formula above tells us a couple of interesting things: It's impossible to make money without the closing price at some point being greater than the opening price (or vice-versa if you are short selling) - there is no amount of money you can invest that will turn things in your favor.Close prices of the past aren't important if you're concerned about the bottom line. While chart technicians use price history to make judgment calls, in the end, the closing price on anything other than the last day is irrelevant.It's possible to make money as long as there is a single day where the closing price is greater than the opening price! You might have to invest a lot to do so, but it's possible.You must make a prediction about where the stock will close at if you want to know how much to invest. That is, we can set up our investment for the day to make money if the stock goes up 1%, but if it only goes up .5% we'll still lose money.It's possible the winning move is to scale back your position. Consider the scenario: You invest money and the stock closes down the day .5%You invest tomorrow expecting the stock to go up 1%The winning investment to break even (assuming a 1% increase) is to scale back the position, since the shares you purchased at the beginning would then be profitable ","version":null,"tagName":"h2"},{"title":"Running the simulation​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#running-the-simulation","content":" So now that we've defined our investment formula,we need to tweak a couple things in order to make an investment strategy we can actually work with. There are two issues we need to address: The formula only tells us how much to invest if we want to break even (dnd_ndn​). If we actually want to turn a profit, we need to invest more than that, which we will refer to as the bias.The formula assumes we know what the closing price will be on any given day. If we don't know this, we can still invest assuming the stock price will close at a level we choose. If the price doesn't meet this objective, we try again tomorrow! This predetermined closing price will be referred to as the expectation. Now that we've defined our bias and expectation, we can actually build a strategy we can simulate. Much like the martingale strategy told you to bet twice your previous bet in order to make money, we've designed a system that tells us how much to bet in order to make money as well. Now, let's get to the code! using Quandl api_key = "" daily_investment = function(current_open, current_close, purchase_history, open_history) # We're not going to safeguard against divide by 0 - that's the user's responsibility t1 = current_close / current_open - 1 t2 = sum(purchase_history - purchase_history*current_close ./ open_history) return t2 / t1 end; And let's code a way to run simulations quickly: is_profitable = function(current_price, purchase_history, open_history) shares = sum(purchase_history ./ open_history) return current_price*shares > sum(purchase_history) end simulate = function(name, start, init, expected, bias) ticker_info = quandlget(name, from=start, api_key=api_key) open_vals = ticker_info["Open"].values close_vals = ticker_info["Close"].values invested = [init] # The simulation stops once we've made a profit day = 1 profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) || is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)]) while !profitable expected_close = open_vals[day+1] * expected todays_purchase = daily_investment(open_vals[day+1], expected_close, invested, open_vals[1:day]) invested = [invested; todays_purchase + bias] # expected_profit = expected_close * sum(invested ./ open_vals[1:length(invested)]) - sum(invested) day += 1 profitable = is_profitable(close_vals[day], invested, open_vals[1:length(invested)]) || is_profitable(open_vals[day+1], invested, open_vals[1:length(invested)]) end shares = sum(invested ./ open_vals[1:length(invested)]) max_profit = max(close_vals[day], open_vals[day+1]) profit = shares * max_profit - sum(invested) return (invested, profit) end sim_summary = function(investments, profit) leverages = [sum(investments[1:i]) for i=1:length(investments)] max_leverage = maximum(leverages) / investments[1] println("Max leverage: $(max_leverage)") println("Days invested: $(length(investments))") println("Profit: $profit") end; Now, let's get some data and run a simulation! Our first test: We'll invest 100 dollars in LMT, and expect that the stock will close up 1% every day. We'll invest dnd_ndn​ + 10 dollars every day that we haven't turned a profit, and end the simulation once we've made a profit. investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.01, 10) sim_summary(investments, profit) Max leverage: 5.590373200042106 Days invested: 5 Profit: 0.6894803101560001 The result: We need to invest 5.6x our initial position over a period of 5 days to make approximately .69¢ Now let's try the same thing, but we'll assume the stock closes up 2% instead. investments, profit = simulate("YAHOO/LMT", Date(2015, 11, 29), 100, 1.02, 10) sim_summary(investments, profit) Max leverage: 1.854949900247809 Days invested: 25 Profit: 0.08304813163696423 In this example, we only get up to a 1.85x leveraged position, but it takes 25 days to turn a profit of 8¢ ","version":null,"tagName":"h2"},{"title":"Summary​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#summary","content":" We've defined an investment strategy that can tell us how much to invest when we know what the closing position of a stock will be. We can tweak the strategy to actually make money, but plenty of work needs to be done so that we can optimize the money invested. In the next post I'm going to post more information about some backtests and strategy tests on this strategy (unless of course this experiment actually produces a significant profit potential, and then I'm keeping it for myself). ","version":null,"tagName":"h2"},{"title":"Side note and disclaimer​","type":1,"pageTitle":"Guaranteed money maker","url":"/2016/02/guaranteed-money-maker#side-note-and-disclaimer","content":" The claims made in this presentation about being able to guarantee making money are intended as a joke and do not constitute investment advice of any sort. ","version":null,"tagName":"h3"},{"title":"Profitability using the investment formula","type":0,"sectionRef":"#","url":"/2016/02/profitability-using-the-investment-formula","content":"","keywords":"","version":null},{"title":"Theoretical Justification​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#theoretical-justification","content":" The formula itself is designed to be simple in principle: I like making a profit, and I want to penalize the leverage you incur and days you have to invest. Ideally, we want to have a stock that goes up all the time. However, the investment formula takes advantage of a different case: trying to profit from highly volatile assets. If we can make money when the investment only has one day up, let's do it! Even so, there are two potential issues: First, stocks that trend upward will have a higher profitability score - both leverage and days invested will be 1. To protect against only investing in this trend, I can do things like taking log⁡(d)\\log(d)log(d). I don't want to start biasing the scoring function until I have a practical reason to do so, so right now I'll leave it standing. The second issue is how to penalize leverage and days invested relative to each other. As it currently stands, a leverage of 6x with only 1 day invested is the same as leveraging 2x with 3 days invested. In the future, I'd again want to look at making the impact of days invested smaller - I can get over an extra 3 days in the market if it means that I don't have to incur a highly leveraged position. So there could be things about the scoring function we change in the future, but I want to run some actual tests before we start worrying about things like that! ","version":null,"tagName":"h2"},{"title":"Running a simulation​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#running-a-simulation","content":" This won't be an incredibly rigorous backtest, I just want to see some results from the work so far. Let's set up the simulation code again, and start looking into some random stocks. If you've read the last blog post, you can skip over the code. The only difference is that it's been ported to python to make the data-wrangling easier. Julia doesn't yet support some of the multi-index things I'm trying to do. import numpy as np import pandas as pd import matplotlib.pyplot as plt from Quandl import get as qget %matplotlib inline api_key = '' profitability = lambda p, i, m, d: 1000*p / (m + i*d) def is_profitable(current_price, purchase_history, open_history): shares = (purchase_history / open_history).sum() return current_price * shares > sum(purchase_history) def daily_investment(current_open, current_close, purchase_history, open_history): t1 = current_close / current_open - 1 t2 = (purchase_history - purchase_history * current_close / open_history).sum() return t2 / t1 def simulate_day(open_vals, close_vals, init, expected, bias): invested = np.array([init]) day = 1 profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\ or is_profitable(open_vals[day], invested, open_vals[0:len(invested)]) while not profitable: expected_close = open_vals[day] * expected todays_purchase = daily_investment(open_vals[day], expected_close, invested, open_vals[0:day]) invested = np.append(invested, todays_purchase + bias) # expected_profit = expected_close * (invested / open_vals[0:len(invested)]).sum() - invested.sum() day += 1 profitable = is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]) \\ or is_profitable(open_vals[day], invested, open_vals[0:len(invested)]) shares = (invested / open_vals[0:len(invested)]).sum() # Make sure we can't see into the future - we know either today's close or tomorrow's open # will be profitable, but we need to check which one. if is_profitable(close_vals[day-1], invested, open_vals[0:len(invested)]): ending_price = close_vals[day-1] else: ending_price = open_vals[day] profit = shares * ending_price - sum(invested) return invested, profit def simulate_ts(name, start, end, initial, expected, bias): ticker_info = qget(name, trim_start=start, api_key=api_key) evaluation_times = ticker_info[:end].index # Handle Google vs. YFinance data if "Adjusted Close" in ticker_info.columns: close_column = "Adjusted Close" else: close_column = "Close" sim = {d: simulate_day(ticker_info[d:]["Open"], ticker_info[d:][close_column], 100, 1.02, 10) for d in evaluation_times} sim_series = pd.Series(sim) result = pd.DataFrame() result["profit"] = sim_series.apply(lambda x: x[1]) result["max"] = sim_series.apply(lambda x: max(x[0])) result["days"] = sim_series.apply(lambda x: len(x[0])) result["score"] = sim_series.apply(lambda x: profitability(x[1], x[0][0], max(x[0]), len(x[0]))) result["investments"] = sim_series.apply(lambda x: x[0]) return result def simulate_tickers(tickers): from datetime import datetime results = {} for ticker in tickers: start = datetime(2015, 1, 1) results_df = simulate_ts(ticker, start, datetime(2016, 1, 1), 100, 1.01, 10) results[ticker] = results_df return pd.concat(list(results.values()), keys=list(results.keys()), axis=1) ","version":null,"tagName":"h2"},{"title":"And now the interesting part​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#and-now-the-interesting-part","content":" Let's start looking into the data! FANG stocks have been big over the past year, let's see how they look: fang_df = simulate_tickers(["YAHOO/FB", "YAHOO/AAPL", "YAHOO/NFLX", "YAHOO/GOOG"]) fang_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); fang_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); Let's think about these graphs. First, the histogram. What we like seeing is a lot of 1's - that means there were a lot of days that the stock went up and we didn't have to worry about actually implementing the strategy - we were able to close the trade at a profit. Looking at the profitability score over time though is a bit more interesting. First off, stocks that are more volatile will tend to have a higher profitability score, no two ways about that. However, Netflix consistently outperformed on this metric. We know that 2015 was a good year for Netflix, so that's a (small) sign the strategy is performing as expected. The final interesting note happens around the end of August 2015. Around this period, the markets were selling off in a big way due to issues in China (not unlike what's happening now). Even so, all of the FANG stocks saw an uptick in profitability around this time. This is another sign that the strategy being developed performs better during periods of volatility, rather than from riding markets up or down. What about FANG vs. some cyclicals? cyclic_df = simulate_tickers(["YAHOO/X", "YAHOO/CAT", "YAHOO/NFLX", "YAHOO/GOOG"]) cyclic_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); cyclic_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); Some more interesting results come from this as well. First off, US Steel (X) has a much smoother distribution of days until profitability - it doesn't have a huge number of values at 1 and then drop off. Intuitively, we're not terribly large fans of this, we want a stock to go up! However, on the profitability score it is the only serious contender to Netflix. Second, we see the same trend around August - the algorithm performs well in volatile markets. For a final test, let's try some biotech and ETFs! biotech_df = simulate_tickers(['YAHOO/REGN', 'YAHOO/CELG', 'GOOG/NASDAQ_BIB', 'GOOG/NASDAQ_IBB']) biotech_df.xs('days', axis=1, level=1).hist() plt.gcf().set_size_inches(18, 8); plt.gcf().suptitle("Distribution of Days Until Profitability", fontsize=18); biotech_df.xs('score', axis=1, level=1).plot() plt.gcf().set_size_inches(18, 6) plt.gcf().suptitle("Profitability score over time", fontsize=18); In this example, we don't see a whole lot of interesting things: the scores are all fairly close together with notable exceptions in late August, and mid-October. What is interesting is that during the volatile period, the ETF's performed significantly better than the stocks did in terms of profitability. The leveraged ETF (BIB) performed far above anyone else, and it appears that indeed, it is most profitable during volatile periods. Even so, it was far more likely to take multiple days to give a return. Its count of 1-day investments trails the other ETF and both stocks by a decent margin. And consider me an OCD freak, but I just really like Celgene's distribution - it looks nice and smooth. ","version":null,"tagName":"h2"},{"title":"Summary and plans for the next post​","type":1,"pageTitle":"Profitability using the investment formula","url":"/2016/02/profitability-using-the-investment-formula#summary-and-plans-for-the-next-post","content":" So far I'm really enjoying playing with this strategy - there's a lot of depth here to understand, though the preliminary results seem to indicate that it profits mostly from taking the other side of a volatile trade. I'd be interested to run results later on data from January - It's been a particularly volatile start to the year so it would be neat to see whether this strategy would work then. For the next post, I want to start playing with some of the parameters: How do the bias and expected close influence the process? The values have been fairly conservative so far, it will be interesting to see how the simulations respond afterward. ","version":null,"tagName":"h2"},{"title":"Predicting Santander customer happiness","type":0,"sectionRef":"#","url":"/2016/03/predicting-santander-customer-happiness","content":"","keywords":"","version":null},{"title":"Data Exploration​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#data-exploration","content":" First up: we need to load our data and do some exploratory work. Because we're going to be using this data for model selection prior to testing, we need to make a further split. I've already gone ahead and done this work, please see the code in the appendix below. import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline # Record how long it takes to run the notebook - I'm curious. from datetime import datetime start = datetime.now() dataset = pd.read_csv('split_train.csv') dataset.index = dataset.ID X = dataset.drop(['TARGET', 'ID', 'ID.1'], 1) y = dataset.TARGET y.unique() array([0, 1], dtype=int64) len(X.columns) 369 Okay, so there are only two classes we're predicting: 1 for unsatisfied customers, 0 for satisfied customers. I would have preferred this to be something more like a regression, or predicting multiple classes: maybe the customer isn't the most happy, but is nowhere near closing their accounts. For now though, that's just the data we're working with. Now, I'd like to make a scatter matrix of everything going on. Unfortunately as noted above, we have 369 different features. There's no way I can graphically make sense of that much data to start with. We're also not told what the data actually represents: Are these survey results? Average time between contact with a customer care person? Frequency of contacting a customer care person? The idea is that I need to reduce the number of dimensions we're predicting across. ","version":null,"tagName":"h2"},{"title":"Dimensionality Reduction pt. 1 - Binary Classifiers​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#dimensionality-reduction-pt-1---binary-classifiers","content":" My first attempt to reduce the data dimensionality is to find all the binary classifiers in the dataset (i.e. 0 or 1 values) and see if any of those are good (or anti-good) predictors of the final data. cols = X.columns b_class = [] for c in cols: if len(X[c].unique()) == 2: b_class.append(c) len(b_class) 111 So there are 111 features in the dataset that are a binary label. Let's see if any of them are good at predicting the users satisfaction! # First we need to `binarize` the data to 0-1; some of the labels are {0, 1}, # some are {0, 3}, etc. from sklearn.preprocessing import binarize X_bin = binarize(X[b_class]) accuracy = [np.mean(X_bin[:,i] == y) for i in range(0, len(b_class))] acc_df = pd.DataFrame({"Accuracy": accuracy}, index=b_class) acc_df.describe() \tAccuracycount\t111.000000 mean\t0.905159 std\t0.180602 min\t0.043598 25%\t0.937329 50%\t0.959372 75%\t0.960837 max\t0.960837 Wow! Looks like we've got some incredibly predictive features! So much so that we should be a bit concerned. My initial guess for what's happening is that we have a sparsity issue: so many of the values are 0, and these likely happen to line up with satisfied customers. So the question we must now answer, which I likely should have asked long before now: What exactly is the distribution of un/satisfied customers? unsat = y[y == 1].count() print("Satisfied customers: {}; Unsatisfied customers: {}".format(len(y) - unsat, unsat)) naive_guess = np.mean(y == np.zeros(len(y))) print("Naive guess accuracy: {}".format(naive_guess)) Satisfied customers: 51131; Unsatisfied customers: 2083 Naive guess accuracy: 0.9608561656706882 This is a bit discouraging. A naive guess of "always satisfied" performs as well as our best individual binary classifier. What this tells me then, is that these data columns aren't incredibly helpful in prediction. I'd be interested in a polynomial expansion of this data-set, but for now, that's more computation than I want to take on. ","version":null,"tagName":"h3"},{"title":"Dimensionality Reduction pt. 2 - LDA​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#dimensionality-reduction-pt-2---lda","content":" Knowing that our naive guess performs so well is a blessing and a curse: Curse: The threshold for performance is incredibly high: We can only "improve" over the naive guess by 4%Blessing: All the binary classification features we just discovered are worthless on their own. We can throw them out and reduce the data dimensionality from 369 to 111. Now, in removing these features from the dataset, I'm not saying that there is no "information" contained within them. There might be. But the only way we'd know is through a polynomial expansion, and I'm not going to take that on within this post. My initial thought for a "next guess" is to use the LDA model for dimensionality reduction. However, it can only reduce dimensions to 1−p1 - p1−p, with ppp being the number of classes. Since this is a binary classification, every LDA model that I try will have dimensionality one; when I actually try this, the predictor ends up being slightly less accurate than the naive guess. Instead, let's take a different approach to dimensionality reduction: principle components analysis. This allows us to perform the dimensionality reduction without worrying about the number of classes. Then, we'll use a Gaussian Naive Bayes model to actually do the prediction. This model is chosen simply because it doesn't take a long time to fit and compute; because PCA will take so long, I just want a prediction at the end of this. We can worry about using a more sophisticated LDA/QDA/SVM model later. Now into the actual process: We're going to test out PCA dimensionality reduction from 1 - 20 dimensions, and then predict using a Gaussian Naive Bayes model. The 20 dimensions upper limit was selected because the accuracy never improves after you get beyond that (I found out by running it myself). Hopefully, we'll find that we can create a model better than the naive guess. from sklearn.naive_bayes import GaussianNB from sklearn.decomposition import PCA X_no_bin = X.drop(b_class, 1) def evaluate_gnb(dims): pca = PCA(n_components=dims) X_xform = pca.fit_transform(X_no_bin) gnb = GaussianNB() gnb.fit(X_xform, y) return gnb.score(X_xform, y) dim_range = np.arange(1, 21) plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy") plt.axhline(naive_guess, label="Naive Guess", c='k') plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k') plt.gcf().set_size_inches(12, 6) plt.legend(); sigh... After all the effort and computational power, we're still at square one: we have yet to beat out the naive guess threshold. With PCA in play we end up performing terribly, but not terribly enough that we can guess against ourselves. Let's try one last-ditch attempt using the entire data set: def evaluate_gnb_full(dims): pca = PCA(n_components=dims) X_xform = pca.fit_transform(X) gnb = GaussianNB() gnb.fit(X_xform, y) return gnb.score(X_xform, y) dim_range = np.arange(1, 21) plt.plot(dim_range, [evaluate_gnb(dim) for dim in dim_range], label="Gaussian NB Accuracy") plt.axhline(naive_guess, label="Naive Guess", c='k') plt.axhline(1 - naive_guess, label="Inverse Naive Guess", c='k') plt.gcf().set_size_inches(12, 6) plt.legend(); Nothing. It is interesting to note that the graphs are almost exactly the same: This would imply again that the variables we removed earlier (all the binary classifiers) indeed have almost no predictive power. It seems this problem is high-dimensional, but with almost no data that can actually inform our decisions. ","version":null,"tagName":"h3"},{"title":"Summary for Day 1​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#summary-for-day-1","content":" After spending a couple hours with this dataset, there seems to be a fundamental issue in play: We have very high-dimensional data, and it has no bearing on our ability to actually predict customer satisfaction. This can be a huge issue: it implies that no matter what model we use, we fundamentally can't perform well. I'm sure most of this is because I'm not an experienced data scientist. Even so, we have yet to develop a strategy that can actually beat out the village idiot; so far, the bank is best off just assuming all its customers are satisfied. Hopefully more to come soon. end = datetime.now() print("Running time: {}".format(end - start)) Running time: 0:00:58.715714 ","version":null,"tagName":"h2"},{"title":"Appendix​","type":1,"pageTitle":"Predicting Santander customer happiness","url":"/2016/03/predicting-santander-customer-happiness#appendix","content":" Code used to split the initial training data: from sklearn.cross_validation import train_test_split data = pd.read_csv('train.csv') data.index = data.ID data_train, data_validate = train_test_split( data, train_size=.7) data_train.to_csv('split_train.csv') data_validate.to_csv('split_validate.csv') ","version":null,"tagName":"h2"},{"title":"Tweet like me","type":0,"sectionRef":"#","url":"/2016/03/tweet-like-me","content":"","keywords":"","version":null},{"title":"The Objective​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-objective","content":" Given an input list of Tweets, build up the following things: The distribution of starting words; since there are no "prior" words to go from, we need to treat this as a special case.The distribution of words given a previous word; for example, every time I use the word woodchuck in the example sentence, there is a 50% chance it is followed by chuck and a 50% chance it is followed by could. I need this distribution for all words.The distribution of quantity of hashtags; Do I most often use just one? Two? Do they follow something like a Poisson distribution?Distribution of hashtags; Given a number of hashtags, what is the actual content? I'll treat hashtags as separate from the content of a tweet. ","version":null,"tagName":"h2"},{"title":"The Data​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-data","content":" I'm using as input my tweet history. I don't really use Twitter anymore, but it seems like a fun use of the dataset. I'd like to eventually build this to a point where I can imitate anyone on Twitter using their last 100 tweets or so, but I'll start with this as example code. ","version":null,"tagName":"h2"},{"title":"The Algorithm​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-algorithm","content":" I'll be using the NLTK library for doing a lot of the heavy lifting. First, let's import the data: import pandas as pd tweets = pd.read_csv('tweets.csv') text = tweets.text # Don't include tweets in reply to or mentioning people replies = text.str.contains('@') text_norep = text.loc[~replies] And now that we've got data, let's start crunching. First, tokenize and build out the distribution of first word: from nltk.tokenize import TweetTokenizer tknzr = TweetTokenizer() tokens = text_norep.map(tknzr.tokenize) first_words = tokens.map(lambda x: x[0]) first_words_alpha = first_words[first_words.str.isalpha()] first_word_dist = first_words_alpha.value_counts() / len(first_words_alpha) Next, we need to build out the conditional distributions. That is, what is the probability of the next word given the current word is XXX? This one is a bit more involved. First, find all unique words, and then find what words proceed them. This can probably be done in a more efficient manner than I'm currently doing here, but we'll ignore that for the moment. from functools import reduce # Get all possible words all_words = reduce(lambda x, y: x+y, tokens, []) unique_words = set(all_words) actual_words = set([x if x[0] != '.' else None for x in unique_words]) word_dist = {} for word in iter(actual_words): indices = [i for i, j in enumerate(all_words) if j == word] proceeding = [all_words[i+1] for i in indices] word_dist[word] = proceeding Now that we've got the tweet analysis done, it's time for the fun part: hashtags! Let's count how many hashtags are in each tweet, I want to get a sense of the distribution. import matplotlib.pyplot as plt %matplotlib inline hashtags = text_norep.str.count('#') bins = hashtags.unique().max() hashtags.plot(kind='hist', bins=bins) <matplotlib.axes._subplots.AxesSubplot at 0x18e59dc28d0> That looks like a Poisson distribution, kind of as I expected. I'm guessing my number of hashtags per tweet is ∼Poi(1)\\sim Poi(1)∼Poi(1), but let's actually find the most likely estimator which in this case is just λˉ\\bar{\\lambda}λˉ: mle = hashtags.mean() mle 0.870236869207003 Pretty close! So we can now simulate how many hashtags are in a tweet. Let's also find what hashtags are actually used: hashtags = [x for x in all_words if x[0] == '#'] n_hashtags = len(hashtags) unique_hashtags = list(set([x for x in unique_words if x[0] == '#'])) hashtag_dist = pd.DataFrame({'hashtags': unique_hashtags, 'prob': [all_words.count(h) / n_hashtags for h in unique_hashtags]}) len(hashtag_dist) 603 Turns out I have used 603 different hashtags during my time on Twitter. That means I was using a unique hashtag for about every third tweet. In better news though, we now have all the data we need to go about actually constructing tweets! The process will happen in a few steps: Randomly select what the first word will be.Randomly select the number of hashtags for this tweet, and then select the actual hashtags.Fill in the remaining space of 140 characters with random words taken from my tweets. And hopefully, we won't have anything too crazy come out the other end. The way we do the selection follows a Multinomial Distribution: given a lot of different values with specific probability, pick one. Let's give a quick example: x: .33 y: .5 z: .17 That is, I pick x with probability 33%, y with probability 50%, and so on. In context of our sentence construction, I've built out the probabilities of specific words already - now I just need to simulate that distribution. Time for the engine to actually be developed! import numpy as np def multinom_sim(n, vals, probs): occurrences = np.random.multinomial(n, probs) results = occurrences * vals return ' '.join(results[results != '']) def sim_n_hashtags(hashtag_freq): return np.random.poisson(hashtag_freq) def sim_hashtags(n, hashtag_dist): return multinom_sim(n, hashtag_dist.hashtags, hashtag_dist.prob) def sim_first_word(first_word_dist): probs = np.float64(first_word_dist.values) return multinom_sim(1, first_word_dist.reset_index()['index'], probs) def sim_next_word(current, word_dist): dist = pd.Series(word_dist[current]) probs = np.ones(len(dist)) / len(dist) return multinom_sim(1, dist, probs) ","version":null,"tagName":"h2"},{"title":"Pulling it all together​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#pulling-it-all-together","content":" I've now built out all the code I need to actually simulate a sentence written by me. Let's try doing an example with five words and a single hashtag: first = sim_first_word(first_word_dist) second = sim_next_word(first, word_dist) third = sim_next_word(second, word_dist) fourth = sim_next_word(third, word_dist) fifth = sim_next_word(fourth, word_dist) hashtag = sim_hashtags(1, hashtag_dist) ' '.join((first, second, third, fourth, fifth, hashtag)) 'My first all-nighter of friends #oldschool' Let's go ahead and put everything together! We're going to simulate a first word, simulate the hashtags, and then simulate to fill the gap until we've either taken up all the space or reached a period. def simulate_tweet(): chars_remaining = 140 first = sim_first_word(first_word_dist) n_hash = sim_n_hashtags(mle) hashtags = sim_hashtags(n_hash, hashtag_dist) chars_remaining -= len(first) + len(hashtags) tweet = first current = first while chars_remaining > len(tweet) + len(hashtags) and current[0] != '.' and current[0] != '!': current = sim_next_word(current, word_dist) tweet += ' ' + current tweet = tweet[:-2] + tweet[-1] return ' '.join((tweet, hashtags)).strip() ","version":null,"tagName":"h2"},{"title":"The results​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#the-results","content":" And now for something completely different: twenty random tweets dreamed up by my computer and my Twitter data. Here you go: for i in range(0, 20): print(simulate_tweet()) print() Also , I'm at 8 this morning. #thursdaysgohard #ornot Turns out of us breathe the code will want to my undergraduate career is becoming more night trying ? Religion is now as a chane #HYPE You know what recursion is to review the UNCC. #ornot There are really sore 3 bonfires in my first writing the library ground floor if awesome. #realtalk #impressed So we can make it out there's nothing but I'm not let us so hot I could think I may be good. #SwingDance Happy Christmas , at Harris Teeter to be be godly or Roman Catholic ). #4b392b#4b392b #Isaiah26 For context , I in the most decisive factor of the same for homework. #accomplishment Freaking done. #loveyouall New blog post : Don't jump in a quiz in with a knife fight. #haskell #earlybirthday God shows me legitimately want to get some food and one day. Stormed the queen city. #mindblown The day of a cold at least outside right before the semester .. Finished with the way back. #winners Waking up , OJ , I feel like Nick Jonas today. First draft of so hard drive. #humansvszombies Eric Whitacre is the wise creation. Ethics paper first , music in close to everyone who just be posting up with my sin , and Jerry Springr #TheLittleThings Love that you know enough time I've eaten at 8 PM. #deepthoughts #stillblownaway Lead. #ThinkingTooMuch #Christmas Aamazing conference when you married #DepartmentOfRedundancyDepartment Yep , but there's a legitimate challenge. ...Which all ended up being a whole lot more nonsensical than I had hoped for. There are some good ones, so I'll call that an accomplishment! I was banking on grammar not being an issue: since my tweets use impeccable grammar, the program modeled off them should have pretty good grammar as well. There are going to be some hilarious edge cases (I'm looking at you, Ethics paper first, music in close to everyone) that make no sense, and some hilarious edge cases (Waking up, OJ, I feel like Nick Jonas today) that make me feel like I should have a Twitter rap career. On the whole though, the structure came out alright. ","version":null,"tagName":"h2"},{"title":"Moving on from here​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#moving-on-from-here","content":" During class we also talked about an interesting idea: trying to analyze corporate documents and corporate speech. I'd be interested to know what this analysis applied to something like a couple of bank press releases could do. By any means, the code needs some work to clean it up before I get that far. ","version":null,"tagName":"h2"},{"title":"For further reading​","type":1,"pageTitle":"Tweet like me","url":"/2016/03/tweet-like-me#for-further-reading","content":" I'm pretty confident I re-invented a couple wheels along the way - what I'm doing feels a lot like what Markov Chain Monte Carlo is intended to do. But I've never worked explicitly with that before, so more research is needed. ","version":null,"tagName":"h2"},{"title":"Tick tock...","type":0,"sectionRef":"#","url":"/2016/04/tick-tock","content":"","keywords":"","version":null},{"title":"2.5 Billion​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#25-billion","content":" If PBS is right, that's the total number of heartbeats we get. Approximately once every second that number goes down, and down, and down again... total_heartbeats = 2500000000 I got a Fitbit this past Christmas season, mostly because I was interested in the data and trying to work on some data science projects with it. This is going to be the first project, but there will likely be more (and not nearly as morbid). My idea was: If this is the final number that I'm running up against, how far have I come, and how far am I likely to go? I've currently had about 3 months' time to estimate what my data will look like, so let's go ahead and see: given a lifetime 2.5 billion heart beats, how much time do I have left? ","version":null,"tagName":"h2"},{"title":"Statistical Considerations​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#statistical-considerations","content":" Since I'm starting to work with health data, there are a few considerations I think are important before I start digging through my data. The concept of 2.5 billion as an agreed-upon number is tenuous at best. I've seen anywhere from 2.21 billion to 3.4 billion so even if I knew exactly how many times my heart had beaten so far, the ending result is suspect at best. I'm using 2.5 billion because that seems to be about the midpoint of the estimates I've seen so far.Most of the numbers I've seen so far are based on extrapolating number of heart beats from life expectancy. As life expectancy goes up, the number of expected heart beats goes up too.My estimation of the number of heartbeats in my life so far is based on 3 months worth of data, and I'm extrapolating an entire lifetime based on this. So while the ending number is not useful in any medical context, it is still an interesting project to work with the data I have on hand. ","version":null,"tagName":"h2"},{"title":"Getting the data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#getting-the-data","content":" Fitbit has an API available for people to pull their personal data off the system. It requires registering an application, authentication with OAuth, and some other complicated things. If you're not interested in how I fetch the data, skip here. ","version":null,"tagName":"h2"},{"title":"Registering an application​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#registering-an-application","content":" I've already registered a personal application with Fitbit, so I can go ahead and retrieve things like the client secret from a file. # Import all the OAuth secret information from a local file from secrets import CLIENT_SECRET, CLIENT_ID, CALLBACK_URL ","version":null,"tagName":"h2"},{"title":"Handling OAuth 2​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#handling-oauth-2","content":" So, all the people that know what OAuth 2 is know what's coming next. For those who don't: OAuth is how people allow applications to access other data without having to know your password. Essentially the dialog goes like this: Application: I've got a user here who wants to use my application, but I need their data. Fitbit: OK, what data do you need access to, and for how long? Application: I need all of these scopes, and for this amount of time. Fitbit: OK, let me check with the user to make sure they really want to do this. Fitbit: User, do you really want to let this application have your data? User: I do! And to prove it, here's my password. Fitbit: OK, everything checks out. I'll let the application access your data. Fitbit: Application, you can access the user's data. Use this special value whenever you need to request data from me. Application: Thank you, now give me all the data. Effectively, this allows an application to gain access to a user's data without ever needing to know the user's password. That way, even if the other application is hacked, the user's original data remains safe. Plus, the user can let the data service know to stop providing the application access any time they want. All in all, very secure. It does make handling small requests a bit challenging, but I'll go through the steps here. We'll be using the Implicit Grant workflow, as it requires fewer steps in processing. First, we need to set up the URL the user would visit to authenticate: import urllib FITBIT_URI = 'https://www.fitbit.com/oauth2/authorize' params = { # If we need more than one scope, must be a CSV string 'scope': 'heartrate', 'response_type': 'token', 'expires_in': 86400, # 1 day 'redirect_uri': CALLBACK_URL, 'client_id': CLIENT_ID } request_url = FITBIT_URI + '?' + urllib.parse.urlencode(params) Now, here you would print out the request URL, go visit it, and get the full URL that it sends you back to. Because that is very sensitive information (specifically containing my CLIENT_ID that I'd really rather not share on the internet), I've skipped that step in the code here, but it happens in the background. # The `response_url` variable contains the full URL that # FitBit sent back to us, but most importantly, # contains the token we need for authorization. access_token = dict(urllib.parse.parse_qsl(response_url))['access_token'] ","version":null,"tagName":"h3"},{"title":"Requesting the data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#requesting-the-data","content":" Now that we've actually set up our access via the access_token, it's time to get the actual heart rate data. I'll be using data from January 1, 2016 through March 31, 2016, and extrapolating wildly from that. Fitbit only lets us fetch intraday data one day at a time, so I'll create a date range using pandas and iterate through that to pull down all the data. from requests_oauthlib import OAuth2Session import pandas as pd from datetime import datetime session = OAuth2Session(token={ 'access_token': access_token, 'token_type': 'Bearer' }) format_str = '%Y-%m-%d' start_date = datetime(2016, 1, 1) end_date = datetime(2016, 3, 31) dr = pd.date_range(start_date, end_date) url = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json' hr_responses = [session.get(url.format(d.strftime(format_str))) for d in dr] def record_to_df(record): if 'activities-heart' not in record: return None date_str = record['activities-heart'][0]['dateTime'] df = pd.DataFrame(record['activities-heart-intraday']['dataset']) df.index = df['time'].apply( lambda x: datetime.strptime(date_str + ' ' + x, '%Y-%m-%d %H:%M:%S')) return df hr_dataframes = [record_to_df(record.json()) for record in hr_responses] hr_df_concat = pd.concat(hr_dataframes) # There are some minutes with missing data, so we need to correct that full_daterange = pd.date_range(hr_df_concat.index[0], hr_df_concat.index[-1], freq='min') hr_df_full = hr_df_concat.reindex(full_daterange, method='nearest') print("Heartbeats from {} to {}: {}".format(hr_df_full.index[0], hr_df_full.index[-1], hr_df_full['value'].sum())) Heartbeats from 2016-01-01 00:00:00 to 2016-03-31 23:59:00: 8139060 And now we've retrieved all the available heart rate data for January 1st through March 31st! Let's get to the actual analysis. ","version":null,"tagName":"h3"},{"title":"Wild Extrapolations from Small Data​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#wild-extrapolations-from-small-data","content":" A fundamental issue of this data is that it's pretty small. I'm using 3 months of data to make predictions about my entire life. But, purely as an exercise, I'll move forward. ","version":null,"tagName":"h2"},{"title":"How many heartbeats so far?​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#how-many-heartbeats-so-far","content":" The first step is figuring out how many of the 2.5 billion heartbeats I've used so far. We're going to try and work backward from the present day to when I was born to get that number. The easy part comes first: going back to January 1st, 1992. That's because I can generalize how many 3-month increments there were between now and then, account for leap years, and call that section done. Between January 1992 and January 2016 there were 96 quarters, and 6 leap days. The number we're looking for is: hrq⋅n−hrd⋅(n−m)\\begin{equation*} hr_q \\cdot n - hr_d \\cdot (n-m) \\end{equation*}hrq​⋅n−hrd​⋅(n−m)​ hrqhr_qhrq​: Number of heartbeats per quarterhrdhr_dhrd​: Number of heartbeats on leap daynnn: Number of quarters, in this case 96mmm: Number of leap days, in this case 6 quarterly_count = hr_df_full['value'].sum() leap_day_count = hr_df_full[(hr_df_full.index.month == 2) & (hr_df_full.index.day == 29)]['value'].sum() num_quarters = 96 leap_days = 6 jan_92_jan_16 = quarterly_count * num_quarters - leap_day_count * (num_quarters - leap_days) jan_92_jan_16 773609400 So between January 1992 and January 2016 I've used ≈\\approx≈ 774 million heartbeats. Now, I need to go back to my exact birthday. I'm going to first find on average how many heartbeats I use in a minute, and multiply that by the number of minutes between my birthday and January 1992. For privacy purposes I'll put the code here that I'm using, but without any identifying information: minute_mean = hr_df_full['value'].mean() # Don't you wish you knew? # birthday_minutes = ??? birthday_heartbeats = birthday_minutes * minute_mean heartbeats_until_2016 = int(birthday_heartbeats + jan_92_jan_16) remaining_2016 = total_heartbeats - heartbeats_until_2016 print("Heartbeats so far: {}".format(heartbeats_until_2016)) print("Remaining heartbeats: {}".format(remaining_2016)) Heartbeats so far: 775804660 Remaining heartbeats: 1724195340 It would appear that my heart has beaten 775,804,660 times between my moment of birth and January 1st 2016, and that I have 1.72 billion left. ","version":null,"tagName":"h3"},{"title":"How many heartbeats longer?​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#how-many-heartbeats-longer","content":" Now comes the tricky bit. I know how many heart beats I've used so far, and how many I have remaining, so I'd like to come up with a (relatively) accurate estimate of when exactly my heart should give out. We'll do this in a few steps, increasing in granularity. First step, how many heartbeats do I use in a 4-year period? I have data for a single quarter including leap day, so I want to know: hrq⋅n−hrd⋅(n−m)\\begin{equation*} hr_q \\cdot n - hr_d \\cdot (n - m) \\end{equation*}hrq​⋅n−hrd​⋅(n−m)​ hrqhr_qhrq​: Heartbeats per quarterhrdhr_dhrd​: Heartbeats per leap daynnn: Number of quarters = 16mmm: Number of leap days = 1 heartbeats_4year = quarterly_count * 16 - leap_day_count * (16 - 1) heartbeats_4year 128934900 Now, I can fast forward from 2016 the number of periods of 4 years I have left. four_year_periods = remaining_2016 // heartbeats_4year remaining_4y = remaining_2016 - four_year_periods * heartbeats_4year print("Four year periods remaining: {}".format(four_year_periods)) print("Remaining heartbeats after 4 year periods: {}".format(remaining_4y)) Four year periods remaining: 13 Remaining heartbeats after 4 year periods: 48041640 Given that there are 13 four-year periods left, I can move from 2016 all the way to 2068, and find that I will have 48 million heart beats left. Let's drop down to figuring out how many quarters that is. I know that 2068 will have a leap day (unless someone finally decides to get rid of them), so I'll subtract that out first. Then, I'm left to figure out how many quarters exactly are left. remaining_leap = remaining_4y - leap_day_count # Ignore leap day in the data set heartbeats_quarter = hr_df_full[(hr_df_full.index.month != 2) & (hr_df_full.index.day != 29)]['value'].sum() quarters_left = remaining_leap // heartbeats_quarter remaining_year = remaining_leap - quarters_left * heartbeats_quarter print("Quarters left starting 2068: {}".format(quarters_left)) print("Remaining heartbeats after that: {}".format(remaining_year)) Quarters left starting 2068: 8 Remaining heartbeats after that: 4760716 So, that analysis gets me through until January 1st 2070. Final step, using that minute estimate to figure out how many minutes past that I'm predicted to have: from datetime import timedelta base = datetime(2070, 1, 1) minutes_left = remaining_year // minute_mean kaput = timedelta(minutes=minutes_left) base + kaput datetime.datetime(2070, 2, 23, 5, 28) According to this, I've got until February 23rd, 2070 at 5:28 PM in the evening before my heart gives out. ","version":null,"tagName":"h3"},{"title":"Summary​","type":1,"pageTitle":"Tick tock...","url":"/2016/04/tick-tock#summary","content":" Well, that's kind of a creepy date to know. As I said at the top though, this number is totally useless in any medical context. It ignores the rate at which we continue to get better at making people live longer, and is extrapolating from 3 months' worth of data the rest of my life. Additionally, throughout my time developing this post I made many minor mistakes. I think they're all fixed now, but it's easy to mix a number up here or there and the analysis gets thrown off by a couple years. Even still, I think philosophically humans have a desire to know how much time we have left in the world. Man is but a breath, and it's scary to think just how quickly that date may be coming up. This analysis asks an important question though: what are you going to do with the time you have left? Thanks for sticking with me on this one, I promise it will be much less depressing next time! ","version":null,"tagName":"h2"},{"title":"The unfair casino","type":0,"sectionRef":"#","url":"/2016/05/the-unfair-casino","content":"","keywords":"","version":null},{"title":"Proving we can detect cheating​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#proving-we-can-detect-cheating","content":" My first question is simply, is this possible? There's a lot of trivial cases that make it obvious that there's cheating going on. But there are some edge cases that might give us more difficulty. First though, let's get a picture of what the fair distribution looks like. In principle, we can only detect cheating if the distribution of the fair die differs from the distribution of the loaded die. import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline fair_1 = np.random.randint(1, 7, 10000) fair_2 = np.random.randint(1, 7, 10000) pd.Series(fair_1 + fair_2).plot(kind='hist', bins=11); plt.title('Fair Distribution'); This distribution makes sense: there are many ways to make a 7 (the most frequent observed value) and very few ways to make a 12 or 2; an important symmetry. As a special note, you can notice that the sum of two fair dice is a discrete case of the Triangle Distribution, which is itself a special case of the Irwin-Hall Distribution. ","version":null,"tagName":"h2"},{"title":"The Edge Cases​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-edge-cases","content":" Given that we understand how the results of two fair dice are distributed, let's see some of the interesting edge cases that come up. This will give us assurance that when a casino is cheating, it is detectable (given sufficient data). To make this as hard as possible, we will think of scenarios where the expected value of the sum of loaded dice is the same as the expected value of the sum of fair dice. ","version":null,"tagName":"h2"},{"title":"Edge Case 1​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#edge-case-1","content":" What happens when one die is biased low, and one die is biased high? That is, where: D1={1w.p.1/32w.p.1/33w.p.1/124w.p.1/125w.p.1/126w.p.1/12D2={1w.p.1/122w.p.1/123w.p.1/124w.p.1/125w.p.1/36w.p.1/3E[D1]=2.5E[D2]=4.5E[D1+D2]=7=E[Dfair+Dfair]\\begin{align*} \\begin{array}{cc} D_1 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/3\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/12 \\end{array} \\right. & D_2 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/12\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/3\\\\ 6 & w.p. 1/3 \\end{array} \\right. \\\\ \\mathbb{E}[D_1] = 2.5 & \\mathbb{E}[D_2] = 4.5 \\end{array}\\\\ \\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}] \\end{align*}D1​=⎩⎨⎧​123456​w.p.1/3w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12​E[D1​]=2.5​D2​=⎩⎨⎧​123456​w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3w.p.1/3​E[D2​]=4.5​E[D1​+D2​]=7=E[Dfair​+Dfair​]​ def unfair_die(p_vals, n): x = np.random.multinomial(1, p_vals, n) return x.nonzero()[1] + 1 d1 = [1/3, 1/3, 1/12, 1/12, 1/12, 1/12] d2 = [1/12, 1/12, 1/12, 1/12, 1/3, 1/3] x1 = unfair_die(d1, 10000) x2 = unfair_die(d2, 10000) pd.Series(x1 + x2).plot(kind='hist', bins=11); plt.title('$D_1$ biased low, $D_2$ biased high'); We can see that while the 7 value remains the most likely (as expected), the distribution is not so nicely shaped any more. ","version":null,"tagName":"h3"},{"title":"Edge Case 2​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#edge-case-2","content":" When one die is loaded low, and one is loaded high, we've seen how we can detect them. How about when two die are loaded both low and high? That is, we have the following distribution: D1={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3D2={1w.p.1/32w.p.1/123w.p.1/124w.p.1/125w.p.1/126w.p.1/3E[D1]=3.5E[D2]=3.5E[D1+D2]=7=E[Dfair+Dfair]\\begin{align*} \\begin{array}{cc} D_1 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/3 \\end{array} \\right. & D_2 = \\left\\{ \\begin{array}{lr} 1 & w.p. 1/3\\\\ 2 & w.p. 1/12\\\\ 3 & w.p. 1/12\\\\ 4 & w.p. 1/12\\\\ 5 & w.p. 1/12\\\\ 6 & w.p. 1/3 \\end{array} \\right. \\\\ \\mathbb{E}[D_1] = 3.5 & \\mathbb{E}[D_2] = 3.5 \\end{array}\\\\ \\mathbb{E}[D_1 + D_2] = 7 = \\mathbb{E}[D_{fair} + D_{fair}] \\end{align*}D1​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​E[D1​]=3.5​D2​=⎩⎨⎧​123456​w.p.1/3w.p.1/12w.p.1/12w.p.1/12w.p.1/12w.p.1/3​E[D2​]=3.5​E[D1​+D2​]=7=E[Dfair​+Dfair​]​ We can see even that the expected value of each individual die is the same as the fair die! However, the distribution (if we are doing this correctly) should still be skewed: d1 = [1/3, 1/12, 1/12, 1/12, 1/12, 1/3] d2 = d1 x1 = unfair_die(d1, 10000) x2 = unfair_die(d2, 10000) pd.Series(x1 + x2).plot(kind='hist', bins=11) plt.title("$D_1$ and $D_2$ biased to 1 and 6"); In a very un-subtle way, we have of course made the values 2 and 12 far more likely. ","version":null,"tagName":"h3"},{"title":"Detection Conclusion​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#detection-conclusion","content":" There are some trivial examples of cheating that are easy to detect: whenever the expected value of the sum of two fair dice deviates from the expected value for the sum of two fair dice, we can immediately conclude that there is cheating at stake. The interesting edge cases occur when the expected value of the sum of loaded dice matches the expected value of the sum of fair dice. Considering the above examples (and a couple more I ran through in developing this), we have seen that in every circumstance having two unfair dice leads to a distribution of results different from the fair results. We can thus finally state: just by looking at the distribution of results from this game, we can immediately conclude whether there is cheating. ","version":null,"tagName":"h2"},{"title":"Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#simulated-annealing","content":" What we really would like to do though, is see if there is any way to determine how exactly the dice are loaded. This is significantly more complicated, but we can borrow some algorithms from Machine Learning to figure out exactly how to perform this process. I'm using the Simulated Annealing algorithm, and I discuss why this works and why I chose it over some of the alternatives in the justification. If you don't care about how I set up the model and just want to see the code, check out the actual code. Simulated Annealing is a variation of the Metropolis-Hastings Algorithm, but the important thing for us is: Simulated Annealing allows us to quickly optimize high-dimensional problems. But what exactly are we trying to optimize? Ideally, we want a function that can tell us whether one distribution for the dice better explains the results than another distribution. This is known as the likelihood function. ","version":null,"tagName":"h2"},{"title":"Deriving the Likelihood function​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#deriving-the-likelihood-function","content":" To derive our likelihood function, we want to know: what is the probability of seeing a specific result given those hidden parameters? This is actually a surprisingly difficult problem. While we can do a lot of calculations by hand, we need a more general solution since we will be working with very some interesting die distributions. We first note that the sum of two dice can take on 11 different values - 2 through 12. This implies that each individual sum follows a Categorical distribution. That is: L(x)={p2x=2p3x=3…p11x=11p12x=12\\begin{align*} \\mathcal{L(x)} = \\left\\{ \\begin{array}{lr} p_2 & x = 2\\\\ p_3 & x = 3\\\\ \\ldots & \\\\ p_{11} & x = 11\\\\ p_{12} & x = 12 \\end{array} \\right. \\end{align*}L(x)=⎩⎨⎧​p2​p3​…p11​p12​​x=2x=3x=11x=12​​ Where each pip_ipi​ is the probability of seeing that specific result. However, we need to calculate what each probability is! I'll save you the details, but this author explains how to do it. Now, we would like to know the likelihood of our entire data-set. This is trivial: L(X)=∏i=1nL(x)\\begin{align*} \\mathcal{L(\\mathbf{X})} &= \\prod_{i=1}^n L(x) \\end{align*}L(X)​=i=1∏n​L(x)​ However, it's typically much easier to work with the log⁡(L)\\log(\\mathcal{L})log(L) function instead. This is critically important from a computational perspective: when you multiply so many small numbers together (i.e. the product of L(x)L(x)L(x) terms) the computer suffers from rounding error; if we don't control for this, we will find that no matter the distributions we choose for each die, the "likelihood" will be close to zero because the computer is not precise enough. log⁡(L)=∑i=1nlog⁡(L)\\begin{align*} \\log(\\mathcal{L}) &= \\sum_{i=1}^n \\log(L) \\end{align*}log(L)​=i=1∑n​log(L)​ ","version":null,"tagName":"h3"},{"title":"The process of Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-process-of-simulated-annealing","content":" The means by which we optimize our likelihood function is the simulated annealing algorithm. The way it works is as follows: Start with a random guess for the parameters we are trying to optimize. In our case we are trying to guess the distribution of two dice, and so we "optimize" until we have a distribution that matches the data. For each iteration of the algorithm: Generate a new "proposed" set of parameters based on the current parameters - i.e. slightly modify the current parameters to get a new set of parameters.Calculate the value of log⁡(L)\\log(\\mathcal{L})log(L) for each set of parameters. If the function value for the proposed parameter set is higher than for the current, automatically switch to the new parameter set and continue the next iteration.Given the new parameter set performs worse, determine a probability of switching to the new parameter set anyways: P(pcurrent,pproposed)\\mathcal{P}(p_{current}, p_{proposed})P(pcurrent​,pproposed​)Switch to the new parameter set with probability P\\mathcal{P}P. If you fail to switch, begin the next iteration. The algorithm is complete after we fail to make a transition nnn times in a row. If everything goes according to plan, we will have a value that is close to the true distribution of each die. ","version":null,"tagName":"h3"},{"title":"The actual code​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#the-actual-code","content":" We start by defining the score function. This will tell us how well the proposed die densities actually explain the results. import numpy as np from numpy import polynomial def density_coef(d1_density, d2_density): # Calculating the probabilities of each outcome was taken # from this author: http://math.stackexchange.com/a/1710392/320784 d1_p = polynomial.Polynomial(d1_density) d2_p = polynomial.Polynomial(d2_density) coefs = (d1_p * d2_p).coef return coefs def score(x, d1_density, d2_density): # We've now got the probabilities of each event, but we need # to shift the array a bit so we can use the x values to actually # index into it. This will allow us to do all the calculations # incredibly quickly coefs = density_coef(d1_density, d2_density) coefs = np.hstack((0, 0, coefs)) return np.log(coefs[x]).sum() Afterward, we need to write something to permute the proposal densities. We make random modifications, and eventually the best one survives. def permute(d1_density, d2_density): # To ensure we have legitimate densities, we will randomly # increase one die face probability by `change`, # and decrease one by `change`. # This means there are something less than (1/`change`)^12 possibilities # we are trying to search over. change = .01 d1_index1, d1_index2 = np.random.randint(0, 6, 2) d2_index1, d2_index2 = np.random.randint(0, 6, 2) # Also make sure to copy. I've had some weird aliasing issues # in the past that made everything blow up. new_d1 = np.float64(np.copy(d1_density)) new_d2 = np.float64(np.copy(d2_density)) # While this doesn't account for the possibility that some # values go negative, in practice this never happens new_d1[d1_index1] += change new_d1[d1_index2] -= change new_d2[d2_index1] += change new_d2[d2_index2] -= change return new_d1, new_d2 Now we've got the main algorithm code to do. This is what brings all the pieces together. def optimize(data, conv_count=10, max_iter=1e4): switch_failures = 0 iter_count = 0 # Start with guessing fair dice cur_d1 = np.repeat(1/6, 6) cur_d2 = np.repeat(1/6, 6) cur_score = score(data, cur_d1, cur_d2) # Keep track of our best guesses - may not be # what we end with max_score = cur_score max_d1 = cur_d1 max_d2 = cur_d2 # Optimization stops when we have failed to switch `conv_count` # times (presumably because we have a great guess), or we reach # the maximum number of iterations. while switch_failures < conv_count and iter_count < max_iter: iter_count += 1 if iter_count % (max_iter / 10) == 0: print('Iteration: {}; Current score (higher is better): {}'.format( iter_count, cur_score)) new_d1, new_d2 = permute(cur_d1, cur_d2) new_score = score(data, new_d1, new_d2) if new_score > max_score: max_score = new_score max_d1 = new_d1 max_d2 = new_d2 if new_score > cur_score: # If the new permutation beats the old one, # automatically select it. cur_score = new_score cur_d1 = new_d1 cur_d2 = new_d2 switch_failures = 0 else: # We didn't beat the current score, but allow # for possibly switching anyways. accept_prob = np.exp(new_score - cur_score) coin_toss = np.random.rand() if coin_toss < accept_prob: # We randomly switch to the new distribution cur_score = new_score cur_d1 = new_d1 cur_d2 = new_d2 switch_failures = 0 else: switch_failures += 1 # Return both our best guess, and the ending guess return max_d1, max_d2, cur_d1, cur_d2 And now we have finished the hard work! ","version":null,"tagName":"h2"},{"title":"Catching the Casino​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#catching-the-casino","content":" Let's go through a couple of scenarios and see if we can catch the casino cheating with some loaded dice. In every scenario we start with an assumption of fair dice, and then try our hand to figure out what the actual distribution was. ","version":null,"tagName":"h2"},{"title":"Attempt 1​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-1","content":" The casino is using two dice that are both biased low. How well can we recover the distribution? import time def simulate_casino(d1_dist, d2_dist, n=10000): d1_vals = unfair_die(d1_dist, n) d2_vals = unfair_die(d2_dist, n) start = time.perf_counter() max_d1, max_d2, final_d1, final_d2 = optimize(d1_vals + d2_vals) end = time.perf_counter() print("Simulated Annealing time: {:.02f}s".format(end - start)) coef_range = np.arange(2, 13) - .5 plt.subplot(221) plt.bar(coef_range, density_coef(d1_dist, d2_dist), width=1) plt.title('True Distribution') plt.subplot(222) plt.hist(d1_vals + d2_vals, bins=11) plt.title('Empirical Distribution') plt.subplot(223) plt.bar(coef_range, density_coef(max_d1, max_d2), width=1) plt.title('Recovered Distribution') plt.gcf().set_size_inches(10, 10) simulate_casino([2/9, 2/9, 2/9, 1/9, 1/9, 1/9], [2/9, 2/9, 2/9, 1/9, 1/9, 1/9]) Iteration: 1000; Current score (higher is better): -22147.004400281654 Simulated Annealing time: 0.30s ","version":null,"tagName":"h3"},{"title":"Attempt 2​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-2","content":" The casino now uses dice that are both biased towards 1 and 6. simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3], [1/3, 1/12, 1/12, 1/12, 1/12, 1/3]) Simulated Annealing time: 0.08s ","version":null,"tagName":"h3"},{"title":"Attempt 3​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-3","content":" The casino will now use one die biased towards 1 and 6, and one die towards 3 and 4. simulate_casino([1/3, 1/12, 1/12, 1/12, 1/12, 1/3], [1/12, 1/12, 1/3, 1/3, 1/12, 1/12]) Simulated Annealing time: 0.09s ","version":null,"tagName":"h3"},{"title":"Attempt 4​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-4","content":" We'll now finally go to a fair casino to make sure that we can still recognize a positive result. simulate_casino(np.repeat(1/6, 6), np.repeat(1/6, 6)) Simulated Annealing time: 0.02s ","version":null,"tagName":"h3"},{"title":"Attempt 5​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#attempt-5","content":" We've so far been working with a large amount of data - 10,000 data points. Can we now scale things back to only 250 throws? We'll start with two dice biased high. simulate_casino([1/9, 1/9, 1/9, 2/9, 2/9, 2/9], [1/9, 1/9, 1/9, 2/9, 2/9, 2/9], n=250) Iteration: 1000; Current score (higher is better): -551.6995384525453 Iteration: 2000; Current score (higher is better): -547.7803673440676 Iteration: 3000; Current score (higher is better): -547.9805613193807 Iteration: 4000; Current score (higher is better): -546.7574874775273 Iteration: 5000; Current score (higher is better): -549.5798007672656 Iteration: 6000; Current score (higher is better): -545.0354060154496 Iteration: 7000; Current score (higher is better): -550.1134504086606 Iteration: 8000; Current score (higher is better): -549.9306537114975 Iteration: 9000; Current score (higher is better): -550.7075182119111 Iteration: 10000; Current score (higher is better): -549.400679551826 Simulated Annealing time: 1.94s The results are surprisingly good. While the actual optimization process took much longer to finish than in the other examples, we still have a very good guess. As a caveat though: the recovered distribution tends to overfit the data. That is, if the data doesn't fit the underlying distribution well, the model will also fail. ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#conclusion","content":" Given the results above, we can see that we have indeed come up with a very good algorithm to determine the distribution of two dice given their results. As a benefit, we have even seen that results come back very quickly; it's not uncommon for the optimization to converge within a tenth of a second. Additionally, we have seen that the algorithm can intuit the distribution even when there is not much data. While the final example shows that we can 'overfit' on the dataset, we can still get valuable information from a relatively small dataset. We can declare at long last: the mathematicians have again triumphed over the casino. ","version":null,"tagName":"h2"},{"title":"Justification of Simulated Annealing​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#justification-of-simulated-annealing","content":" ","version":null,"tagName":"h2"},{"title":"Why Simulated Annealing?​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#why-simulated-annealing","content":" So why even use an algorithm with a fancy title like Simulated Annealing? First of all, because the title is sexy. Second of all, because this is a reasonably complicated problem to try and solve. We have a parameter space where each value pij∈(0,1);i,j∈{1,…,6}p_{ij} \\in (0, 1); i, j \\in \\{1, \\ldots, 6\\}pij​∈(0,1);i,j∈{1,…,6}, for a total of 12 different variables we are trying to optimize over. Additionally, given a 12-dimensional function we are trying to optimize, simulated annealing makes sure that we don't fall into a local minimum. ","version":null,"tagName":"h3"},{"title":"Why not something else?​","type":1,"pageTitle":"The unfair casino","url":"/2016/05/the-unfair-casino#why-not-something-else","content":" This is a fair question. There are two classes of algorithms that can also be used to solve this problem: Non-linear optimization methods, and the EM algorithm. I chose not to use non-linear optimization simply because I'm a bit concerned that it will trap me in a local maximum. Instead of running multiple different optimizations from different starting points, I can just use simulated annealing to take that into account. In addition, throughout the course of testing the simulated annealing code converged incredibly quickly - far more quickly than any non-linear solver would be able to accomplish. The EM Algorithm was originally what I intended to write this blog post with. Indeed, the post was inspired by the crooked casino example which uses the EM algorithm to solve it. However, after modeling the likelihood function I realized that the algebra would very quickly get out of hand. Trying to compute all the polynomial terms would not be fun, which would be needed to actually optimize for each parameter. So while the EM algorithm would likely be much faster in raw speed terms, the amount of time needed to program and verify it meant that I was far better off using a different method for optimization. ","version":null,"tagName":"h3"},{"title":"Event studies and earnings releases","type":0,"sectionRef":"#","url":"/2016/06/event-studies-and-earnings-releases","content":"","keywords":"","version":null},{"title":"The Market Just Knew​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#the-market-just-knew","content":" I recently saw two examples of stock charts that have kept me thinking for a while. And now that the semester is complete, I finally have enough time to really look at them and give them the treatment they deserve. The first is good old Apple: Code from secrets import QUANDL_KEY import matplotlib.pyplot as plt from matplotlib.dates import date2num from matplotlib.finance import candlestick_ohlc from matplotlib.dates import DateFormatter, WeekdayLocator,\\ DayLocator, MONDAY import quandl from datetime import datetime import pandas as pd %matplotlib inline def fetch_ticker(ticker, start, end): # Quandl is currently giving me issues with returning # the entire dataset and not slicing server-side. # So instead, we'll do it client-side! q_format = '%Y-%m-%d' ticker_data = quandl.get('YAHOO/' + ticker, start_date=start.strftime(q_format), end_date=end.strftime(q_format), authtoken=QUANDL_KEY) return ticker_data def ohlc_dataframe(data, ax=None): # Much of this code re-used from: # http://matplotlib.org/examples/pylab_examples/finance_demo.html if ax is None: f, ax = plt.subplots() vals = [(date2num(date), *(data.loc[date])) for date in data.index] candlestick_ohlc(ax, vals) mondays = WeekdayLocator(MONDAY) alldays = DayLocator() weekFormatter = DateFormatter('%b %d') ax.xaxis.set_major_locator(mondays) ax.xaxis.set_minor_locator(alldays) ax.xaxis.set_major_formatter(weekFormatter) return ax AAPL = fetch_ticker('AAPL', datetime(2016, 3, 1), datetime(2016, 5, 1)) ax = ohlc_dataframe(AAPL) plt.vlines(date2num(datetime(2016, 4, 26, 12)), ax.get_ylim()[0], ax.get_ylim()[1], color='b', label='Earnings Release') plt.legend(loc=3) plt.title("Apple Price 3/1/2016 - 5/1/2016"); The second chart is from Facebook: FB = fetch_ticker('FB', datetime(2016, 3, 1), datetime(2016, 5, 5)) ax = ohlc_dataframe(FB) plt.vlines(date2num(datetime(2016, 4, 27, 12)), ax.get_ylim()[0], ax.get_ylim()[1], color='b', label='Earnings Release') plt.title('Facebook Price 3/5/2016 - 5/5/2016') plt.legend(loc=2); These two charts demonstrate two very specific phonomena: how the market prepares for earnings releases. Let's look at those charts again, but with some extra information. As we're about the see, the market "knew" in advance that Apple was going to perform poorly. The market expected that Facebook was going to perform poorly, and instead shot the lights out. Let's see that trend in action: Code def plot_hilo(ax, start, end, data): ax.plot([date2num(start), date2num(end)], [data.loc[start]['High'], data.loc[end]['High']], color='b') ax.plot([date2num(start), date2num(end)], [data.loc[start]['Low'], data.loc[end]['Low']], color='b') f, axarr = plt.subplots(1, 2) ax_aapl = axarr[0] ax_fb = axarr[1] # Plot the AAPL trend up and down ohlc_dataframe(AAPL, ax=ax_aapl) plot_hilo(ax_aapl, datetime(2016, 3, 1), datetime(2016, 4, 15), AAPL) plot_hilo(ax_aapl, datetime(2016, 4, 18), datetime(2016, 4, 26), AAPL) ax_aapl.vlines(date2num(datetime(2016, 4, 26, 12)), ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1], color='g', label='Earnings Release') ax_aapl.legend(loc=2) ax_aapl.set_title('AAPL Price History') # Plot the FB trend down and up ohlc_dataframe(FB, ax=ax_fb) plot_hilo(ax_fb, datetime(2016, 3, 30), datetime(2016, 4, 27), FB) plot_hilo(ax_fb, datetime(2016, 4, 28), datetime(2016, 5, 5), FB) ax_fb.vlines(date2num(datetime(2016, 4, 27, 12)), ax_fb.get_ylim()[0], ax_fb.get_ylim()[1], color='g', label='Earnings Release') ax_fb.legend(loc=2) ax_fb.set_title('FB Price History') f.set_size_inches(18, 6) As we can see above, the market broke a prevailing trend on Apple in order to go down, and ultimately predict the earnings release. For Facebook, the opposite happened. While the trend was down, the earnings were fantastic and the market corrected itself much higher. ","version":null,"tagName":"h2"},{"title":"Formulating the Question​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#formulating-the-question","content":" While these are two specific examples, there are plenty of other examples you could cite one way or another. Even if the preponderance of evidence shows that the market correctly predicts earnings releases, we need not accuse people of collusion; for a company like Apple with many suppliers we can generally forecast how Apple has done based on those same suppliers. The question then, is this: how well does the market predict the earnings releases? It's an incredibly broad question that I want to disect in a couple of different ways: Given a stock that has been trending down over the past N days before an earnings release, how likely does it continue downward after the release?Given a stock trending up, how likely does it continue up?Is there a difference in accuracy between large- and small-cap stocks?How often, and for how long, do markets trend before an earnings release? I want to especially thank Alejandro Saltiel for helping me retrieve the data. He's great. And now for all of the interesting bits. ","version":null,"tagName":"h2"},{"title":"Event Studies​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-studies","content":" Before we go too much further, I want to introduce the actual event study. Each chart intends to capture a lot of information and present an easy-to-understand pattern: Code import numpy as np import pandas as pd from pandas.tseries.holiday import USFederalHolidayCalendar from pandas.tseries.offsets import CustomBusinessDay from datetime import datetime, timedelta # If you remove rules, it removes them from *all* calendars # To ensure we don't pop rules we don't want to, first make # sure to fully copy the object trade_calendar = USFederalHolidayCalendar() trade_calendar.rules.pop(6) # Remove Columbus day trade_calendar.rules.pop(7) # Remove Veteran's day TradeDay = lambda days: CustomBusinessDay(days, calendar=trade_calendar) def plot_study(array): # Given a 2-d array, we assume the event happens at index `lookback`, # and create all of our summary statistics from there. lookback = int((array.shape[1] - 1) / 2) norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1) centered_data = array / norm_factor - 1 lookforward = centered_data.shape[1] - lookback means = centered_data.mean(axis=0) lookforward_data = centered_data[:,lookforward:] std_dev = np.hstack([0, lookforward_data.std(axis=0)]) maxes = lookforward_data.max(axis=0) mins = lookforward_data.min(axis=0) f, axarr = plt.subplots(1, 2) range_begin = -lookback range_end = lookforward axarr[0].plot(range(range_begin, range_end), means) axarr[1].plot(range(range_begin, range_end), means) axarr[0].fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") axarr[1].fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") max_err = maxes - means[-lookforward+1:] min_err = means[-lookforward+1:] - mins axarr[0].errorbar(range(1, range_end), means[-lookforward+1:], yerr=[min_err, max_err], label='Max & Min') axarr[0].legend(loc=2) axarr[1].legend(loc=2) axarr[0].set_xlim((-lookback-1, lookback+1)) axarr[1].set_xlim((-lookback-1, lookback+1)) def plot_study_small(array): # Given a 2-d array, we assume the event happens at index `lookback`, # and create all of our summary statistics from there. lookback = int((array.shape[1] - 1) / 2) norm_factor = np.repeat(array[:,lookback].reshape(-1, 1), array.shape[1], axis=1) centered_data = array / norm_factor - 1 lookforward = centered_data.shape[1] - lookback means = centered_data.mean(axis=0) lookforward_data = centered_data[:,lookforward:] std_dev = np.hstack([0, lookforward_data.std(axis=0)]) maxes = lookforward_data.max(axis=0) mins = lookforward_data.min(axis=0) range_begin = -lookback range_end = lookforward plt.plot(range(range_begin, range_end), means) plt.fill_between(range(0, range_end), means[-lookforward:] + std_dev, means[-lookforward:] - std_dev, alpha=.5, label="$\\pm$ 1 s.d.") max_err = maxes - means[-lookforward+1:] min_err = means[-lookforward+1:] - mins plt.errorbar(range(1, range_end), means[-lookforward+1:], yerr=[min_err, max_err], label='Max & Min') plt.legend(loc=2) plt.xlim((-lookback-1, lookback+1)) def fetch_event_data(ticker, events, horizon=5): # Use horizon+1 to account for including the day of the event, # and half-open interval - that is, for a horizon of 5, # we should be including 11 events. Additionally, using the # CustomBusinessDay means we automatically handle issues if # for example a company reports Friday afternoon - the date # calculator will turn this into a "Saturday" release, but # we effectively shift that to Monday with the logic below. td_back = TradeDay(horizon+1) td_forward = TradeDay(horizon+1) start_date = min(events) - td_back end_date = max(events) + td_forward total_data = fetch_ticker(ticker, start_date, end_date) event_data = [total_data.ix[event-td_back:event+td_forward]\\ [0:horizon*2+1]\\ ['Adjusted Close'] for event in events] return np.array(event_data) # Generate a couple of random events event_dates = [datetime(2016, 5, 27) - timedelta(days=1) - TradeDay(x*20) for x in range(1, 40)] data = fetch_event_data('CELG', event_dates) plot_study_small(data) plt.legend(loc=3) plt.gcf().set_size_inches(12, 6); plt.annotate('Mean price for days leading up to each event', (-5, -.01), (-4.5, .025), arrowprops=dict(facecolor='black', shrink=0.05)) plt.annotate('', (-.1, .005), (-.5, .02), arrowprops={'facecolor': 'black', 'shrink': .05}) plt.annotate('$\\pm$ 1 std. dev. each day', (5, .055), (2.5, .085), arrowprops={'facecolor': 'black', 'shrink': .05}) plt.annotate('Min/Max each day', (.9, -.07), (-1, -.1), arrowprops={'facecolor': 'black', 'shrink': .05}); And as a quick textual explanation as well: The blue line represents the mean price for each day, represented as a percentage of the price on the '0-day'. For example, if we defined an 'event' as whenever the stock price dropped for three days, we would see a decreasing blue line to the left of the 0-day.The blue shaded area represents one standard deviation above and below the mean price for each day following an event. This is intended to give us an idea of what the stock price does in general following an event.The green bars are the minimum and maximum price for each day following an event. This instructs us as to how much it's possible for the stock to move. ","version":null,"tagName":"h2"},{"title":"Event Type 1: Trending down over the past N days​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-type-1-trending-down-over-the-past-n-days","content":" The first type of event I want to study is how stocks perform when they've been trending down over the past couple of days prior to a release. However, we need to clarify what exactly is meant by "trending down." To do so, we'll use the following metric: the midpoint between each day's opening and closing price goes down over a period of N days. It's probably helpful to have an example: Code f, axarr = plt.subplots(1, 2) f.set_size_inches(18, 6) FB_plot = axarr[0] ohlc_dataframe(FB[datetime(2016, 4, 18):], FB_plot) FB_truncated = FB[datetime(2016, 4, 18):datetime(2016, 4, 27)] midpoint = FB_truncated['Open']/2 + FB_truncated['Close']/2 FB_plot.plot(FB_truncated.index, midpoint, label='Midpoint') FB_plot.vlines(date2num(datetime(2016, 4, 27, 12)), ax_fb.get_ylim()[0], ax_fb.get_ylim()[1], color='g', label='Earnings Release') FB_plot.legend(loc=2) FB_plot.set_title('FB Midpoint Plot') AAPL_plot = axarr[1] ohlc_dataframe(AAPL[datetime(2016, 4, 10):], AAPL_plot) AAPL_truncated = AAPL[datetime(2016, 4, 10):datetime(2016, 4, 26)] midpoint = AAPL_truncated['Open']/2 + AAPL_truncated['Close']/2 AAPL_plot.plot(AAPL_truncated.index, midpoint, label='Midpoint') AAPL_plot.vlines(date2num(datetime(2016, 4, 26, 12)), ax_aapl.get_ylim()[0], ax_aapl.get_ylim()[1], color='g', label='Earnings Release') AAPL_plot.legend(loc=3) AAPL_plot.set_title('AAPL Midpoint Plot'); Given these charts, we can see that FB was trending down for the four days preceding the earnings release, and AAPL was trending down for a whopping 8 days (we don't count the peak day). This will define the methodology that we will use for the study. So what are the results? For a given horizon, how well does the market actually perform? Code # Read in the events for each stock; # The file was created using the first code block in the Appendix import yaml from dateutil.parser import parse from progressbar import ProgressBar data_str = open('earnings_dates.yaml', 'r').read() # Need to remove invalid lines filtered = filter(lambda x: '{' not in x, data_str.split('\\n')) earnings_data = yaml.load('\\n'.join(filtered)) # Convert our earnings data into a list of (ticker, date) pairs # to make it easy to work with. # This is horribly inefficient, but should get us what we need ticker_dates = [] for ticker, date_list in earnings_data.items(): for iso_str in date_list: ticker_dates.append((ticker, parse(iso_str))) def does_trend_down(ticker, event, horizon): # Figure out if the `event` has a downtrend for # the `horizon` days preceding it # As an interpretation note: it is assumed that # the closing price of day `event` is the reference # point, and we want `horizon` days before that. # The price_data.hdf was created in the second appendix code block try: ticker_data = pd.read_hdf('price_data.hdf', ticker) data = ticker_data[event-TradeDay(horizon):event] midpoints = data['Open']/2 + data['Close']/2 # Shift dates one forward into the future and subtract # Effectively: do we trend down over all days? elems = midpoints - midpoints.shift(1) return len(elems)-1 == len(elems.dropna()[elems <= 0]) except KeyError: # If the stock doesn't exist, it doesn't qualify as trending down # Mostly this is here to make sure the entire analysis doesn't # blow up if there were issues in data retrieval return False def study_trend(horizon, trend_function): five_day_events = np.zeros((1, horizon*2 + 1)) invalid_events = [] for ticker, event in ProgressBar()(ticker_dates): if trend_function(ticker, event, horizon): ticker_data = pd.read_hdf('price_data.hdf', ticker) event_data = ticker_data[event-TradeDay(horizon):event+TradeDay(horizon)]['Close'] try: five_day_events = np.vstack([five_day_events, event_data]) except ValueError: # Sometimes we don't get exactly the right number of values due to calendar # issues. I've fixed most everything I can, and the few issues that are left # I assume don't systemically bias the results (i.e. data could be missing # because it doesn't exist, etc.). After running through, ~1% of events get # discarded this way invalid_events.append((ticker, event)) # Remove our initial zero row five_day_events = five_day_events[1:,:] plot_study(five_day_events) plt.gcf().suptitle('Action over {} days: {} events' .format(horizon,five_day_events.shape[0])) plt.gcf().set_size_inches(18, 6) # Start with a 5 day study study_trend(5, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:21:38 Time: 0:21:38 When a stock has been trending down for 5 days, once the earnings are announced it really doesn't move on average. However, the variability is incredible. This implies two important things: The market is just as often wrong about an earnings announcement before it happens as it is correctThe incredible width of the min/max bars and standard deviation area tell us that the market reacts violently after the earnings are released. Let's repeat the same study, but over a time horizon of 8 days and 3 days. Presumably if a stock has been going down for 8 days at a time before the earnings, the market should be more accurate. Code # 8 day study next study_trend(8, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:29 Time: 0:20:29 However, looking only at stocks that trended down for 8 days prior to a release, the same pattern emerges: on average, the stock doesn't move, but the market reaction is often incredibly violent. Code # 3 day study after that study_trend(3, does_trend_down) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:26 Time: 0:26:26 Finally, when we look at a 3-day horizon, we start getting some incredible outliers. Stocks have a potential to move over ~300% up, and the standard deviation width is again, incredible. The results for a 3-day horizon follow the same pattern we've seen in the 5- and 8-day horizons. ","version":null,"tagName":"h2"},{"title":"Event Type 2: Trending up for N days​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#event-type-2-trending-up-for-n-days","content":" We're now going to repeat the analysis, but do it for uptrends instead. That is, instead of looking at stocks that have been trending down over the past number of days, we focus only on stocks that have been trending up. Code def does_trend_up(ticker, event, horizon): # Figure out if the `event` has an uptrend for # the `horizon` days preceding it # As an interpretation note: it is assumed that # the closing price of day `event` is the reference # point, and we want `horizon` days before that. # The price_data.hdf was created in the second appendix code block try: ticker_data = pd.read_hdf('price_data.hdf', ticker) data = ticker_data[event-TradeDay(horizon):event] midpoints = data['Open']/2 + data['Close']/2 # Shift dates one forward into the future and subtract # Effectively: do we trend down over all days? elems = midpoints - midpoints.shift(1) return len(elems)-1 == len(elems.dropna()[elems >= 0]) except KeyError: # If the stock doesn't exist, it doesn't qualify as trending down # Mostly this is here to make sure the entire analysis doesn't # blow up if there were issues in data retrieval return False study_trend(5, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:22:51 Time: 0:22:51 The patterns here are very similar. With the exception of noting that stocks can go to nearly 400% after an earnings announcement (most likely this included a takeover announcement, etc.), we still see large min/max bars and wide standard deviation of returns. We'll repeat the pattern for stocks going up for both 8 and 3 days straight, but at this point, the results should be very predictable: Code study_trend(8, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:20:51 Time: 0:20:51 Code study_trend(3, does_trend_up) 100% (47578 of 47578) |###########################################################| Elapsed Time: 0:26:56 Time: 0:26:56 ","version":null,"tagName":"h2"},{"title":"Conclusion and Summary​","type":1,"pageTitle":"Event studies and earnings releases","url":"/2016/06/event-studies-and-earnings-releases#conclusion-and-summary","content":" I guess the most important thing to summarize with is this: looking at the entire market, stock performance prior to an earnings release has no bearing on the stock's performance. Honestly: given the huge variability of returns after an earnings release, even when the stock has been trending for a long time, you're best off divesting before an earnings release and letting the market sort itself out. However, there is a big caveat. These results are taken when we look at the entire market. So while we can say that the market as a whole knows nothing and just reacts violently, I want to take a closer look into this data. Does the market typically perform poorly on large-cap/high liquidity stocks? Do smaller companies have investors that know them better and can thus predict performance better? Are specific market sectors better at prediction? Presumably technology stocks are more volatile than the industrials. So there are some more interesting questions I still want to ask with this data. Knowing that the hard work of data processing is largely already done, it should be fairly simple to continue this analysis and get much more refined with it. Until next time. Appendix Export event data for Russell 3000 companies: Code import pandas as pd from html.parser import HTMLParser from datetime import datetime, timedelta import requests import re from dateutil import parser import progressbar from concurrent import futures import yaml class EarningsParser(HTMLParser): store_dates = False earnings_offset = None dates = [] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.dates = [] def handle_starttag(self, tag, attrs): if tag == 'table': self.store_dates = True def handle_data(self, data): if self.store_dates: match = re.match(r'\\d+/\\d+/\\d+', data) if match: self.dates.append(match.group(0)) # If a company reports before the bell, record the earnings date # being at midnight the day before. Ex: WMT reports 5/19/2016, # but we want the reference point to be the closing price on 5/18/2016 if 'After Close' in data: self.earnings_offset = timedelta(days=0) elif 'Before Open' in data: self.earnings_offset = timedelta(days=-1) def handle_endtag(self, tag): if tag == 'table': self.store_dates = False def earnings_releases(ticker): #print("Looking up ticker {}".format(ticker)) user_agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) '\\ 'Gecko/20100101 Firefox/46.0' headers = {'user-agent': user_agent} base_url = 'http://www.streetinsider.com/ec_earnings.php?q={}'\\ .format(ticker) e = EarningsParser() s = requests.Session() a = requests.adapters.HTTPAdapter(max_retries=0) s.mount('http://', a) e.feed(str(s.get(base_url, headers=headers).content)) if e.earnings_offset is not None: dates = map(lambda x: parser.parse(x) + e.earnings_offset, e.dates) past = filter(lambda x: x < datetime.now(), dates) return list(map(lambda d: d.isoformat(), past)) # Use a Russell-3000 ETF tracker (ticker IWV) to get a list of holdings r3000 = pd.read_csv('https://www.ishares.com/us/products/239714/' 'ishares-russell-3000-etf/1449138789749.ajax?' 'fileType=csv&fileName=IWV_holdings&dataType=fund', header=10) r3000_equities = r3000[(r3000['Exchange'] == 'NASDAQ') | (r3000['Exchange'] == 'New York Stock Exchange Inc.')] dates_file = open('earnings_dates.yaml', 'w') with futures.ThreadPoolExecutor(max_workers=8) as pool: fs = {pool.submit(earnings_releases, r3000_equities.ix[t]['Ticker']): t for t in r3000_equities.index} pbar = progressbar.ProgressBar(term_width=80, max_value=r3000_equities.index.max()) for future in futures.as_completed(fs): i = fs[future] pbar.update(i) dates_file.write(yaml.dump({r3000_equities.ix[i]['Ticker']: future.result()})) Downloading stock price data needed for the event studies: Code from secrets import QUANDL_KEY import pandas as pd import yaml from dateutil.parser import parse from datetime import timedelta import quandl from progressbar import ProgressBar def fetch_ticker(ticker, start, end): # Quandl is currently giving me issues with returning # the entire dataset and not slicing server-side. # So instead, we'll do it client-side! q_format = '%Y-%m-%d' ticker_data = quandl.get('YAHOO/' + ticker, start_date=start.strftime(q_format), end_date=end.strftime(q_format), authtoken=QUANDL_KEY) return ticker_data data_str = open('earnings_dates.yaml', 'r').read() # Need to remove invalid lines filtered = filter(lambda x: '{' not in x, data_str.split('\\n')) earnings_data = yaml.load('\\n'.join(filtered)) # Get the first 1500 keys - split up into two statements # because of Quandl rate limits tickers = list(earnings_data.keys()) price_dict = {} invalid_tickers = [] for ticker in ProgressBar()(tickers[0:1500]): try: # Replace '.' with '-' in name for some tickers fixed = ticker.replace('.', '-') event_strs = earnings_data[ticker] events = [parse(event) for event in event_strs] td = timedelta(days=20) price_dict[ticker] = fetch_ticker(fixed, min(events)-td, max(events)+td) except quandl.NotFoundError: invalid_tickers.append(ticker) # Execute this after 10 minutes have passed for ticker in ProgressBar()(tickers[1500:]): try: # Replace '.' with '-' in name for some tickers fixed = ticker.replace('.', '-') event_strs = earnings_data[ticker] events = [parse(event) for event in event_strs] td = timedelta(days=20) price_dict[ticker] = fetch_ticker(fixed, min(events)-td, max(events)+td) except quandl.NotFoundError: invalid_tickers.append(ticker) prices_store = pd.HDFStore('price_data.hdf') for ticker, prices in price_dict.items(): prices_store[ticker] = prices ","version":null,"tagName":"h2"},{"title":"A Rustic re-podcasting server","type":0,"sectionRef":"#","url":"/2016/10/rustic-repodcasting","content":"","keywords":"","version":null},{"title":"The Setup​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#the-setup","content":" We'll be using the iron library to handle the server, and hyper to fetch the data we need from elsewhere on the interwebs. HTML5Ever allows us to ingest the content that will be coming from Bassdrive, and finally, output is done with handlebars-rust. It will ultimately be interesting to see how much more work must be done to actually get this working over another language like Python. Coming from a dynamic state of mind it's super easy to just chain stuff together, ship it out, and call it a day. I think I'm going to end up getting much dirtier trying to write all of this out. ","version":null,"tagName":"h2"},{"title":"Issue 1: Strings​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#issue-1-strings","content":" Strings in Rust are hard. I acknowledge Python can get away with some things that make strings super easy (and Python 3 has gotten better at cracking down on some bad cases, str <-> bytes specifically), but Rust is hard. Let's take for example the 404 error handler I'm trying to write. The result should be incredibly simple: All I want is to echo backDidn't find URL: <url>. Shouldn't be that hard right? In Python I'd just do something like: def echo_handler(request): return "You're visiting: {}".format(request.uri) And we'd call it a day. Rust isn't so simple. Let's start with the trivial examples people post online: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, "You found the server!"))) } Doesn't look too bad right? In fact, it's essentially the same as the Python version! All we need to do is just send back a string of some form. So, we look up the documentation for Request and see a url field that will contain what we want. Let's try the first iteration: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, "You found the URL: " + req.url))) } Which yields the error: error[E0369]: binary operation `+` cannot be applied to type `&'static str` OK, what's going on here? Time to start Googling for "concatenate strings in Rust". That's what we want to do right? Concatenate a static string and the URL. After Googling, we come across a helpful concat! macro that looks really nice! Let's try that one: fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, concat!("You found the URL: ", req.url)))) } And the error: error: expected a literal Turns out Rust actually blows up because the concat! macro expects us to know at compile time what req.url is. Which, in my outsider opinion, is a bit strange. println! and format!, etc., all handle values they don't know at compile time. Why can't concat!? By any means, we need a new plan of attack. How about we try formatting strings? fn hello_world(req: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, format!("You found the URL: {}", req.url)))) } And at long last, it works. Onwards! ","version":null,"tagName":"h2"},{"title":"Issue 2: Fighting with the borrow checker​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#issue-2-fighting-with-the-borrow-checker","content":" Rust's single coolest feature is how the compiler can guarantee safety in your program. As long as you don't use unsafe pointers in Rust, you're guaranteed safety. And not having truly manual memory management is really cool; I'm totally OK with never having to write malloc() again. That said, even the Rust documentation makes a specific note: Many new users to Rust experience something we like to call ‘fighting with the borrow checker’, where the Rust compiler refuses to compile a program that the author thinks is valid. If you have to put it in the documentation, it's not a helpful note: it's hazing. So now that we have a handler which works with information from the request, we want to start making something that looks like an actual web application. The router provided by iron isn't terribly difficult so I won't cover it. Instead, the thing that had me stumped for a couple hours was trying to dynamically create routes. The unfortunate thing with Rust (in my limited experience at the moment) is that there is a severe lack of non-trivial examples. Using the router is easy when you want to give an example of a static function. But how do you you start working on things that are a bit more complex? We're going to cover that here. Our first try: creating a function which returns other functions. This is a principle called currying. We set up a function that allows us to keep some data in scope for another function to come later. fn build_handler(message: String) -> Fn(&mut Request) -> IronResult<Response> { move |_: &mut Request| { Ok(Response::with((status::Ok, message))) } } We've simply set up a function that returns another anonymous function with themessage parameter scoped in. If you compile this, you get not 1, not 2, but 5 new errors. 4 of them are the same though: error[E0277]: the trait bound `for<'r, 'r, 'r> std::ops::Fn(&'r mut iron::Request<'r, 'r>) -> std::result::Result<iron::Response, iron::IronError> + 'static: std::marker::Sized` is not satisfied ...oookay. I for one, am not going to spend time trying to figure out what's going on there. And it is here that I will save the audience many hours of frustrated effort. At this point, I decided to switch from iron to pure hyper since usinghyper would give me a much simpler API. All I would have to do is build a function that took two parameters as input, and we're done. That said, it ultimately posed many more issues because I started getting into a weird fight with the 'static lifetimeand being a Rust newbie I just gave up on trying to understand it. Instead, we will abandon (mostly) the curried function attempt, and instead take advantage of something Rust actually intends us to use: struct andtrait. Remember when I talked about a lack of non-trivial examples on the Internet? This is what I was talking about. I could only find one example of this available online, and it was incredibly complex and contained code we honestly don't need or care about. There was no documentation of how to build routes that didn't use static functions, etc. But, I'm assuming you don't really care about my whining, so let's get to it. The iron documentation mentions the Handler trait as being something we can implement. Does the function signature for that handle() method look familiar? It's what we've been working with so far. The principle is that we need to define a new struct to hold our data, then implement that handle() method to return the result. Something that looks like this might do: struct EchoHandler { message: String } impl Handler for EchoHandler { fn handle(&self, _: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, self.message))) } } // Later in the code when we set up the router... let echo = EchoHandler { message: "Is it working yet?" } router.get("/", echo.handle, "index"); We attempt to build a struct, and give its handle method off to the router so the router knows what to do. You guessed it, more errors: error: attempted to take value of method `handle` on type `EchoHandler` Now, the Rust compiler is actually a really nice fellow, and offers us help: help: maybe a `()` to call it is missing? If not, try an anonymous function We definitely don't want to call that function, so maybe try an anonymous function as it recommends? router.get("/", |req: &mut Request| echo.handle(req), "index"); Another error: error[E0373]: closure may outlive the current function, but it borrows `echo`, which is owned by the current function Another helpful message: help: to force the closure to take ownership of `echo` (and any other referenced variables), use the `move` keyword We're getting closer though! Let's implement this change: router.get("/", move |req: &mut Request| echo.handle(req), "index"); And here's where things get strange: error[E0507]: cannot move out of borrowed content --> src/main.rs:18:40 | 18 | Ok(Response::with((status::Ok, self.message))) | ^^^^ cannot move out of borrowed content Now, this took me another couple hours to figure out. I'm going to explain it, but keep this in mind: Rust only allows one reference at a time (exceptions apply of course). When we attempt to use self.message as it has been created in the earlierstruct, we essentially are trying to give it away to another piece of code. Rust's semantics then state that we may no longer access it unless it is returned to us (which iron's code does not do). There are two ways to fix this: Only give away references (i.e. &self.message instead of self.message) instead of transferring ownershipMake a copy of the underlying value which will be safe to give away I didn't know these were the two options originally, so I hope this helps the audience out. Because iron won't accept a reference, we are forced into the second option: making a copy. To do so, we just need to change the function to look like this: Ok(Response::with((status::Ok, self.message.clone()))) Not so bad, huh? My only complaint is that it took so long to figure out exactly what was going on. And now we have a small server that we can configure dynamically. At long last. Final sidenote: You can actually do this without anonymous functions. Just change the router line to:router.get("/", echo, "index"); Rust's type system seems to figure out that we want to use the handle() method. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"A Rustic re-podcasting server","url":"/2016/10/rustic-repodcasting#conclusion","content":" After a good long days' work, we now have the routing functionality set up on our application. We should be able to scale this pretty well in the future: the RSS content we need to deliver in the future can be treated as a string, so the building blocks are in place. There are two important things I learned starting with Rust today: Rust is a new language, and while the code is high-quality, the mindshare is coming.I'm a terrible programmer. Number 1 is pretty obvious and not surprising to anyone. Number two caught me off guard. I've gotten used to having either a garbage collector (Java, Python, etc.) or playing a little fast and loose with scoping rules (C, C++). You don't have to worry about object lifetime there. With Rust, it's forcing me to fully understand and use well the memory in my applications. In the final mistake I fixed (using .clone()) I would have been fine in C++ to just give away that reference and never use it again. I wouldn't have run into a "use-after-free" error, but I would have potentially been leaking memory. Rust forced me to be incredibly precise about how I use it. All said I'm excited for using Rust more. I think it's super cool, it's just going to take me a lot longer to do this than I originally thought. ","version":null,"tagName":"h2"},{"title":"PCA audio compression","type":0,"sectionRef":"#","url":"/2016/11/pca-audio-compression","content":"","keywords":"","version":null},{"title":"Towards a new (and pretty poor) compression scheme​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#towards-a-new-and-pretty-poor-compression-scheme","content":" I'm going to be working with some audio data for a while as I get prepared for a term project this semester. I'll be working (with a partner) to design a system for separating voices from music. Given my total lack of experience with Digital Signal Processing I figured that now was as good a time as ever to work on a couple of fun projects that would get me back up to speed. The first project I want to work on: Designing a new compression scheme for audio data. ","version":null,"tagName":"h2"},{"title":"A Brief Introduction to Audio Compression​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-brief-introduction-to-audio-compression","content":" Audio files when uncompressed (files ending with .wav) are huge. Like, 10.5 Megabytes per minute huge. Storage is cheap these days, but that's still an incredible amount of data that we don't really need. Instead, we'd like to compress that data so that it's not taking up so much space. There are broadly two ways to accomplish this: Lossless compression - Formats like FLAC, ALAC, and Monkey's Audio (.ape) all go down this route. The idea is that when you compress and uncompress a file, you get exactly the same as what you started with. Lossy compression - Formats like MP3, Ogg, and AAC (.m4a) are far more popular, but make a crucial tradeoff: We can reduce the file size even more during compression, but the decompressed file won't be the same. There is a fundamental tradeoff at stake: Using lossy compression sacrifices some of the integrity of the resulting file to save on storage space. Most people (I personally believe it's everybody) can't hear the difference, so this is an acceptable tradeoff. You have files that take up a 10th of the space, and nobody can tell there's a difference in audio quality. ","version":null,"tagName":"h2"},{"title":"A PCA-based Compression Scheme​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-pca-based-compression-scheme","content":" What I want to try out is a PCA approach to encoding audio. The PCA technique comes from Machine Learning, where it is used for a process called Dimensionality Reduction. Put simply, the idea is the same as lossy compression: if we can find a way that represents the data well enough, we can save on space. There are a lot of theoretical concerns that lead me to believe this compression style will not end well, but I'm interested to try it nonetheless. PCA works as follows: Given a dataset with a number of features, I find a way to approximate those original features using some "new features" that are statistically as close as possible to the original ones. This is comparable to a scheme like MP3: Given an original signal, I want to find a way of representing it that gets approximately close to what the original was. The difference is that PCA is designed for statistical data, and not signal data. But we won't let that stop us. The idea is as follows: Given a signal, reshape it into 1024 columns by however many rows are needed (zero-padded if necessary). Run the PCA algorithm, and do dimensionality reduction with a couple different settings. The number of components I choose determines the quality: If I use 1024 components, I will essentially be using the original signal. If I use a smaller number of components, I start losing some of the data that was in the original file. This will give me an idea of whether it's possible to actually build an encoding scheme off of this, or whether I'm wasting my time. ","version":null,"tagName":"h2"},{"title":"Running the Algorithm​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#running-the-algorithm","content":" The audio I will be using comes from the song Tabulasa, by Broke for Free. I'll be loading in the audio signal to Python and using Scikit-Learn to actually run the PCA algorithm. We first need to convert the FLAC file I have to a WAV: !ffmpeg -hide_banner -loglevel panic -i "Broke For Free/XXVII/01 Tabulasa.flac" "Tabulasa.wav" -c wav Then, let's go ahead and load a small sample so you can hear what is going on. from IPython.display import Audio from scipy.io import wavfile samplerate, tabulasa = wavfile.read('Tabulasa.wav') start = samplerate * 14 # 10 seconds in end = start + samplerate * 10 # 5 second duration Audio(data=tabulasa[start:end, 0], rate=samplerate) Next, we'll define the code we will be using to do PCA. It's very short, as the PCA algorithm is very simple. from sklearn.decomposition import PCA import numpy as np def pca_reduce(signal, n_components, block_size=1024): # First, zero-pad the signal so that it is divisible by the block_size samples = len(signal) hanging = block_size - np.mod(samples, block_size) padded = np.lib.pad(signal, (0, hanging), 'constant', constant_values=0) # Reshape the signal to have 1024 dimensions reshaped = padded.reshape((len(padded) // block_size, block_size)) # Second, do the actual PCA process pca = PCA(n_components=n_components) pca.fit(reshaped) transformed = pca.transform(reshaped) reconstructed = pca.inverse_transform(transformed).reshape((len(padded))) return pca, transformed, reconstructed Now that we've got our functions set up, let's try actually running something. First, we'll use n_components == block_size, which implies that we should end up with the same signal we started with. tabulasa_left = tabulasa[:,0] _, _, reconstructed = pca_reduce(tabulasa_left, 1024, 1024) Audio(data=reconstructed[start:end], rate=samplerate) OK, that does indeed sound like what we originally had. Let's drastically cut down the number of components we're doing this with as a sanity check: the audio quality should become incredibly poor. _, _, reconstructed = pca_reduce(tabulasa_left, 32, 1024) Audio(data=reconstructed[start:end], rate=samplerate) As expected, our reconstructed audio does sound incredibly poor! But there's something else very interesting going on here under the hood. Did you notice that the bassline comes across very well, but that there's no midrange or treble? The drums are almost entirely gone. ","version":null,"tagName":"h2"},{"title":"Drop the (Treble)​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#drop-the-treble","content":" It will help to understand PCA more fully when trying to read this part, but I'll do my best to break it down. PCA tries to find a way to best represent the dataset using "components." Think of each "component" as containing some of the information you need in order to reconstruct the full audio. For example, you might have a "low frequency" component that contains all the information you need in order to hear the bassline. There might be other components that explain the high frequency things like singers, or melodies, that you also need. What makes PCA interesting is that it attempts to find the "most important" components in explaining the signal. In a signal processing world, this means that PCA is trying to find the signal amongst the noise in your data. In our case, this means that PCA, when forced to work with small numbers of components, will chuck out the noisy components first. It's doing it's best job to reconstruct the signal, but it has to make sacrifices somewhere. So I've mentioned that PCA identifies the "noisy" components in our dataset. This is equivalent to saying that PCA removes the "high frequency" components in this case: it's very easy to represent a low-frequency signal like a bassline. It's far more difficult to represent a high-frequency signal because it's changing all the time. When you force PCA to make a tradeoff by using a small number of components, the best it can hope to do is replicate the low-frequency sections and skip the high-frequency things. This is a very interesting insight, and it also has echos (pardon the pun) of how humans understand music in general. Other encoding schemes (like MP3, etc.) typically chop off a lot of the high-frequency range as well. There is typically a lot of high-frequency noise in audio that is nearly impossible to hear, so it's easy to remove it without anyone noticing. PCA ends up doing something similar, and while that certainly wasn't the intention, it is an interesting effect. ","version":null,"tagName":"h2"},{"title":"A More Realistic Example​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#a-more-realistic-example","content":" So we've seen the edge cases so far: Using a large number of components results in audio very close to the original, and using a small number of components acts as a low-pass filter. How about we develop something that sounds "good enough" in practice, that we can use as a benchmark for size? We'll use ourselves as judges of audio quality, and build another function to help us estimate how much space we need to store everything in. from bz2 import compress import pandas as pd def raw_estimate(transformed, pca): # We assume that we'll be storing things as 16-bit WAV, # meaning two bytes per sample signal_bytes = transformed.tobytes() # PCA stores the components as floating point, we'll assume # that means 32-bit floats, so 4 bytes per element component_bytes = transformed.tobytes() # Return a result in megabytes return (len(signal_bytes) + len(component_bytes)) / (2**20) # Do an estimate for lossless compression applied on top of our # PCA reduction def bz2_estimate(transformed, pca): bytestring = transformed.tobytes() + b';' + pca.components_.tobytes() compressed = compress(bytestring) return len(compressed) / (2**20) compression_attempts = [ (1, 1), (1, 2), (1, 4), (4, 32), (16, 256), (32, 256), (64, 256), (128, 1024), (256, 1024), (512, 1024), (128, 2048), (256, 2048), (512, 2048), (1024, 2048) ] def build_estimates(signal, n_components, block_size): pca, transformed, recon = pca_reduce(tabulasa_left, n_components, block_size) raw_pca_estimate = raw_estimate(transformed, pca) bz2_pca_estimate = bz2_estimate(transformed, pca) raw_size = len(recon.tobytes()) / (2**20) return raw_size, raw_pca_estimate, bz2_pca_estimate pca_compression_results = pd.DataFrame([ build_estimates(tabulasa_left, n, bs) for n, bs in compression_attempts ]) pca_compression_results.columns = ["Raw", "PCA", "PCA w/ BZ2"] pca_compression_results.index = compression_attempts pca_compression_results \tRaw\tPCA\tPCA w/ BZ2(1, 1)\t69.054298\t138.108597\t16.431797 (1, 2)\t69.054306\t69.054306\t32.981380 (1, 4)\t69.054321\t34.527161\t16.715032 (4, 32)\t69.054443\t17.263611\t8.481735 (16, 256)\t69.054688\t8.631836\t4.274846 (32, 256)\t69.054688\t17.263672\t8.542909 (64, 256)\t69.054688\t34.527344\t17.097543 (128, 1024)\t69.054688\t17.263672\t9.430644 (256, 1024)\t69.054688\t34.527344\t18.870387 (512, 1024)\t69.054688\t69.054688\t37.800940 (128, 2048)\t69.062500\t8.632812\t6.185015 (256, 2048)\t69.062500\t17.265625\t12.366942 (512, 2048)\t69.062500\t34.531250\t24.736506 (1024, 2048)\t69.062500\t69.062500\t49.517493 As we can see, there are a couple of instances where we do nearly 20 times better on storage space than the uncompressed file. Let's here what that sounds like: _, _, reconstructed = pca_reduce(tabulasa_left, 16, 256) Audio(data=reconstructed[start:end], rate=samplerate) It sounds incredibly poor though. Let's try something that's a bit more realistic: _, _, reconstructed = pca_reduce(tabulasa_left, 1, 4) Audio(data=reconstructed[start:end], rate=samplerate) And just out of curiosity, we can try something that has the same ratio of components to block size. This should be close to an apples-to-apples comparison. _, _, reconstructed = pca_reduce(tabulasa_left, 64, 256) Audio(data=reconstructed[start:end], rate=samplerate) The smaller block size definitely has better high-end response, but I personally think the larger block size sounds better overall. ","version":null,"tagName":"h2"},{"title":"Conclusions​","type":1,"pageTitle":"PCA audio compression","url":"/2016/11/pca-audio-compression#conclusions","content":" So, what do I think about audio compression using PCA? Strangely enough, it actually works pretty well relative to what I expected. That said, it's a terrible idea in general. First off, you don't really save any space. The component matrix needed to actually run the PCA algorithm takes up a lot of space on its own, so it's very difficult to save space without sacrificing a huge amount of audio quality. And even then, codecs like AAC sound very nice even at bitrates that this PCA method could only dream of. Second, there's the issue of audio streaming. PCA relies on two components: the datastream, and a matrix used to reconstruct the original signal. While it is easy to stream the data, you can't stream that matrix. And even if you divided the stream up into small blocks to give you a small matrix, you must guarantee that the matrix arrives; if you don't have that matrix, the data stream will make no sense whatsoever. All said, this was an interesting experiment. It's really cool seeing PCA used for signal analysis where I haven't seen it applied before, but I don't think it will lead to any practical results. Look forward to more signal processing stuff in the future! ","version":null,"tagName":"h2"},{"title":"Captain's Cookbook: Project setup","type":0,"sectionRef":"#","url":"/2018/01/captains-cookbook-part-1","content":"","keywords":"","version":null},{"title":"Step 1: Installing capnp​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-1-installing-capnp","content":" The capnp binary itself is needed for taking the schema files you write and turning them into a format that can be used by the code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed. I'll refer you to Cap'N Proto's installation instructions here. As a quick TLDR though: Linux users will likely have a binary shipped by their package manager - On Ubuntu, apt install capnproto is enoughOS X users can use Homebrew as an easy install path. Just brew install capnpWindows users are a bit more complicated. If you're using Chocolatey, there's a package available. If that doesn't work however, you need to download a release zip and make sure that the capnp.exe binary is in your %PATH% environment variable The way you know you're done with this step is if the following command works in your shell: capnp id ","version":null,"tagName":"h2"},{"title":"Step 2: Starting a Cap'N Proto Rust project​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-2-starting-a-capn-proto-rust-project","content":" After the capnp binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple mkdir capnp_cookbook_1 cd capnp_cookbook_1 cargo init --bin We'll put the following content into Cargo.toml: [package] name = "capnp_cookbook_1" version = "0.1.0" authors = ["Bradlee Speice <bspeice@kcg.com>"] [build-dependencies] capnpc = "0.8" # 1 [dependencies] capnp = "0.8" # 2 This sets up: The Rust code generator (CAPNProto Compiler)The Cap'N Proto runtime library (CAPNProto runtime) We've now got everything prepared that we need for writing a Cap'N Proto project. ","version":null,"tagName":"h2"},{"title":"Step 3: Writing a basic schema​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-3-writing-a-basic-schema","content":" We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure you get familiar with how to start from a basic project. First, we're going to create a top-level directory for storing the schema files in: # Assuming we're starting from the `capnp_cookbook_1` directory created earlier mkdir schema cd schema Now, we're going to put the following content in point.capnp: @0xab555145c708dad2; struct Point { x @0 :Int32; y @1 :Int32; } Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format. ","version":null,"tagName":"h2"},{"title":"Step 4: Setting up the build process​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-4-setting-up-the-build-process","content":" Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using. This is typically done through a build.rs file to invoke the schema compiler. In the same folder as your Cargo.toml file, please put the following content in build.rs: extern crate capnpc; fn main() { ::capnpc::CompilerCommand::new() .src_prefix("schema") // 1 .file("schema/point.capnp") // 2 .run().expect("compiling schema"); } This sets up the protocol compiler (capnpc from earlier) to compile the schema we've built so far. Because Cap'N Proto schema files can re-use types specified in other files, the src_prefix() tells the compiler where to look for those extra files at.We specify the schema file we're including by hand. In a much larger project, you could presumably build the CompilerCommanddynamically, but we won't worry too much about that one for now. ","version":null,"tagName":"h2"},{"title":"Step 5: Running the build​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-5-running-the-build","content":" If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code. Run a cargo build command, and if you don't see cargo complaining, you're doing just fine! So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives somewhere in the target/ directory. The long answer is that you're best off running a find command to get the actual file path: # Assuming we're running from the capnp_cookbook_1 project folder find . -name point_capnp.rs Alternately, if the find command isn't available, the path will look something like: ./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs See if there are any paths in your target directory that look similar. Now, the file content looks pretty nasty. I've included an example hereif you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how the schema we wrote for the "Point" message is tied to the generated code. First, the Cap'N Proto library splits things up into Builder and Reader structs. These are best thought of the same way Rust separates mut from non-mut code. Builders are mut versions of your message, and Readers are immutable versions. For example, the Builder impl for point defines get_x(), set_x(), get_y(), and set_y() methods. In comparison, the Reader impl only defines get_x() and get_y() methods. So now we know that there are some get and set methods available for our x and y coordinates; but what do we actually do with those? ","version":null,"tagName":"h2"},{"title":"Step 6: Making a point​","type":1,"pageTitle":"Captain's Cookbook: Project setup","url":"/2018/01/captains-cookbook-part-1#step-6-making-a-point","content":" So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code should go in src/main.rs: // Note that we use `capnp` here, NOT `capnpc` extern crate capnp; // We create a module here to define how we are to access the code // being included. pub mod point_capnp { // The environment variable OUT_DIR is set by Cargo, and // is the location of all the code that was built as part // of the codegen step. // point_capnp.rs is the actual file to include include!(concat!(env!("OUT_DIR"), "/point_capnp.rs")); } fn main() { // The process of building a Cap'N Proto message is a bit tedious. // We start by creating a generic Builder; it acts as the message // container that we'll later be filling with content of our `Point` let mut builder = capnp::message::Builder::new_default(); // Because we need a mutable reference to the `builder` later, // we fence off this part of the code to allow sequential mutable // borrows. As I understand it, non-lexical lifetimes: // https://github.com/rust-lang/rust-roadmap/issues/16 // will make this no longer necessary { // And now we can set up the actual message we're trying to create let mut point_msg = builder.init_root::<point_capnp::point::Builder>(); // Stuff our message with some content point_msg.set_x(12); point_msg.set_y(14); } // It's now time to serialize our message to binary. Let's set up a buffer for that: let mut buffer = Vec::new(); // And actually fill that buffer with our data capnp::serialize::write_message(&mut buffer, &builder).unwrap(); // Finally, let's deserialize the data let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); // `deserialized` is currently a generic reader; it understands // the content of the message we gave it (i.e. that there are two // int32 values) but doesn't really know what they represent (the Point). // This is where we map the generic data back into our schema. let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); // We can now get our x and y values back, and make sure they match assert_eq!(point_reader.get_x(), 12); assert_eq!(point_reader.get_y(), 14); } And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up some practical examples of Cap'N Proto in action: ","version":null,"tagName":"h2"},{"title":"Captain's Cookbook: Practical usage","type":0,"sectionRef":"#","url":"/2018/01/captains-cookbook-part-2","content":"","keywords":"","version":null},{"title":"Attempt 1: Move the reference​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-1-move-the-reference","content":" As a first attempt, we're going to try and let Rust move the reference. Our code will look something like: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from // somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); // By using `point_reader` inside the new thread, we're hoping that Rust can // safely move the reference and invalidate the original thread's usage. // Since the original thread doesn't use `point_reader` again, this should // be safe, right? let handle = std::thread:spawn(move || { assert_eq!(point_reader.get_x(), 12); assert_eq!(point_reader.get_y(), 14); }); handle.join().unwrap() } Well, the Rust compiler doesn't really like this. We get four distinct errors back: error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely | error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely | error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` --> src/main.rs:31:18 | 31 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely | error: aborting due to 4 previous errors Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating. Pay attention to the text that keeps on getting repeated though: XYZ cannot be sent between threads safely. This is a bit frustrating: we own the buffer from which all the content was derived, and we don't have any unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust preventing us from doing something that really should be legal? This is what is known as fighting the borrow checker. Let our crusade begin. ","version":null,"tagName":"h2"},{"title":"Attempt 2: Put the Reader in a Box​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-2-put-the-reader-in-a-box","content":" The Box type allows us to convert a pointer we have (in our case the point_reader) into an "owned" value, which should be easier to send across threads. Our next attempt looks something like this: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content // from somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader = deserialized.get_root::<point_capnp::point::Reader>().unwrap(); let boxed_reader = Box::new(point_reader); // Now that the reader is `Box`ed, we've proven ownership, and Rust can // move the ownership to the new thread, right? let handle = std::thread::spawn(move || { assert_eq!(boxed_reader.get_x(), 12); assert_eq!(boxed_reader.get_y(), 14); }); handle.join().unwrap(); } Spoiler alert: still doesn't work. Same errors still show up. error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely | error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely | error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely | error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` --> src/main.rs:33:18 | 33 | let handle = std::thread::spawn(move || { | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely | error: aborting due to 4 previous errors Let's be a little bit smarter about the exceptions this time though. What is thatstd::marker::Send thing the compiler keeps telling us about? The documentation is pretty clear; Send is used to denote: Types that can be transferred across thread boundaries. In our case, we are seeing the error messages for two reasons: Pointers (*const u8) are not safe to send across thread boundaries. While we're nice in our code making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make that assumption, and so complains that we're not using this in a safe manner. The point_capnp::point::Reader type is itself not safe to send across threads because it doesn't implement the Send trait. Which is to say, the things that make up a Reader are themselves not thread-safe, so the Reader is also not thread-safe. So, how are we to actually transfer a parsed Cap'N Proto message between threads? ","version":null,"tagName":"h2"},{"title":"Attempt 3: The TypedReader​","type":1,"pageTitle":"Captain's Cookbook: Practical usage","url":"/2018/01/captains-cookbook-part-2#attempt-3-the-typedreader","content":" The TypedReader is a new API implemented in the Cap'N Proto Rust code. We're interested in it here for two reasons: It allows us to define an object where the object owns the underlying data. In previous attempts, the current context owned the data, but the Reader itself had no such control. We can compose the TypedReader using objects that are safe to Send across threads, guaranteeing that we can transfer parsed messages across threads. The actual type info for the TypedReaderis a bit complex. And to be honest, I'm still really not sure what the whole point of thePhantomData thing is either. My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto message represents. That is, technically the only thing we're storing is the untyped binary message;PhantomData just enforces the principle that the binary represents some specific object that has been parsed. Either way, we can carefully construct something which is safe to move between threads: fn main() { // ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else let deserialized = capnp::serialize::read_message( &mut buffer.as_slice(), capnp::message::ReaderOptions::new() ).unwrap(); let point_reader: capnp::message::TypedReader<capnp::serialize::OwnedSegments, point_capnp::point::Owned> = capnp::message::TypedReader::new(deserialized); // Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message // (which is 'static lifetime), this is now safe let handle = std::thread::spawn(move || { // The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader // object from it let point_root = point_reader.get().unwrap(); assert_eq!(point_root.get_x(), 12); assert_eq!(point_root.get_y(), 14); }); handle.join().unwrap(); } And while we've left Rust to do the dirty work of actually moving the point_reader into the new thread, we could also use things like mpsc channels to achieve a similar effect. So now we're able to define basic Cap'N Proto messages, and send them all around our programs. ","version":null,"tagName":"h2"},{"title":"Hello!","type":0,"sectionRef":"#","url":"/2018/05/hello","content":"I'll do what I can to keep this short, there's plenty of other things we both should be doing right now. If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you covered: And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven. Okay, just one: Thanks, and keep it amazing.","keywords":"","version":null},{"title":"What I learned porting dateutil to Rust","type":0,"sectionRef":"#","url":"/2018/06/dateutil-parser-to-rust","content":"","keywords":"","version":null},{"title":"Slow down, what?​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#slow-down-what","content":" OK, fine, I guess I should start with why someone would do this. Dateutil is a Python library for handling dates. The standard library support for time in Python is kinda dope, but there are a lot of extras that go into making it useful beyond just the datetimemodule. dateutil.parser specifically is code to take all the super-weird time formats people come up with and turn them into something actually useful. Date/time parsing, it turns out, is just like everything else involvingcomputers andtime: it feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people suck and this is whywe can't we have nice things. But alas, we'll try and make contemporary art out of the rubble and give it a pretentious name likeTime. Time What makes dateutil.parser great is that there's single function with a single argument that drives what programmers interact with:parse(timestr). It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can possibly do to make sense of your input" value. It doesn't expect much of you. And now it's in Rust. ","version":null,"tagName":"h2"},{"title":"Lost in Translation​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#lost-in-translation","content":" Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better experiences thanthis guywho attempted the same thing for D. These are the actual take-aways: When transcribing code, stay as close to the original library as possible. I'm talking about using the same variable names, same access patterns, the whole shebang. It's way too easy to make a couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference manual for verbatim what your code should be means that you don't spend that long debugging complicated logic, you're more looking for typos. Also, don't use nice Rust things like enums. Whileone time it worked out OK for me, I also managed to shoot myself in the foot a couple times because dateutil stores AM/PM as a boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In general, writing nice code should not be a first-pass priority when you're just trying to recreate the same functionality. Exceptions are a pain. Make peace with it. Python code is just allowed to skip stack frames. So when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns outhe's not quite right, and I'm OK with that. And whiledateutil is pretty well-behaved about not skipping multiple stack frames,130-line try-catch blockstake a while to verify. As another Python quirk, be very careful aboutlong nested if-elif-else blocks. I used to think that Python's whitespace was just there to get you to format your code correctly. I think that no longer. It's way too easy to close a block too early and have incredibly weird issues in the logic. Make sure you use an editor that displays indentation levels so you can keep things straight. Rust macros are not free. I originally had themain test bodywrapped up in a macro using pyo3. It took two minutes to compile. Aftermoving things to a functioncompile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually functions that need to be liberated, man. Finally, I really miss list comprehensions and dictionary comprehensions. As a quick comparison, seethis dateutil codeandthe implementation in Rust. I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be added through macros or syntax extensions. Either way, they're expressive, save typing, and are super-readable. Let's get more of that. ","version":null,"tagName":"h2"},{"title":"Using a young language​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#using-a-young-language","content":" Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On more than one occasion though, I've had issues navigating the Rust ecosystem. What I'll call the "canonical library" is still being built. In Python, if you need datetime parsing, you use dateutil. If you want decimal types, it's already in thestandard library. While I might've gotten away with f64, dateutil uses decimals, and I wanted to follow the principle of staying as close to the original library as possible. Thus began my quest to find a decimal library in Rust. What I quickly found was summarized in a comment: Writing a BigDecimal is easy. Writing a good BigDecimal is hard. -cmr In practice, this means that there are at least 4differentimplementations available. And that's a lot of decisions to worry about when all I'm thinking is "why can'tcalendar reform be a thing" and I'm forced to dig through a coupledifferentthreads to figure out if the library I'm look at is dead or just stable. And even when the "canonical library" exists, there's no guarantees that it will be well-maintained.Chrono is the de facto date/time library in Rust, and just released version 0.4.4 like two days ago. Meanwhile,chrono-tz appears to be dead in the water even thoughthere are people happy to help maintain it. I know relatively little about it, but it appears that most of the release process is automated; keeping that up to date should be a no-brainer. ","version":null,"tagName":"h2"},{"title":"Trial Maintenance Policy​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#trial-maintenance-policy","content":" Specifically given "maintenance" being anoft-discussedissue, I'm going to try out the following policy to keep things moving on dtparse: Issues/PRs needing maintainer feedback will be updated at least weekly. I want to make sure nobody's blocking on me. To keep issues/PRs needing contributor feedback moving, I'm going to (kindly) ask the contributor to check in after two weeks, and close the issue without resolution if I hear nothing back after a month. The second point I think has the potential to be a bit controversial, so I'm happy to receive feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And second: I don't mind keeping those requests going indefinitely. I just want to try and balance keeping things moving with giving people the necessary time they need. I should also note that I'm still getting some best practices in place - CONTRIBUTING and CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are perfect. ","version":null,"tagName":"h2"},{"title":"Roadmap and Conclusion​","type":1,"pageTitle":"What I learned porting dateutil to Rust","url":"/2018/06/dateutil-parser-to-rust#roadmap-and-conclusion","content":" So if I've now built a dateutil-compatible parser, we're done, right? Of course not! That's not nearly ambitious enough. Ultimately, I'd love to have a library that's capable of parsing everything the Linux date command can do (and not date on OSX, because seriously, BSD coreutils are the worst). I know Rust has a coreutils rewrite going on, and dtparse would potentially be an interesting candidate since it doesn't bring in a lot of extra dependencies. humantimecould help pick up some of the (current) slack in dtparse, so maybe we can share and care with each other? All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going to take it hard. And in the mean time, I'm looking forward to building more. Onwards. ","version":null,"tagName":"h2"},{"title":"Isomorphic desktop apps with Rust","type":0,"sectionRef":"#","url":"/2018/09/isomorphic-apps","content":"I both despise Javascript and am stunned by its success doing some really cool things. It'sthis duality that's led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I bootstrap a simple desktop application. See, as much asWebassembly isn't trying to replace Javascript,I want Javascript gone. There are plenty of people who don't share my views, and they are probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think it's hilarious that thelanguage specificationdramatically outpaces anyone'sactual implementation. The answer to this conundrum is of course to recompile code from newer versions of the language to older versions of the same language before running. At least Babel is a nice tongue-in-cheek reference. Yet for as much hate as Electron receives, it does a stunningly good job at solving a really hard problem: how the hell do I put a button on the screen and react when the user clicks it? GUI programming is hard, straight up. But if browsers are already able to run everywhere, why don't we take advantage of someone else solving the hard problems for us? I don't like that I have to use Javascript for it, but I really don't feel inclined to whip out good ol' wxWidgets. Now there are other native solutions (libui-rs, conrod, oh hey wxWdidgets again!), but those also have their own issues with distribution, styling, etc. With Electron, I canyarn create electron-app my-app and just get going, knowing that packaging/upgrades/etc. are built in. My question is: given recent innovations with WASM, are we Electron yet? No, not really. Instead, what would it take to get to a point where we can skip Javascript in Electron apps? Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to try and organize what I did manage to discover. I should also mention that the content and things I'm talking about here are not intended to be prescriptive, but more "if someone else is interested, what do we already know doesn't work?" I expect everything in this post to be obsolete within two months. Even over the course of writing this, a separate blog post had to be modified because upstream changes broke aRust tool the post tried to use. The post ultimatelygot updated, but all this happened within the span of a week. Things are moving quickly. I'll also note that we're going to skip asm.js and emscripten. Truth be told, I couldn't get either of these to output anything, and so I'm just going to sayhere be dragons. Everything I'm discussing here uses the wasm32-unknown-unknown target. The code that I did get running is availableover here. Feel free to use it as a starting point, but I'm mostly including the link as a reference for the things that were attempted. An Example Running Application So, I did technically get a running application: ...which you can also try out if you want: git clone https://github.com/speice-io/isomorphic-rust.git cd isomorphic_rust/percy yarn install && yarn start ...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly there to prove this is possible in the first place. And that's something to be proud of! There's a huge amount of engineering that went into showing a window with the text "It's alive!". There's also a lot of usability issues that prevent me from recommending anyone try Electron and WASM apps at the moment, and I think that's the more important thing to discuss. Issue the First: Complicated Toolchains I quickly established that wasm-bindgen was necessary to "link" my Rust code to Javascript. At that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM blob. To keep things simple, the goal was to package everything using webpack so that I could just load a bundle.js file on the page. That decision was to be the last thing that kinda worked in this process. The first issueI ran intowhile attempting to bundle everything via webpack is a detail in the WASM spec: This function accepts a Response object, or a promise for one, and ... [if > it] does not match the application/wasm MIME type, the returned promise will be rejected with a TypeError; WebAssembly - Additional Web Embedding API Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the web this isn't a huge issue, as the server can set MIME types when delivering the blob. With Electron, you're resolving things with a file:// URL and thus can't control the MIME type: There are a couple of solutions depending on how far into the deep end you care to venture: Embed a static file server in your Electron applicationUse a custom protocol and custom protocol handlerHost your WASM blob on a website that you resolve at runtime But all these are pretty bad solutions and defeat the purpose of using WASM in the first place. Instead, my workaround was toopen a PR with webpack and use regex to remove calls to instantiateStreaming in thebuild script: cargo +nightly build --target=wasm32-unknown-unknown && \\ wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\ # Have to use --mode=development so we can patch out the call to instantiateStreaming "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=development "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" && \\ sed -i 's/.*instantiateStreaming.*//g' "$APP_DIR/bundle.js" Once that lands, thebuild processbecomes much simpler: cargo +nightly build --target=wasm32-unknown-unknown && \\ wasm-bindgen "$WASM_DIR/debug/$WASM_NAME.wasm" --out-dir "$APP_DIR" --no-typescript && \\ "$DIR/node_modules/webpack-cli/bin/cli.js" --mode=production "$APP_DIR/app_loader.js" -o "$APP_DIR/bundle.js" But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (viawasm-bindgen and webpack), we still have to make an Electron app. For this purpose I used a starter app from Electron Forge, and then aprestart scriptto actually handle starting the application. Thefinal toolchainlooks something like this: yarn start triggers the prestart scriptprestart checks for missing tools (wasm-bindgen-cli, etc.) and then: Uses cargo to compile the Rust code into WASMUses wasm-bindgen to link the WASM blob into a Javascript file with exported symbolsUses webpack to bundle the page start script with the Javascript we just generated Uses babel under the hood to compile the wasm-bindgen code down from ES6 into something browser-compatible The start script runs an Electron Forge handler to do some sanity checksElectron actually starts ...which is complicated. I think more work needs to be done to either build a high-quality starter app that can manage these steps, or another tool that "just handles" the complexity of linking a compiled WASM file into something the Electron browser can run. Issue the Second: WASM tools in Rust For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that leads to a fragmented ecosystem. Here's what I can recommend as a starting point: Don't check in your Cargo.lock files to version control. If there's a disagreement between the version of wasm-bindgen-cli you have installed and the wasm-bindgen you're compiling with inCargo.lock, you get a nasty error: it looks like the Rust project used to create this wasm file was linked against a different version of wasm-bindgen than this binary: rust wasm file: 0.2.21 this binary: 0.2.17 Currently the bindgen format is unstable enough that these two version must exactly match, so it's required that these two version are kept in sync by either updating the wasm-bindgen dependency or this binary. Not that I ever managed to run into this myself (coughs nervously). There are two projects attempting to be "application frameworks": percy and yew. Between those, I managed to get twoexamples running using percy, but was unable to get anexample running with yew because of issues with "missing modules" during the webpack step: ERROR in ./dist/electron_yew_wasm_bg.wasm Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/yew/dist' @ ./dist/electron_yew_wasm_bg.wasm @ ./dist/electron_yew_wasm.js @ ./dist/app.js @ ./dist/app_loader.js If you want to work with the browser APIs directly, your choices are percy-webapis or stdweb (or eventually web-sys). See above for my percy examples, but when I triedan example with stdweb, I was unable to get it running: ERROR in ./dist/stdweb_electron_bg.wasm Module not found: Error: Can't resolve 'env' in '/home/bspeice/Development/isomorphic_rust/stdweb/dist' @ ./dist/stdweb_electron_bg.wasm @ ./dist/stdweb_electron.js @ ./dist/app_loader.js At this point I'm pretty convinced that stdweb is causing issues for yew as well, but can't prove it. I did also get a minimal examplerunning that doesn't depend on any tools besides wasm-bindgen. However, it requires manually writing "extern C" blocks for everything you need from the browser. Es no bueno. Finally, from a tools and platform view, there are two up-and-coming packages that should be mentioned: js-sys and web-sys. Their purpose is to be fundamental building blocks that exposes the browser's APIs to Rust. If you're interested in building an app framework from scratch, these should give you the most flexibility. I didn't touch either in my research, though I expect them to be essential long-term. So there's a lot in play from the Rust side of things, and it's just going to take some time to figure out what works and what doesn't. Issue the Third: Known Unknowns Alright, so after I managed to get an application started, I stopped there. It was a good deal of effort to chain together even a proof of concept, and at this point I'd rather learn Typescriptthan keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know... The important point I want to make is that there's a lot unknown about how any of this holds up outside proofs of concept. Things I didn't attempt: TestingPackagingUpdatesLiterally anything related to why I wanted to use Electron in the first place What it Would Take Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an application in production a couple months from now. But at the moment, I'm personally going to stay away. Let's finish with a wishlist then - here are the things that I think need to happen before Electron/WASM/Rust can become a thing: Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet (#7983)Browser API libraries (web-sys and stdweb) need to make sure they can support running in Electron (see module error above)Projects need to stabilize. There's talk of stdweb being turned into a Rust APIon top of web-sys, and percymoving to web-sys, both of which are big changeswasm-bindgen is great, but still in the "move fast and break things" phaseA good "boilerplate" app would dramatically simplify the start-up costs;electron-react-boilerplate comes to mind as a good project to imitateMore blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm doing","keywords":"","version":null},{"title":"Primitives in Rust are weird (and cool)","type":0,"sectionRef":"#","url":"/2018/09/primitives-in-rust-are-weird","content":"","keywords":"","version":null},{"title":"Defining primitives (Java)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#defining-primitives-java","content":" The reason I'm using the name primitive comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special name for some specific types of values: bool char byte short int long float double They are referred to as primitives. And relative to the other bits of Java, they have two unique features. First, they don't have to worry about thebillion-dollar mistake; primitives in Java can never be null. Second: they can't have instance methods. Remember that Rust program from earlier? Java has no idea what to do with it: class Main { public static void main(String[] args) { int x = 8; System.out.println(x.toString()); // Triggers a compiler error } } The error is: Main.java:5: error: int cannot be dereferenced System.out.println(x.toString()); ^ 1 error Specifically, Java's Objectand things that inherit from it are pointers under the hood, and we have to dereference them before the fields and methods they define can be used. In contrast, primitive types are just values - there's nothing to be dereferenced. In memory, they're just a sequence of bits. If we really want, we can turn the int into anInteger and then dereference it, but it's a bit wasteful: class Main { public static void main(String[] args) { int x = 8; Integer y = Integer.valueOf(x); System.out.println(y.toString()); } } This creates the variable y of type Integer (which inherits Object), and at run time we dereference y to locate the toString() function and call it. Rust obviously handles things a bit differently, but we have to dig into the low-level details to see it in action. ","version":null,"tagName":"h2"},{"title":"Low Level Handling of Primitives (C)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#low-level-handling-of-primitives-c","content":" We first need to build a foundation for reading and understanding the assembly code the final answer requires. Let's begin with showing how the C language (and your computer) thinks about "primitive" values in memory: void my_function(int num) {} int main() { int x = 8; my_function(x); } The compiler explorer gives us an easy way of showing off the assembly-level code that's generated: whose output has been lightly edited main: push rbp mov rbp, rsp sub rsp, 16 ; We assign the value `8` to `x` here mov DWORD PTR [rbp-4], 8 ; And copy the bits making up `x` to a location ; `my_function` can access (`edi`) mov eax, DWORD PTR [rbp-4] mov edi, eax ; Call `my_function` and give it control call my_function mov eax, 0 leave ret my_function: push rbp mov rbp, rsp ; Copy the bits out of the pre-determined location (`edi`) ; to somewhere we can use mov DWORD PTR [rbp-4], edi nop pop rbp ret At a really low level of memory, we're copying bits around using the mov instruction; nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C to Rust: fn my_function(x: i32) {} fn main() { let x = 8; my_function(x) } And the assembly generated when we stick it in thecompiler explorer: again, lightly edited example::main: push rax ; Look familiar? We're copying bits to a location for `my_function` ; The compiler just optimizes out holding `x` in memory mov edi, 8 ; Call `my_function` and give it control call example::my_function pop rax ret example::my_function: sub rsp, 4 ; And copying those bits again, just like in C mov dword ptr [rsp], edi add rsp, 4 ret The generated Rust assembly is functionally pretty close to the C assembly: When working with primitives, we're just dealing with bits in memory. In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to dereference. So what exactly is going on with this .to_string() function call? ","version":null,"tagName":"h2"},{"title":"impl primitive (and Python)​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#impl-primitive-and-python","content":" Now it's time to reveal my trap card show the revelation that tied all this together: Rust has implementations for its primitive types. That's right, impl blocks aren't only for structs and traits, primitives get them too. Don't believe me? Check outu32,f64 andchar as examples. But the really interesting bit is how Rust turns those impl blocks into assembly. Let's break out the compiler explorer once again: pub fn main() { 8.to_string() } And the interesting bits in the assembly: heavily trimmed down example::main: sub rsp, 24 mov rdi, rsp lea rax, [rip + .Lbyte_str.u] mov rsi, rax ; Cool stuff right here call <T as alloc::string::ToString>::to_string@PLT mov rdi, rsp call core::ptr::drop_in_place add rsp, 24 ret Now, this assembly is a bit more complicated, but here's the big revelation: we're callingto_string() as a function that exists all on its own, and giving it the instance of 8. Instead of thinking of the value 8 as an instance of u32 and then peeking in to find the location of the function we want to call (like Java), we have a function that exists outside of the instance and just give that function the value 8. This is an incredibly technical detail, but the interesting idea I had was this: if to_string()is a static function, can I refer to the unbound function and give it an instance? Better explained in code (and a compiler explorer link because I seriously love this thing): struct MyVal { x: u32 } impl MyVal { fn to_string(&self) -> String { self.x.to_string() } } pub fn main() { let my_val = MyVal { x: 8 }; // THESE ARE THE SAME my_val.to_string(); MyVal::to_string(&my_val); } Rust is totally fine "binding" the function call to the instance, and also as a static. MIND == BLOWN. Python does the same thing where I can both call functions bound to their instances and also call as an unbound function where I give it the instance: class MyClass(): x = 24 def my_function(self): print(self.x) m = MyClass() m.my_function() MyClass.my_function(m) And Python tries to make you think that primitives can have instance methods... >>> dir(8) ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', ... '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', ...] >>> # Theoretically `8.__str__()` should exist, but: >>> 8.__str__() File "<stdin>", line 1 8.__str__() ^ SyntaxError: invalid syntax >>> # It will run if we assign it first though: >>> x = 8 >>> x.__str__() '8' ...but in practice it's a bit complicated. So while Python handles binding instance methods in a way similar to Rust, it's still not able to run the example we started with. ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Primitives in Rust are weird (and cool)","url":"/2018/09/primitives-in-rust-are-weird#conclusion","content":" This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor details like primitives leads to really cool effects. Primitives are optimized like C in how they have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python (like both instance and late binding). And when you put it together, there are areas where Rust does cool things nobody else can; as a quirky feature of Rust's type system, 8.to_string() is actually valid code. Now go forth and fool your friends into thinking you know assembly. This is all I've got. ","version":null,"tagName":"h2"},{"title":"A case study in heaptrack","type":0,"sectionRef":"#","url":"/2018/10/case-study-optimization","content":"","keywords":"","version":null},{"title":"Curiosity​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#curiosity","content":" When I first started building the dtparse crate, my intention was to mirror as closely as possible the equivalent Python library. Python, as you may know, is garbage collected. Very rarely is memory usage considered in Python, and I likewise wasn't paying too much attention whendtparse was first being built. This lackadaisical approach to memory works well enough, and I'm not planning on making dtparsehyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the advent of Rust 1.28 and theGlobal Allocator trait, I had a really great idea: build a custom allocator that allows you to track your own allocations. That way, you can do things like writing tests for both correct results and correct memory usage. I gave it ashot, but learned very quickly: never write your own allocator. It went from "fun weekend project" to "I have literally no idea what my computer is doing" at breakneck speed. Instead, I'll highlight a separate path I took to make sense of my memory usage: heaptrack. ","version":null,"tagName":"h2"},{"title":"Turning on the System Allocator​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#turning-on-the-system-allocator","content":" This is the hardest part of the post. Because Rust usesits own allocator by default,heaptrack is unable to properly record unmodified Rust code. To remedy this, we'll make use of the#[global_allocator] attribute. Specifically, in lib.rs or main.rs, add this: use std::alloc::System; #[global_allocator] static GLOBAL: System = System; ...and that's it. Everything else comes essentially for free. ","version":null,"tagName":"h2"},{"title":"Running heaptrack​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#running-heaptrack","content":" Assuming you've installed heaptrack (Homebrew in Mac, package manager in Linux, ??? in Windows), all that's left is to fire up your application: heaptrack my_application It's that easy. After the program finishes, you'll see a file in your local directory with a name like heaptrack.my_appplication.XXXX.gz. If you load that up in heaptrack_gui, you'll see something like this: And even these pretty colors: ","version":null,"tagName":"h2"},{"title":"Reading Flamegraphs​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#reading-flamegraphs","content":" To make sense of our memory usage, we're going to focus on that last picture - it's called a"flamegraph". These charts are typically used to show how much time your program spends executing each function, but they're used here to show how much memory was allocated during those functions instead. For example, we can see that all executions happened during the main function: ...and within that, all allocations happened during dtparse::parse: ...and within that, allocations happened in two different places: Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue:what the heck is the Default thing doing? ","version":null,"tagName":"h2"},{"title":"Optimizing dtparse​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#optimizing-dtparse","content":" See, I knew that there were some allocations during calls to dtparse::parse, but I was totally wrong about where the bulk of allocations occurred in my program. Let me post the code and see if you can spot the mistake: /// Main entry point for using `dtparse`. pub fn parse(timestr: &str) -> ParseResult<(NaiveDateTime, Option<FixedOffset>)> { let res = Parser::default().parse( timestr, None, None, false, false, None, false, &HashMap::new(), )?; Ok((res.0, res.1)) } dtparse Because Parser::parse requires a mutable reference to itself, I have to create a newParser::default every time it receives a string. This is excessive! We'd rather have an immutable parser that can be re-used, and avoid allocating memory in the first place. Armed with that information, I put some time in tomake the parser immutable. Now that I can re-use the same parser over and over, the allocations disappear: In total, we went from requiring 2 MB of memory inversion 1.0.2: All the way down to 300KB in version 1.0.3: ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"A case study in heaptrack","url":"/2018/10/case-study-optimization#conclusion","content":" In the end, you don't need to write a custom allocator to be efficient with memory, great tools already exist to help you understand what your program is doing. Use them. Given that Moore's Law isdead, we've all got to do our part to take back what Microsoft stole. ","version":null,"tagName":"h2"},{"title":"QADAPT - debug_assert! for allocations","type":0,"sectionRef":"#","url":"/2018/12/allocation-safety","content":"","keywords":"","version":null},{"title":"Why an Allocator?​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#why-an-allocator","content":" So why, after complaining about allocators, would I still want to write one? There are three reasons for that: Allocation/dropping is slowIt's difficult to know exactly when Rust will allocate or drop, especially when using code that you did not writeI want automated tools to verify behavior, instead of inspecting by hand When I say "slow," it's important to define the terms. If you're writing web applications, you'll spend orders of magnitude more time waiting for the database than you will the allocator. However, there's still plenty of code where micro- or nano-seconds matter; thinkfinance,real-time audio,self-driving cars, andnetworking. In these situations it's simply unacceptable for you to spend time doing things that are not your program, and waiting on the allocator is not cool. As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen. So, I propose we play a quick trivia game: Does this code invoke the allocator? ","version":null,"tagName":"h2"},{"title":"Example 1​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-1","content":" fn my_function() { let v: Vec<u8> = Vec::new(); } No: Rust knows how big the Vec type is, and reserves a fixed amount of memory on the stack for the v vector. However, if we wanted to reserve extra space (using Vec::with_capacity) the allocator would get invoked. ","version":null,"tagName":"h3"},{"title":"Example 2​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-2","content":" fn my_function() { let v: Box<Vec<u8>> = Box::new(Vec::new()); } Yes: Because Boxes allow us to work with things that are of unknown size, it has to allocate on the heap. While the Box is unnecessary in this snippet (release builds will optimize out the allocation), reserving heap space more generally is needed to pass a dynamically sized type to another function. ","version":null,"tagName":"h3"},{"title":"Example 3​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#example-3","content":" fn my_function(v: Vec<u8>) { v.push(5); } Maybe: Depending on whether the Vector we were given has space available, we may or may not allocate. Especially when dealing with code that you did not author, it's difficult to verify that things behave as you expect them to. ","version":null,"tagName":"h3"},{"title":"Blowing Things Up​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#blowing-things-up","content":" So, how exactly does QADAPT solve these problems? Whenever an allocation or drop occurs in code marked allocation-safe, QADAPT triggers a thread panic. We don't want to let the program continue as if nothing strange happened, we want things to explode. However, you don't want code to panic in production because of circumstances you didn't predict. Just like debug_assert!, QADAPT will strip out its own code when building in release mode to guarantee no panics and no performance impact. Finally, there are three ways to have QADAPT check that your code will not invoke the allocator: ","version":null,"tagName":"h2"},{"title":"Using a procedural macro​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-a-procedural-macro","content":" The easiest method, watch an entire function for allocator invocation: use qadapt::no_alloc; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; #[no_alloc] fn push_vec(v: &mut Vec<u8>) { // This triggers a panic if v.len() == v.capacity() v.push(5); } fn main() { let v = Vec::with_capacity(1); // This will *not* trigger a panic push_vec(&v); // This *will* trigger a panic push_vec(&v); } ","version":null,"tagName":"h3"},{"title":"Using a regular macro​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-a-regular-macro","content":" For times when you need more precision: use qadapt::assert_no_alloc; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; fn main() { let v = Vec::with_capacity(1); // No allocations here, we already have space reserved assert_no_alloc!(v.push(5)); // Even though we remove an item, it doesn't trigger a drop // because it's a scalar. If it were a `Box<_>` type, // a drop would trigger. assert_no_alloc!({ v.pop().unwrap(); }); } ","version":null,"tagName":"h3"},{"title":"Using function calls​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#using-function-calls","content":" Both the most precise and most tedious: use qadapt::enter_protected; use qadapt::exit_protected; use qadapt::QADAPT; #[global_allocator] static Q: QADAPT = QADAPT; fn main() { // This triggers an allocation (on non-release builds) let v = Vec::with_capacity(1); enter_protected(); // This does not trigger an allocation because we've reserved size v.push(0); exit_protected(); // This triggers an allocation because we ran out of size, // but doesn't panic because we're no longer protected. v.push(1); } ","version":null,"tagName":"h3"},{"title":"Caveats​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#caveats","content":" It's important to point out that QADAPT code is synchronous, so please be careful when mixing in asynchronous functions: use futures::future::Future; use futures::future::ok; #[no_alloc] fn async_capacity() -> impl Future<Item=Vec<u8>, Error=()> { ok(12).and_then(|e| Ok(Vec::with_capacity(e))) } fn main() { // This doesn't trigger a panic because the `and_then` closure // wasn't run during the function call. async_capacity(); // Still no panic assert_no_alloc!(async_capacity()); // This will panic because the allocation happens during `unwrap` // in the `assert_no_alloc!` macro assert_no_alloc!(async_capacity().poll().unwrap()); } ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"QADAPT - debug_assert! for allocations","url":"/2018/12/allocation-safety#conclusion","content":" While there's a lot more to writing high-performance code than managing your usage of the allocator, it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for most allocators. Version 1.0 was released today, and you can check it out over atcrates.io or on github. I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will help guide that. If there are topics you're interested in, let me know in the comments below! ","version":null,"tagName":"h2"},{"title":"More \"what companies really mean\"","type":0,"sectionRef":"#","url":"/2018/12/what-small-business-really-means","content":"","keywords":"","version":null},{"title":"How do you feel about production support?​","type":1,"pageTitle":"More \"what companies really mean\"","url":"/2018/12/what-small-business-really-means#how-do-you-feel-about-production-support","content":" Translation: We're a fairly small team, and when things break on an evening/weekend/Christmas Day, can we call on you to be there? I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make it out the door before the zombie apocalypse. Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people who either enjoy that, or play along nicely enough that our systems keep working. Small teams have no such luck. If you're interviewing at a small company, especially as a "data scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the most inopportune moments. Terrible-but-popular answers include: It's a part of the job, and I'm happy to contribute. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Compiler optimizations","type":0,"sectionRef":"#","url":"/2019/02/08/compiler-optimizations","content":"","keywords":"","version":null},{"title":"The Case of the Disappearing Box​","type":1,"pageTitle":"Allocations in Rust: Compiler optimizations","url":"/2019/02/08/compiler-optimizations#the-case-of-the-disappearing-box","content":" Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the stack instead! The way this interacts with #[inline] attributes is a bit opaque, but the important part is that LLVM can sometimes do better than the baseline Rust language: use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{AtomicBool, Ordering}; pub fn cmp(x: u32) { // Turn on panicking if we allocate on the heap DO_PANIC.store(true, Ordering::SeqCst); // The compiler is able to see through the constant `Box` // and directly compare `x` to 24 - assembly line 73 let y = Box::new(24); let equals = x == *y; // This call to drop is eliminated drop(y); // Need to mark the comparison result as volatile so that // LLVM doesn't strip out all the code. If `y` is marked // volatile instead, allocation will be forced. unsafe { std::ptr::read_volatile(&equals) }; // Turn off panicking, as there are some deallocations // when we exit main. DO_PANIC.store(false, Ordering::SeqCst); } fn main() { cmp(12) } #[global_allocator] static A: PanicAllocator = PanicAllocator; static DO_PANIC: AtomicBool = AtomicBool::new(false); struct PanicAllocator; unsafe impl GlobalAlloc for PanicAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected allocation."); } System.alloc(layout) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected deallocation."); } System.dealloc(ptr, layout); } } -- Compiler Explorer -- Rust Playground ","version":null,"tagName":"h2"},{"title":"Dr. Array or: how I learned to love the optimizer​","type":1,"pageTitle":"Allocations in Rust: Compiler optimizations","url":"/2019/02/08/compiler-optimizations#dr-array-or-how-i-learned-to-love-the-optimizer","content":" Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if you're not careful, they can make your benchmarks lookimpossibly good. In Rust, theblack_box function (implemented in bothlibtest andcriterion) will tell the compiler to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up running programs that previously caused errors: #[derive(Default)] struct TwoFiftySix { _a: [u64; 32] } #[derive(Default)] struct EightK { _a: [TwoFiftySix; 32] } #[derive(Default)] struct TwoFiftySixK { _a: [EightK; 32] } #[derive(Default)] struct EightM { _a: [TwoFiftySixK; 32] } pub fn main() { // Normally this blows up because we can't reserve size on stack // for the `EightM` struct. But because the compiler notices we // never do anything with `_x`, it optimizes out the stack storage // and the program completes successfully. let _x = EightM::default(); } -- Compiler Explorer -- Rust Playground ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Dynamic memory","type":0,"sectionRef":"#","url":"/2019/02/a-heaping-helping","content":"","keywords":"","version":null},{"title":"Smart pointers​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#smart-pointers","content":" The first thing to note are the "smart pointer" types. When you have data that must outlive the scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these types. The term smart pointer comes from C++, and while it's closely linked to a general design pattern of"Resource Acquisition Is Initialization", we'll use it here specifically to describe objects that are responsible for managing ownership of data allocated on the heap. The smart pointers available in the alloc crate should look mostly familiar: BoxRcArcCow The standard library also defines some smart pointers to manage heap objects, though more than can be covered here. Some examples are: RwLockMutex Finally, there is one "gotcha": cell types(like RefCell) look and behave similarly, but don't involve heap allocation. Thecore::cell docs have more information. When a smart pointer is created, the data it is given is placed in heap memory and the location of that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to deallocate that memory (when a Box hasgone out of scope or a reference countgoes to zero), the heap space is reclaimed. We can prove these types use heap memory by looking at code: use std::rc::Rc; use std::sync::Arc; use std::borrow::Cow; pub fn my_box() { // Drop at assembly line 1640 Box::new(0); } pub fn my_rc() { // Drop at assembly line 1650 Rc::new(0); } pub fn my_arc() { // Drop at assembly line 1660 Arc::new(0); } pub fn my_cow() { // Drop at assembly line 1672 Cow::from("drop"); } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Collections​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#collections","content":" Collection types use heap memory because their contents have dynamic size; they will request more memory when needed, and canrelease memory when it's no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In a way, collections are smart pointers for many objects at a time. Common types that fall under this umbrella are Vec,HashMap, andString (notstr). While collections store the objects they own in heap memory, creating new collections will not allocate on the heap. This is a bit weird; if we call Vec::new(), the assembly shows a corresponding call to real_drop_in_place: pub fn my_vec() { // Drop in place at line 481 Vec::<u8>::new(); } -- Compiler Explorer But because the vector has no elements to manage, no calls to the allocator will ever be dispatched: use std::alloc::{GlobalAlloc, Layout, System}; use std::sync::atomic::{AtomicBool, Ordering}; fn main() { // Turn on panicking if we allocate on the heap DO_PANIC.store(true, Ordering::SeqCst); // Interesting bit happens here let x: Vec<u8> = Vec::new(); drop(x); // Turn panicking back off, some deallocations occur // after main as well. DO_PANIC.store(false, Ordering::SeqCst); } #[global_allocator] static A: PanicAllocator = PanicAllocator; static DO_PANIC: AtomicBool = AtomicBool::new(false); struct PanicAllocator; unsafe impl GlobalAlloc for PanicAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected allocation."); } System.alloc(layout) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { if DO_PANIC.load(Ordering::SeqCst) { panic!("Unexpected deallocation."); } System.dealloc(ptr, layout); } } --Rust Playground Other standard library types follow the same behavior; make sure to check outHashMap::new(), and String::new(). ","version":null,"tagName":"h2"},{"title":"Heap Alternatives​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#heap-alternatives","content":" While it is a bit strange to speak of the stack after spending time with the heap, it's worth pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by other crates. If you have need of the functionality, but want to avoid allocating, there are typically alternatives available. When it comes to some standard library smart pointers (RwLock andMutex), stack-based alternatives are provided in crates like parking_lot andspin. You can check outlock_api::RwLock,lock_api::Mutex, andspin::Once if you're in need of synchronization primitives. thread_id may be necessary if you're implementing an allocator because thread::current().id() uses athread_local! structurethat needs heap allocation. ","version":null,"tagName":"h2"},{"title":"Tracing Allocators​","type":1,"pageTitle":"Allocations in Rust: Dynamic memory","url":"/2019/02/a-heaping-helping#tracing-allocators","content":" When writing performance-sensitive code, there's no alternative to measuring your code. If you didn't write a benchmark,you don't care about it's performanceYou should never rely on your instincts whena microsecond is an eternity. Similarly, there's great work going on in Rust with allocators that keep track of what they're doing (like alloc_counter). When it comes to tracking heap behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard against future issues. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Summary","type":0,"sectionRef":"#","url":"/2019/02/summary","content":"While there's a lot of interesting detail captured in this series, it's often helpful to have a document that answers some "yes/no" questions. You may not care about what an Iterator looks like in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust will prioritize the fastest behavior it can, here are the rules for each memory type: Global Allocation: const is a fixed value; the compiler is allowed to copy it wherever useful.static is a fixed reference; the compiler will guarantee it is unique. Stack Allocation: Everything not using a smart pointer will be allocated on the stack.Structs, enums, iterators, arrays, and closures are all stack allocated.Cell types (RefCell) behave like smart pointers, but are stack-allocated.Inlining (#[inline]) will not affect allocation behavior for better or worse.Types that are marked Copy are guaranteed to have their contents stack-allocated. Heap Allocation: Smart pointers (Box, Rc, Mutex, etc.) allocate their contents in heap memory.Collections (HashMap, Vec, String, etc.) allocate their contents in heap memory.Some smart pointers in the standard library have counterparts in other crates that don't need heap memory. If possible, use those. -- Raph Levien","keywords":"","version":null},{"title":"Allocations in Rust: Foreword","type":0,"sectionRef":"#","url":"/2019/02/understanding-allocations-in-rust","content":"There's an alchemy of distilling complex technical topics into articles and videos that change the way programmers see the tools they interact with on a regular basis. I knew what a linker was, but there's a staggering amount of complexity in betweenthe OS and main(). Rust programmers use theBox type all the time, but there's a rich history of the Rust language itself wrapped up inhow special it is. In a similar vein, this series attempts to look at code and understand how memory is used; the complex choreography of operating system, compiler, and program that frees you to focus on functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the cognitive burden associated with memory management, but we're going to step into its world for a while. Let's learn a bit about memory in Rust. Rust's three defining features ofPerformance, Reliability, and Productivity are all driven to a great degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java, Python), Rustdoesn't reallygarbage collect; instead, it uses anownership system to reason about how long objects will last in your program. In some cases, if the life of an object is fairly transient, Rust can make use of a very fast region called the "stack." When that's not possible, Rust usesdynamic (heap) memoryand the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it is important to have available. That said, there are specific situations in Rust where you'd never need to worry about the stack/heap distinction! If you: Never use unsafeNever use #![feature(alloc)] or the alloc crate ...then it's not possible for you to use dynamic memory! For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited memory, and the program binary size itself may significantly affect what's available! There's no operating system able to manage this"virtual memory" thing, but that's not an issue because there's only one running application. Theembedonomicon is ever in mind, and interacting with the "real world" through extra peripherals is accomplished by reading and writing to specific memory addresses. Most Rust programs find these requirements overly burdensome though. C++ developers would struggle without access to std::vector (except those hardcore no-STL people), and Rust developers would struggle withoutstd::vec. But with the constraints above,std::vec is actually a part of thealloc crate, and thus off-limits. Box,Rc, etc., are also unusable for the same reason. Whether writing code for embedded devices or not, the important thing in both situations is how much you know before your application starts about what its memory usage will look like. In embedded devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how largegoogle.com's home page is until you start trying to download it. The compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code runs faster when the compiler can guarantee exactly how much memory your program needs while it's running. This series is all about understanding how the compiler reasons about your program, with an emphasis on the implications for performance. Now let's address some conditions and caveats before going much further: We'll focus on "safe" Rust only; unsafe lets you use platform-specific allocation API's (malloc) that we'll ignore.We'll assume a "debug" build of Rust code (what you get with cargo run and cargo test) and address (pun intended) release mode at the end (cargo run --release and cargo test --release).All content will be run using Rust 1.32, as that's the highest currently supported in theCompiler Exporer. As such, we'll avoid upcoming innovations likecompile-time evaluation of staticthat are available in nightly.Because of the nature of the content, being able to read assembly is helpful. We'll keep it simple, but I found arefresher on the push and popinstructions was helpful while writing this.I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are available, but if there's something said in error it will be corrected expeditiously. Please let me know at bradlee@speice.io Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth repeating: Rust does not currently have a rigorously and formally defined memory model. -- the docs","keywords":"","version":null},{"title":"Making bread","type":0,"sectionRef":"#","url":"/2019/05/making-bread","content":"Having recently started my "gardening leave" between positions, I have some more personal time available. I'm planning to stay productive, contributing to some open-source projects, but it also occurred to me that despite talking about bread pics, this blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites and Bytes"? Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on some lighter material. I recently learned two critically important lessons: first, the temperature of the dough when you put the yeast in makes a huge difference. Previously, when I wasn't paying attention to dough temperature: Compared with what happens when I put the dough in the microwave for a defrost cycle because the water I used wasn't warm enough: I mean, just look at the bubbles! After shaping the dough, I've got two loaves ready: Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot to add the water and learned my second lesson: never add room-temperature water to a glass dish that's currently at 500 degrees. Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected to be doing during my garden leave. In the end, the bread crust wasn't great, but the bread itself turned out pretty alright: I've been writing a lot more during this break, so I'm looking forward to sharing that in the future. In the mean-time, I'm planning on making a sandwich.","keywords":"","version":null},{"title":"Binary format shootout","type":0,"sectionRef":"#","url":"/2019/09/binary-format-shootout","content":"","keywords":"","version":null},{"title":"Prologue: Binary Parsing with Nom​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#prologue-binary-parsing-with-nom","content":" Our benchmark system will be a simple data processor; given depth-of-book market data fromIEX, serialize each message into the schema format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices. This test isn't complex, but is representative of the project I need a binary format for. But before we make it to that point, we have to actually read in the market data. To do so, I'm using a library called nom. Version 5.0 was recently released and brought some big changes, so this was an opportunity to build a non-trivial program and get familiar. If you don't already know about nom, it's a "parser generator". By combining different smaller parsers, you can assemble a parser to handle complex structures without writing tedious code by hand. For example, when parsingPCAP files: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +---------------------------------------------------------------+ 0 | Block Type = 0x00000006 | +---------------------------------------------------------------+ 4 | Block Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 | Interface ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 | Timestamp (High) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 | Timestamp (Low) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 | Captured Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 | Packet Len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Packet Data | | ... | ...you can build a parser in nom that looks likethis: const ENHANCED_PACKET: [u8; 4] = [0x06, 0x00, 0x00, 0x00]; pub fn enhanced_packet_block(input: &[u8]) -> IResult<&[u8], &[u8]> { let ( remaining, ( block_type, block_len, interface_id, timestamp_high, timestamp_low, captured_len, packet_len, ), ) = tuple(( tag(ENHANCED_PACKET), le_u32, le_u32, le_u32, le_u32, le_u32, le_u32, ))(input)?; let (remaining, packet_data) = take(captured_len)(remaining)?; Ok((remaining, packet_data)) } While this example isn't too interesting, more complex formats (like IEX market data) are wherenom really shines. Ultimately, because the nom code in this shootout was the same for all formats, we're not too interested in its performance. Still, it's worth mentioning that building the market data parser was actually fun; I didn't have to write tons of boring code by hand. ","version":null,"tagName":"h2"},{"title":"Cap'n Proto​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#capn-proto","content":" Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried because of how long it has supported Rust (thanks to dwrensha for maintaining the Rust port since2014!). However, I had a ton of performance concerns once I started using it. To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the heap to hold the message content, but because builderscan't be re-used, we have to allocate a new buffer for every single message. I was able to work around this with aspecial builderthat could re-use the buffer, but it required reading through Cap'n Proto'sbenchmarksto find an example, and usedstd::mem::transmute to bypass Rust's borrow checker. The process of reading messages was better, but still had issues. Cap'n Proto has two message encodings: a "packed" representation, and an "unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n Proto shines; its main selling point is that there's no decoding step. However, accomplishing zero-copy deserialization required code in the private API (since fixed), and we allocate a vector on every read for the segment table. In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too many issues for me to feel comfortable using it long-term. ","version":null,"tagName":"h2"},{"title":"Flatbuffers​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#flatbuffers","content":" This is the new kid on the block. After afirst attempt didn't pan out, official support was recently launched. Flatbuffers intends to address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The difference is that Flatbuffers claims to have a simpler wire format andmore flexibility. On the whole, I enjoyed using Flatbuffers; the tooling is nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However, there were still some issues. First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats like the following: table Message { symbol: string; } table MultiMessage { messages:[Message]; } We want to create a MultiMessage which contains a vector of Message, and each Message itself contains a vector (the string type). I was able to work around this bycaching Message elementsin a SmallVec before building the final MultiMessage, but it was a painful process that I believe contributed to poor serialization performance. Second, streaming support in Flatbuffers seems to be something of anafterthought. Where Cap'n Proto in Rust handles reading messages from a stream as part of the API, Flatbuffers just sticks a u32 at the front of each message to indicate the size. Not specifically a problem, but calculating message size without that tag is nigh on impossible. Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform well. ","version":null,"tagName":"h2"},{"title":"Simple Binary Encoding​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#simple-binary-encoding","content":" Support for SBE was added by the author of one of my favoriteRust blog posts. I've talked previously about how important variance is in high-performance systems, so it was encouraging to read about a format thatdirectly addressed my concerns. SBE has by far the simplest binary format, but it does make some tradeoffs. Both Cap'n Proto and Flatbuffers use message offsetsto handle variable-length data, unions, and various other features. In contrast, messages in SBE are essentiallyjust structs; variable-length data is supported, but there's no union type. As mentioned in the beginning, the Rust port of SBE works well, but isessentially unmaintained. However, if you don't need union types, and can accept that schemas are XML documents, it's still worth using. SBE's implementation had the best streaming support of all formats I tested, and doesn't trigger allocation during de/serialization. ","version":null,"tagName":"h2"},{"title":"Results​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#results","content":" After building a test harnessforeachformat, it was time to actually take them for a spin. I usedthis script to run the benchmarks, and the raw results arehere. All data reported below is the average of 10 runs on a single day of IEX data. Results were validated to make sure that each format parsed the data correctly. ","version":null,"tagName":"h2"},{"title":"Serialization​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#serialization","content":" This test measures, on aper-message basis, how long it takes to serialize the IEX message into the desired format and write to a pre-allocated buffer. Schema\tMedian\t99th Pctl\t99.9th Pctl\tTotalCap'n Proto Packed\t413ns\t1751ns\t2943ns\t14.80s Cap'n Proto Unpacked\t273ns\t1828ns\t2836ns\t10.65s Flatbuffers\t355ns\t2185ns\t3497ns\t14.31s SBE\t91ns\t1535ns\t2423ns\t3.91s ","version":null,"tagName":"h3"},{"title":"Deserialization​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#deserialization","content":" This test measures, on aper-message basis, how long it takes to read the previously-serialized message and perform some basic aggregation. The aggregation code is the same for each format, so any performance differences are due solely to the format implementation. Schema\tMedian\t99th Pctl\t99.9th Pctl\tTotalCap'n Proto Packed\t539ns\t1216ns\t2599ns\t18.92s Cap'n Proto Unpacked\t366ns\t737ns\t1583ns\t12.32s Flatbuffers\t173ns\t421ns\t1007ns\t6.00s SBE\t116ns\t286ns\t659ns\t4.05s ","version":null,"tagName":"h3"},{"title":"Conclusion​","type":1,"pageTitle":"Binary format shootout","url":"/2019/09/binary-format-shootout#conclusion","content":" Building a benchmark turned out to be incredibly helpful in making a decision; because a "union" type isn't important to me, I can be confident that SBE best addresses my needs. While SBE was the fastest in terms of both median and worst-case performance, its worst case performance was proportionately far higher than any other format. It seems to be that de/serialization time scales with message size, but I'll need to do some more research to understand what exactly is going on. ","version":null,"tagName":"h2"},{"title":"On building high performance systems","type":0,"sectionRef":"#","url":"/2019/06/high-performance-systems","content":"","keywords":"","version":null},{"title":"Language-specific​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#language-specific","content":" Garbage Collection: How often does garbage collection happen? When is it triggered? What are the impacts? In Python, individual objects are collected if the reference count reaches 0, and each generation is collected ifnum_alloc - num_dealloc > gc_threshold whenever an allocation happens. The GIL is acquired for the duration of generational collection.Java hasmanydifferentcollectionalgorithmsto choose from, each with different characteristics. The default algorithms (Parallel GC in Java 8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms (ZGC andShenandoah) are designed to keep "stop the world" to a minimum by doing collection work in parallel. Allocation: Every language has a different way of interacting with "heap" memory, but the principle is the same: running the allocator to allocate/deallocate memory takes time that can often be put to better use. Understanding when your language interacts with the allocator is crucial, and not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java does (meaning potential GC pauses). Take time to understand heap behavior (I made aa guide for Rust), and look into alternative allocators (jemalloc,tcmalloc) that might run faster than the operating system default. Data Layout: How your data is arranged in memory matters;data-oriented design andcache locality can have huge impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't make. Cachegrind and kernelperf counters are both great for understanding how performance relates to memory layout. Just-In-Time Compilation: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are great because they optimize your program for how it's actually being used, rather than how a compiler expects it to be used. However, there's a variance problem if the program stops executing while waiting for translation from VM bytecode to native code. As a remedy, many languages support ahead-of-time compilation in addition to the JIT versions (CoreRT in C# and GraalVM in Java). On the other hand, LLVM supportsProfile Guided Optimization, which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT compiler kicked in. Programming Tricks: These won't make or break performance, but can be useful in specific circumstances. For example, C++ can usetemplates instead of branchesin critical sections. ","version":null,"tagName":"h2"},{"title":"Kernel​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#kernel","content":" Code you wrote is almost certainly not the only code running on your hardware. There are many ways the operating system interacts with your program, from interrupts to system calls, that are important to watch for. These are written from a Linux perspective, but Windows does typically have equivalent functionality. Scheduling: The kernel is normally free to schedule any process on any core, so it's important to reserve CPU cores exclusively for the important programs. There are a few parts to this: first, limit the CPU cores that non-critical processes are allowed to run on by excluding cores from scheduling (isolcpuskernel command-line option), or by setting the init process CPU affinity (systemd example). Second, set critical processes to run on the isolated cores by setting theprocessor affinity usingtaskset. Finally, useNO_HZ orchrt to disable scheduling interrupts. Turning off hyper-threading is also likely beneficial. System calls: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long the I/O operation takes, these all trigger expensivesystem calls (syscalls). To handle these, the CPU mustcontext switch to the kernel, let the kernel operation complete, then context switch back to your program. We'd rather keep theseto a minimum (see timestamp 18:20). Strace is your friend for understanding when and where syscalls happen. Signal Handling: Far less likely to be an issue, but signals do trigger a context switch if your code has a handler registered. This will be highly dependent on the application, but you canblock signalsif it's an issue. Interrupts: System interrupts are how devices connected to your computer notify the CPU that something has happened. The CPU will then choose a processor core to pause and context switch to the OS to handle the interrupt. Make sure thatSMP affinity is set so that interrupts are handled on a CPU core not running the program you care about. NUMA: While NUMA is good at making multi-cell systems transparent, there are variance implications; if the kernel moves a process across nodes, future memory accesses must wait for the controller on the original node. Usenumactl to handle memory-/cpu-cell pinning so this doesn't happen. ","version":null,"tagName":"h2"},{"title":"Hardware​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#hardware","content":" CPU Pipelining/Speculation: Speculative execution in modern processors gave us vulnerabilities like Spectre, but it also gave us performance improvements likebranch prediction. And if the CPU mis-speculates your code, there's variance associated with rewind and replay. While the compiler knows a lot about how your CPU pipelines instructions, code can bestructured to help the branch predictor. Paging: For most systems, virtual memory is incredible. Applications live in their own worlds, and the CPU/MMU figures out the details. However, there's a variance penalty associated with memory paging and caching; if you access more memory pages than the TLB can store, you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an issue, but using huge pages can reduce TLB burdens. Alternately, running applications in a hypervisor likeJailhouse allows one to skip virtual memory entirely, but this is probably more work than the benefits are worth. Network Interfaces: When more than one computer is involved, variance can go up dramatically. Tuning kernelnetwork parameters may be helpful, but modern systems more frequently opt to skip the kernel altogether with a technique called kernel bypass. This typically requires specialized hardware and drivers, but even industries liketelecom are finding the benefits. ","version":null,"tagName":"h2"},{"title":"Networks​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#networks","content":" Routing: There's a reason financial firms are willing to paymillions of eurosfor rights to a small plot of land - having a straight-line connection from point A to point B means the path their data takes is the shortest possible. In contrast, there are currently 6 computers in between me and Google, but that may change at any moment if my ISP realizes amore efficient route is available. Whether it's usingresearch-quality equipmentfor shortwave radio, or just making sure there's no data inadvertently going between data centers, routing matters. Protocol: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control, and congestion control all built in. But these attributes make the most sense when networking infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may make sense in these contexts as it avoids the chatter needed to track connection state, andgap-fillstrategiescan handle the rest. Switching: Many routers/switches handle packets using "store-and-forward" behavior: wait for the whole packet, validate checksums, and then send to the next device. In variance terms, the time needed to move data between two nodes is proportional to the size of that data; the switch must "store" all data before it can calculate checksums and "forward" to the next node. With"cut-through"designs, switches will begin forwarding data as soon as they know where the destination is, checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter the size. ","version":null,"tagName":"h2"},{"title":"Final Thoughts​","type":1,"pageTitle":"On building high performance systems","url":"/2019/06/high-performance-systems#final-thoughts","content":" High-performance systems, regardless of industry, are not magical. They do require extreme precision and attention to detail, but they're designed, built, and operated by regular people, using a lot of tools that are publicly available. Interested in seeing how context switching affects performance of your benchmarks? taskset should be installed in all modern Linux distributions, and can be used to make sure the OS never migrates your process. Curious how often garbage collection triggers during a crucial operation? Your language of choice will typically expose details of its operations (Python,Java). Want to know how hard your program is stressing the TLB? Use perf record and look fordtlb_load_misses.miss_causes_a_walk. Two final guiding questions, then: first, before attempting to apply some of the technology above to your own systems, can you first identifywhere/when you care about "high-performance"? As an example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are they being designed in a way that's actually helpful? Tools likeCriterion (also inRust) and Google'sBenchmark output not only average run time, but variance as well; your benchmarking environment is subject to the same concerns your production environment is. Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique. Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate it; once that's at an acceptable level, then optimize for speed. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Global memory","type":0,"sectionRef":"#","url":"/2019/02/the-whole-world","content":"","keywords":"","version":null},{"title":"const values​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#const-values","content":" When a value is guaranteed to be unchanging in your program (where "value" may be scalars,structs, etc.), you can declare it const. This tells the compiler that it's safe to treat the value as never changing, and enables some interesting optimizations; not only is there no initialization cost to creating the value (it is loaded at the same time as the executable parts of your program), but the compiler can also copy the value around if it speeds up the code. The points we need to address when talking about const are: Const values are stored in read-only memory - it's impossible to modify.Values resulting from calling a const fn are materialized at compile-time.The compiler may (or may not) copy const values wherever it chooses. ","version":null,"tagName":"h2"},{"title":"Read-Only​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#read-only","content":" The first point is a bit strange - "read-only memory."The Rust bookmentions in a couple places that using mut with constants is illegal, but it's also important to demonstrate just how immutable they are. Typically in Rust you can useinterior mutability to modify things that aren't declared mut.RefCell provides an example of this pattern in action: use std::cell::RefCell; fn my_mutator(cell: &RefCell<u8>) { // Even though we're given an immutable reference, // the `replace` method allows us to modify the inner value. cell.replace(14); } fn main() { let cell = RefCell::new(25); // Prints out 25 println!("Cell: {:?}", cell); my_mutator(&cell); // Prints out 14 println!("Cell: {:?}", cell); } --Rust Playground When const is involved though, interior mutability is impossible: use std::cell::RefCell; const CELL: RefCell<u8> = RefCell::new(25); fn my_mutator(cell: &RefCell<u8>) { cell.replace(14); } fn main() { // First line prints 25 as expected println!("Cell: {:?}", &CELL); my_mutator(&CELL); // Second line *still* prints 25 println!("Cell: {:?}", &CELL); } --Rust Playground And a second example using Once: use std::sync::Once; const SURPRISE: Once = Once::new(); fn main() { // This is how `Once` is supposed to be used SURPRISE.call_once(|| println!("Initializing...")); // Because `Once` is a `const` value, we never record it // having been initialized the first time, and this closure // will also execute. SURPRISE.call_once(|| println!("Initializing again???")); } --Rust Playground When theconst specificationrefers to "rvalues", this behavior is what they refer to. Clippy will treat this as an error, but it's still something to be aware of. ","version":null,"tagName":"h3"},{"title":"Initialization​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#initialization","content":" The next thing to mention is that const values are loaded into memory as part of your program binary. Because of this, any const values declared in your program will be "realized" at compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may be able to prefetch the value), but that's it. use std::cell::RefCell; const CELL: RefCell<u32> = RefCell::new(24); pub fn multiply(value: u32) -> u32 { // CELL is stored at `.L__unnamed_1` value * (*CELL.get_mut()) } -- Compiler Explorer The compiler creates one RefCell, uses it everywhere, and never needs to call the RefCell::newfunction. ","version":null,"tagName":"h3"},{"title":"Copying​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#copying","content":" If it's helpful though, the compiler can choose to copy const values. const FACTOR: u32 = 1000; pub fn multiply(value: u32) -> u32 { // See assembly line 4 for the `mov edi, 1000` instruction value * FACTOR } pub fn multiply_twice(value: u32) -> u32 { // See assembly lines 22 and 29 for `mov edi, 1000` instructions value * FACTOR * FACTOR } -- Compiler Explorer In this example, the FACTOR value is turned into the mov edi, 1000 instruction in both themultiply and multiply_twice functions; the "1000" value is never "stored" anywhere, as it's small enough to inline into the assembly instructions. Finally, getting the address of a const value is possible, but not guaranteed to be unique (because the compiler can choose to copy values). I was unable to get non-unique pointers in my testing (even using different crates), but the specifications are clear enough: don't rely on pointers to const values being consistent. To be frank, caring about locations for const values is almost certainly a code smell. ","version":null,"tagName":"h3"},{"title":"static values​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#static-values","content":" Static variables are related to const variables, but take a slightly different approach. When we declare that a reference is unique for the life of a program, you have a static variable (unrelated to the 'static lifetime). Because of the reference/value distinction withconst/static, static variables behave much more like typical "global" variables. But to understand static, here's what we'll look at: static variables are globally unique locations in memory.Like const, static variables are loaded at the same time as your program being read into memory.All static variables must implement theSync marker trait.Interior mutability is safe and acceptable when using static variables. ","version":null,"tagName":"h2"},{"title":"Memory Uniqueness​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#memory-uniqueness","content":" The single biggest difference between const and static is the guarantees provided about uniqueness. Where const variables may or may not be copied in code, static variables are guarantee to be unique. If we take a previous const example and change it to static, the difference should be clear: static FACTOR: u32 = 1000; pub fn multiply(value: u32) -> u32 { // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used value * FACTOR } pub fn multiply_twice(value: u32) -> u32 { // The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used value * FACTOR * FACTOR } -- Compiler Explorer Where previously there were plenty of references to multiplying by 1000, the new assembly refers to FACTOR as a named memory location instead. No initialization work needs to be done, but the compiler can no longer prove the value never changes during execution. ","version":null,"tagName":"h3"},{"title":"Initialization​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#initialization-1","content":" Next, let's talk about initialization. The simplest case is initializing static variables with either scalar or struct notation: #[derive(Debug)] struct MyStruct { x: u32 } static MY_STRUCT: MyStruct = MyStruct { // You can even reference other statics // declared later x: MY_VAL }; static MY_VAL: u32 = 24; fn main() { println!("Static MyStruct: {:?}", MY_STRUCT); } --Rust Playground Things can get a bit weirder when using const fn though. In most cases, it just works: #[derive(Debug)] struct MyStruct { x: u32 } impl MyStruct { const fn new() -> MyStruct { MyStruct { x: 24 } } } static MY_STRUCT: MyStruct = MyStruct::new(); fn main() { println!("const fn Static MyStruct: {:?}", MY_STRUCT); } --Rust Playground However, there's a caveat: you're currently not allowed to use const fn to initialize static variables of types that aren't marked Sync. For example,RefCell::new() is aconst fn, but becauseRefCell isn't Sync, you'll get an error at compile time: use std::cell::RefCell; // error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely static MY_LOCK: RefCell<u8> = RefCell::new(0); --Rust Playground It's likely that this willchange in the future though. ","version":null,"tagName":"h3"},{"title":"The Sync marker​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#the-sync-marker","content":" Which leads well to the next point: static variable types must implement theSync marker. Because they're globally unique, it must be safe for you to access static variables from any thread at any time. Moststruct definitions automatically implement the Sync trait because they contain only elements which themselves implement Sync (read more in theNomicon). This is why earlier examples could get away with initializing statics, even though we never included an impl Sync for MyStruct in the code. To demonstrate this property, Rust refuses to compile our earlier example if we add a non-Sync element to the struct definition: use std::cell::RefCell; struct MyStruct { x: u32, y: RefCell<u8>, } // error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely static MY_STRUCT: MyStruct = MyStruct { x: 8, y: RefCell::new(8) }; --Rust Playground ","version":null,"tagName":"h3"},{"title":"Interior mutability​","type":1,"pageTitle":"Allocations in Rust: Global memory","url":"/2019/02/the-whole-world#interior-mutability","content":" Finally, while static mut variables are allowed, mutating them is an unsafe operation. If we want to stay in safe Rust, we can use interior mutability to accomplish similar goals: use std::sync::Once; // This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once static INIT: Once = Once::new(); fn main() { // Note that while `INIT` is declared immutable, we're still allowed // to mutate its interior INIT.call_once(|| println!("Initializing...")); // This code won't panic, as the interior of INIT was modified // as part of the previous `call_once` INIT.call_once(|| panic!("INIT was called twice!")); } --Rust Playground ","version":null,"tagName":"h3"},{"title":"Release the GIL","type":0,"sectionRef":"#","url":"/2019/12/release-the-gil","content":"","keywords":"","version":null},{"title":"Cython​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#cython","content":" Put simply, Cython is a programming language that looks a lot like Python, gets transpiled to C/C++, and integrates well with the CPython API. It's great for building Python wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And when it comes to managing the GIL, there are two special features: The nogilfunction annotationasserts that a Cython function is safe to use without the GIL, and compilation will fail if it interacts with Python in an unsafe mannerThe with nogilcontext managerexplicitly unlocks the CPython GIL while active Whenever Cython code runs inside a with nogil block on a separate thread, the Python interpreter is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that demonstrates this principle in action: %%cython # Annotating a function with `nogil` indicates only that it is safe # to call in a `with nogil` block. It *does not* release the GIL. cdef unsigned long fibonacci(unsigned long n) nogil: if n <= 1: return n cdef unsigned long a = 0, b = 1, c = 0 c = a + b for _i in range(2, n): a = b b = c c = a + b return c def cython_nogil(unsigned long n): # Explicitly release the GIL while running `fibonacci` with nogil: value = fibonacci(n) return value def cython_gil(unsigned long n): # Because the GIL is not explicitly released, it implicitly # remains acquired when running the `fibonacci` function return fibonacci(n) First, let's time how long it takes Cython to calculate the billionth Fibonacci number: %%time _ = cython_gil(N); CPU times: user 365 ms, sys: 0 ns, total: 365 ms Wall time: 372 ms %%time _ = cython_nogil(N); CPU times: user 381 ms, sys: 0 ns, total: 381 ms Wall time: 388 ms Both versions (with and without GIL) take effectively the same amount of time to run. Even when running this calculation in parallel on separate threads, it is expected that the run time will double because only one thread can be active at a time: %%time from threading import Thread # Create the two threads to run on t1 = Thread(target=cython_gil, args=[N]) t2 = Thread(target=cython_gil, args=[N]) # Start the threads t1.start(); t2.start() # Wait for the threads to finish t1.join(); t2.join() CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms Wall time: 645 ms However, if the first thread releases the GIL, the second thread is free to acquire it and run in parallel: %%time t1 = Thread(target=cython_nogil, args=[N]) t2 = Thread(target=cython_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 717 ms, sys: 372 µs, total: 718 ms Wall time: 358 ms Because user time represents the sum of processing time on all threads, it doesn't change much. The "wall time" has been cut roughly in half because each function is running simultaneously. Keep in mind that the order in which threads are started makes a difference! %%time # Note that the GIL-locked version is started first t1 = Thread(target=cython_gil, args=[N]) t2 = Thread(target=cython_nogil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 667 ms, sys: 0 ns, total: 667 ms Wall time: 672 ms Even though the second thread releases the GIL while running, it can't start until the first has completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads. Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash theinterpreter, not just the thread attempting the unlock: %%cython cdef int cython_recurse(int n) nogil: if n <= 0: return 0 with nogil: return cython_recurse(n - 1) cython_recurse(2) Fatal Python error: PyEval_SaveThread: NULL tstate Thread 0x00007f499effd700 (most recent call first): File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap In practice, avoiding this issue is simple. First, nogil functions probably shouldn't containwith nogil blocks. Second, Cython canconditionally acquire/releasethe GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation forexternal C codecontains more detail on how to safely manage the GIL. To conclude: use Cython's nogil annotation to assert that functions are safe for calling when the GIL is unlocked, and with nogil to actually unlock the GIL and run those functions. ","version":null,"tagName":"h2"},{"title":"Numba​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#numba","content":" Like Cython, Numba is a "compiled Python." Where Cython works by compiling a Python-like language to C/C++, Numba compiles Python bytecode directly to machine codeat runtime. Behavior is controlled with a special @jit decorator; calling a decorated function first compiles it to machine code before running. Calling the function a second time re-uses that machine code unless the argument types have changed. Numba works best when a nopython=True argument is added to the @jit decorator; functions compiled in nopython mode avoid the CPython API and have performance comparable to C. Further, adding nogil=True to the@jit decorator unlocks the GIL while that function is running. Note that nogil and nopythonare separate arguments; while it is necessary for code to be compiled in nopython mode in order to release the lock, the GIL will remain locked if nogil=False (the default). Let's repeat the same experiment, this time using Numba instead of Cython: # The `int` type annotation is only for humans and is ignored # by Numba. @jit(nopython=True, nogil=True) def numba_nogil(n: int) -> int: if n <= 1: return n a = 0 b = 1 c = a + b for _i in range(2, n): a = b b = c c = a + b return c # Run using `nopython` mode to receive a performance boost, # but GIL remains locked due to `nogil=False` by default. @jit(nopython=True) def numba_gil(n: int) -> int: if n <= 1: return n a = 0 b = 1 c = a + b for _i in range(2, n): a = b b = c c = a + b return c # Call each function once to force compilation; we don't want # the timing statistics to include how long it takes to compile. numba_nogil(N) numba_gil(N); We'll perform the same tests as above; first, figure out how long it takes the function to run: %%time _ = numba_gil(N) CPU times: user 253 ms, sys: 258 µs, total: 253 ms Wall time: 251 ms Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be effectively identical after compilation. When running two GIL-locked threads, the result (as expected) takes around twice as long to compute: %%time t1 = Thread(target=numba_gil, args=[N]) t2 = Thread(target=numba_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms Wall time: 541 ms But if the GIL-unlocking thread starts first, both threads run in parallel: %%time t1 = Thread(target=numba_nogil, args=[N]) t2 = Thread(target=numba_gil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms Wall time: 279 ms Just like Cython, starting the GIL-locked thread first leads to poor performance: %%time t1 = Thread(target=numba_gil, args=[N]) t2 = Thread(target=numba_nogil, args=[N]) t1.start(); t2.start() t1.join(); t2.join() CPU times: user 524 ms, sys: 0 ns, total: 524 ms Wall time: 522 ms Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired; recursively calling @jit(nogil=True) functions is perfectly safe: from numba import jit @jit(nopython=True, nogil=True) def numba_recurse(n: int) -> int: if n <= 0: return 0 return numba_recurse(n - 1) numba_recurse(2); ","version":null,"tagName":"h2"},{"title":"Conclusion​","type":1,"pageTitle":"Release the GIL","url":"/2019/12/release-the-gil#conclusion","content":" Before finishing, it's important to address pain points that will show up if these techniques are used in a more realistic project: First, code running in a GIL-free context will likely also need non-trivial data structures; GIL-free functions aren't useful if they're constantly interacting with Python objects whose access requires the GIL. Cython providesextension types and Numba provides a @jitclass decorator to address this need. Second, building and distributing applications that make use of Cython/Numba can be complicated. Cython packages require running the compiler, (potentially) linking/packaging external dependencies, and distributing a binary wheel. Numba is generally simpler because the code being distributed is pure Python, but can be tricky since errors aren't detected until runtime. Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba provide tools to directly manage the GIL when appropriate. This enables true parallelism (not justconcurrency) that is impossible in vanilla Python. ","version":null,"tagName":"h2"},{"title":"Allocations in Rust: Fixed memory","type":0,"sectionRef":"#","url":"/2019/02/stacking-up","content":"","keywords":"","version":null},{"title":"Structs​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#structs","content":" The simplest case comes first. When creating vanilla struct objects, we use stack memory to hold their contents: struct Point { x: u64, y: u64, } struct Line { a: Point, b: Point, } pub fn make_line() { // `origin` is stored in the first 16 bytes of memory // starting at location `rsp` let origin = Point { x: 0, y: 0 }; // `point` makes up the next 16 bytes of memory let point = Point { x: 1, y: 2 }; // When creating `ray`, we just move the content out of // `origin` and `point` into the next 32 bytes of memory let ray = Line { a: origin, b: point }; } -- Compiler Explorer Note that while some extra-fancy instructions are used for memory manipulation in the assembly, thesub rsp, 64 instruction indicates we're still working with the stack. ","version":null,"tagName":"h2"},{"title":"Function arguments​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#function-arguments","content":" Have you ever wondered how functions communicate with each other? Like, once the variables are given to you, everything's fine. But how do you "give" those variables to another function? How do you get the results back afterward? The answer: the compiler arranges memory and assembly instructions using a pre-determined calling convention. This convention governs the rules around where arguments needed by a function will be located (either in memory offsets relative to the stack pointer rsp, or in other registers), and where the results can be found once the function has finished. And when multiple languages agree on what the calling conventions are, you can do things like having Go call Rust code! Put simply: it's the compiler's job to figure out how to call other functions, and you can assume that the compiler is good at its job. We can see this in action using a simple example: struct Point { x: i64, y: i64, } // We use integer division operations to keep // the assembly clean, understanding the result // isn't accurate. fn distance(a: &Point, b: &Point) -> i64 { // Immediately subtract from `rsp` the bytes needed // to hold all the intermediate results - this is // the stack allocation step // The compiler used the `rdi` and `rsi` registers // to pass our arguments, so read them in let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; // Do the actual math work let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared // Our final result will be stored in the `rax` register // so that our caller knows where to retrieve it. // Finally, add back to `rsp` the stack memory that is // now ready to be used by other functions. } pub fn total_distance() { let start = Point { x: 1, y: 2 }; let middle = Point { x: 3, y: 4 }; let end = Point { x: 5, y: 6 }; let _dist_1 = distance(&start, &middle); let _dist_2 = distance(&middle, &end); } -- Compiler Explorer As a consequence of function arguments never using heap memory, we can also infer that functions using the #[inline] attributes also do not heap allocate. But better than inferring, we can look at the assembly to prove it: struct Point { x: i64, y: i64, } // Note that there is no `distance` function in the assembly output, // and the total line count goes from 229 with inlining off // to 306 with inline on. Even still, no heap allocations occur. #[inline(always)] fn distance(a: &Point, b: &Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (a.x - b.x) * (a.x - b.x); let y_pow = (a.y - b.y) * (a.y - b.y); let squared = x_pow + y_pow; squared / squared } pub fn total_distance() { let start = Point { x: 1, y: 2 }; let middle = Point { x: 3, y: 4 }; let end = Point { x: 5, y: 6 }; let _dist_1 = distance(&start, &middle); let _dist_2 = distance(&middle, &end); } -- Compiler Explorer Finally, passing by value (arguments with typeCopy) and passing by reference (either moving ownership or passing a pointer) may have slightly different layouts in assembly, but will still use either stack memory or CPU registers: pub struct Point { x: i64, y: i64, } // Moving values pub fn distance_moved(a: Point, b: Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared } // Borrowing values has two extra `mov` instructions on lines 21 and 22 pub fn distance_borrowed(a: &Point, b: &Point) -> i64 { let x1 = a.x; let x2 = b.x; let y1 = a.y; let y2 = b.y; let x_pow = (x1 - x2) * (x1 - x2); let y_pow = (y1 - y2) * (y1 - y2); let squared = x_pow + y_pow; squared / squared } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Enums​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#enums","content":" If you've ever worried that wrapping your types inOption orResult would finally make them large enough that Rust decides to use heap allocation instead, fear no longer: enum and union types don't use heap allocation: enum MyEnum { Small(u8), Large(u64) } struct MyStruct { x: MyEnum, y: MyEnum, } pub fn enum_compare() { let x = MyEnum::Small(0); let y = MyEnum::Large(0); let z = MyStruct { x, y }; let opt = Option::Some(z); } -- Compiler Explorer Because the size of an enum is the size of its largest element plus a flag, the compiler can predict how much memory is used no matter which variant of an enum is currently stored in a variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great way to show this in assembly, so I'll instead point you to thecore::mem::size_ofdocumentation. ","version":null,"tagName":"h2"},{"title":"Arrays​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#arrays","content":" The array type is guaranteed to be stack allocated, which is why the array size must be declared. Interestingly enough, this can be used to cause safe Rust programs to crash: // 256 bytes #[derive(Default)] struct TwoFiftySix { _a: [u64; 32] } // 8 kilobytes #[derive(Default)] struct EightK { _a: [TwoFiftySix; 32] } // 256 kilobytes #[derive(Default)] struct TwoFiftySixK { _a: [EightK; 32] } // 8 megabytes - exceeds space typically provided for the stack, // though the kernel can be instructed to allocate more. // On Linux, you can check stack size using `ulimit -s` #[derive(Default)] struct EightM { _a: [TwoFiftySixK; 32] } fn main() { // Because we already have things in stack memory // (like the current function call stack), allocating another // eight megabytes of stack memory crashes the program let _x = EightM::default(); } --Rust Playground There aren't any security implications of this (no memory corruption occurs), but it's good to note that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to overflow the stack. ","version":null,"tagName":"h2"},{"title":"Closures​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#closures","content":" Rules for how anonymous functions capture their arguments are typically language-specific. In Java,Lambda Expressions are actually objects created on the heap that capture local primitives by copying, and capture local non-primitives as (final) references.Python andJavaScriptboth bind everything by reference normally, but Python can alsocapture values and JavaScript hasArrow functions. In Rust, arguments to closures are the same as arguments to other functions; closures are simply functions that don't have a declared name. Some weird ordering of the stack may be required to handle them, but it's the compiler's responsiblity to figure that out. Each example below has the same effect, but a different assembly implementation. In the simplest case, we immediately run a closure returned by another function. Because we don't store a reference to the closure, the stack memory needed to store the captured values is contiguous: fn my_func() -> impl FnOnce() { let x = 24; // Note that this closure in assembly looks exactly like // any other function; you even use the `call` instruction // to start running it. move || { x; } } pub fn immediate() { my_func()(); my_func()(); } -- Compiler Explorer, 25 total assembly instructions If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory of the original function. Getting the details right is a bit harder, so the instruction count goes up even though this code is functionally equivalent to our original example: pub fn simple_reference() { let x = my_func(); let y = my_func(); y(); x(); } -- Compiler Explorer, 55 total assembly instructions Even things like variable order can make a difference in instruction count: pub fn complex() { let x = my_func(); let y = my_func(); x(); y(); } -- Compiler Explorer, 70 total assembly instructions In every circumstance though, the compiler ensured that no heap allocations were necessary. ","version":null,"tagName":"h2"},{"title":"Generics​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#generics","content":" Traits in Rust come in two broad forms: static dispatch (monomorphization, impl Trait) and dynamic dispatch (trait objects, dyn Trait). While dynamic dispatch is often associated with trait objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well: trait GetInt { fn get_int(&self) -> u64; } // vtable stored at section L__unnamed_1 struct WhyNotU8 { x: u8 } impl GetInt for WhyNotU8 { fn get_int(&self) -> u64 { self.x as u64 } } // vtable stored at section L__unnamed_2 struct ActualU64 { x: u64 } impl GetInt for ActualU64 { fn get_int(&self) -> u64 { self.x } } // `&dyn` declares that we want to use dynamic dispatch // rather than monomorphization, so there is only one // `retrieve_int` function that shows up in the final assembly. // If we used generics, there would be one implementation of // `retrieve_int` for each type that implements `GetInt`. pub fn retrieve_int(u: &dyn GetInt) { // In the assembly, we just call an address given to us // in the `rsi` register and hope that it was set up // correctly when this function was invoked. let x = u.get_int(); } pub fn do_call() { // Note that even though the vtable for `WhyNotU8` and // `ActualU64` includes a pointer to // `core::ptr::real_drop_in_place`, it is never invoked. let a = WhyNotU8 { x: 0 }; let b = ActualU64 { x: 0 }; retrieve_int(&a); retrieve_int(&b); } -- Compiler Explorer It's hard to imagine practical situations where dynamic dispatch would be used for objects that aren't heap allocated, but it technically can be done. ","version":null,"tagName":"h2"},{"title":"Copy types​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#copy-types","content":" Understanding move semantics and copy semantics in Rust is weird at first. The Rust docsgo into detail far better than can be addressed here, so I'll leave them to do the job. From a memory perspective though, their guideline is reasonable:if your type can implemement Copy, it should. While there are potential speed tradeoffs to benchmark when discussing Copy (move semantics for stack objects vs. copying stack pointers vs. copying stack structs), it's impossible for Copyto introduce a heap allocation. But why is this the case? Fundamentally, it's because the language controls what Copy means -"the behavior of Copy is not overloadable"because it's a marker trait. From there we'll note that a typecan implement Copyif (and only if) its components implement Copy, and thatno heap-allocated types implement Copy. Thus, assignments involving heap types are always move semantics, and new heap allocations won't occur because of implicit operator behavior. #[derive(Clone)] struct Cloneable { x: Box<u64> } // error[E0204]: the trait `Copy` may not be implemented for this type #[derive(Copy, Clone)] struct NotCopyable { x: Box<u64> } -- Compiler Explorer ","version":null,"tagName":"h2"},{"title":"Iterators​","type":1,"pageTitle":"Allocations in Rust: Fixed memory","url":"/2019/02/stacking-up#iterators","content":" In managed memory languages (likeJava), there's a subtle difference between these two code samples: public static int sum_for(List<Long> vals) { long sum = 0; // Regular for loop for (int i = 0; i < vals.length; i++) { sum += vals[i]; } return sum; } public static int sum_foreach(List<Long> vals) { long sum = 0; // "Foreach" loop - uses iteration for (Long l : vals) { sum += l; } return sum; } In the sum_for function, nothing terribly interesting happens. In sum_foreach, an object of typeIteratoris allocated on the heap, and will eventually be garbage-collected. This isn't a great design; iterators are often transient objects that you need during a function and can discard once the function ends. Sounds exactly like the issue stack-allocated objects address, no? In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in heap memory, but the iterator itself (Iter) doesn't need to use the heap. In each of the examples below we iterate over a collection, but never use heap allocation: use std::collections::HashMap; // There's a lot of assembly generated, but if you search in the text, // there are no references to `real_drop_in_place` anywhere. pub fn sum_vec(x: &Vec<u32>) { let mut s = 0; // Basic iteration over vectors doesn't need allocation for y in x { s += y; } } pub fn sum_enumerate(x: &Vec<u32>) { let mut s = 0; // More complex iterators are just fine too for (_i, y) in x.iter().enumerate() { s += y; } } pub fn sum_hm(x: &HashMap<u32, u32>) { let mut s = 0; // And it's not just Vec, all types will allocate the iterator // on stack memory for y in x.values() { s += y; } } -- Compiler Explorer ","version":null,"tagName":"h2"}],"options":{"id":"default"}} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..12df068 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1 @@ +https://speice.io/2011/11/webpack-industrial-complexweekly0.5https://speice.io/2015/11/autocallableweekly0.5https://speice.io/2015/11/welcomeweekly0.5https://speice.io/2015/12/testing-cramerweekly0.5https://speice.io/2016/01/cloudy-in-seattleweekly0.5https://speice.io/2016/01/complaining-about-the-weatherweekly0.5https://speice.io/2016/02/guaranteed-money-makerweekly0.5https://speice.io/2016/02/profitability-using-the-investment-formulaweekly0.5https://speice.io/2016/03/predicting-santander-customer-happinessweekly0.5https://speice.io/2016/03/tweet-like-meweekly0.5https://speice.io/2016/04/tick-tockweekly0.5https://speice.io/2016/05/the-unfair-casinoweekly0.5https://speice.io/2016/06/event-studies-and-earnings-releasesweekly0.5https://speice.io/2016/10/rustic-repodcastingweekly0.5https://speice.io/2016/11/pca-audio-compressionweekly0.5https://speice.io/2018/01/captains-cookbook-part-1weekly0.5https://speice.io/2018/01/captains-cookbook-part-2weekly0.5https://speice.io/2018/05/helloweekly0.5https://speice.io/2018/06/dateutil-parser-to-rustweekly0.5https://speice.io/2018/09/isomorphic-appsweekly0.5https://speice.io/2018/09/primitives-in-rust-are-weirdweekly0.5https://speice.io/2018/10/case-study-optimizationweekly0.5https://speice.io/2018/12/allocation-safetyweekly0.5https://speice.io/2018/12/what-small-business-really-meansweekly0.5https://speice.io/2019/02/08/compiler-optimizationsweekly0.5https://speice.io/2019/02/a-heaping-helpingweekly0.5https://speice.io/2019/02/stacking-upweekly0.5https://speice.io/2019/02/summaryweekly0.5https://speice.io/2019/02/the-whole-worldweekly0.5https://speice.io/2019/02/understanding-allocations-in-rustweekly0.5https://speice.io/2019/05/making-breadweekly0.5https://speice.io/2019/06/high-performance-systemsweekly0.5https://speice.io/2019/09/binary-format-shootoutweekly0.5https://speice.io/2019/12/release-the-gilweekly0.5https://speice.io/archiveweekly0.5https://speice.io/authorsweekly0.5https://speice.io/feed.xmlweekly0.5https://speice.io/page/2weekly0.5https://speice.io/page/3weekly0.5https://speice.io/page/4weekly0.5https://speice.io/weekly0.5 \ No newline at end of file