/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Reflection;
namespace QuantConnect.Optimizer.Parameters
{
///
/// Override deserialization method.
/// Can handle instances
///
public class OptimizationParameterJsonConverter : JsonConverter
{
///
/// Writes a JSON object from a OptimizationParameter object
///
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jo = new JObject();
Type type = value.GetType();
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.CanRead)
{
var attribute = prop.GetCustomAttribute();
object propVal = prop.GetValue(value, null);
if (propVal != null)
{
jo.Add(attribute.PropertyName ?? prop.Name, JToken.FromObject(propVal, serializer));
}
}
}
jo.WriteTo(writer);
}
///
/// Creates a Optimization Parameter object from a JSON object
///
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer
)
{
JObject token = JObject.Load(reader);
var parameterName = (token.GetValue("name", StringComparison.OrdinalIgnoreCase) ?? token.GetValue("key", StringComparison.OrdinalIgnoreCase))?.Value();
if (string.IsNullOrEmpty(parameterName))
{
throw new ArgumentException(Messages.OptimizationParameterJsonConverter.OptimizationParameterNotSpecified);
}
JToken value;
JToken minToken;
JToken maxToken;
OptimizationParameter optimizationParameter = null;
if (token.TryGetValue("min", StringComparison.OrdinalIgnoreCase, out minToken) &&
token.TryGetValue("max", StringComparison.OrdinalIgnoreCase, out maxToken))
{
var stepToken = token.GetValue("step", StringComparison.OrdinalIgnoreCase)?.Value();
var minStepToken = token.GetValue("minStep", StringComparison.OrdinalIgnoreCase)?.Value() ?? token.GetValue("min-step", StringComparison.OrdinalIgnoreCase)?.Value();
if (stepToken.HasValue)
{
if (minStepToken.HasValue)
{
optimizationParameter = new OptimizationStepParameter(parameterName,
minToken.Value(),
maxToken.Value(),
stepToken.Value,
minStepToken.Value);
}
else
{
optimizationParameter = new OptimizationStepParameter(parameterName,
minToken.Value(),
maxToken.Value(),
stepToken.Value);
}
}
else
{
optimizationParameter = new OptimizationStepParameter(parameterName,
minToken.Value(),
maxToken.Value());
}
}
else if(token.TryGetValue("value", StringComparison.OrdinalIgnoreCase, out value))
{
optimizationParameter = new StaticOptimizationParameter(parameterName, value.Value());
}
if (optimizationParameter == null)
{
throw new ArgumentException(Messages.OptimizationParameterJsonConverter.OptimizationParameterNotSupported);
}
return optimizationParameter;
}
///
/// Determines if an OptimizationParameter is assignable from the given object type
///
public override bool CanConvert(Type objectType) => typeof(OptimizationParameter).IsAssignableFrom(objectType);
}
}