import org.apache.commons.cli.*;
import org.apache.commons.io.FilenameUtils;
import java.io.*;
import java.util.*;
/**
* The generated point files have different number of points.
* We need to make sure that all the point files have the same stock ordering with same stocks before applying the rotations.
*/
public class PointTransformer {
private String globalVectorFile;
private String globalPointFile;
private String pointFolder;
private String vectorFolder;
private String destPointFolder;
private String weightFolder;
private String symbolList;
private String stocksFile;
public static void main(String[] args) {
Options options = new Options();
options.addOption("sf", true, "The complese stock file");
options.addOption("g", true, "Global file");
options.addOption("gp", true, "Global pooint file");
options.addOption("v", true, "Input Vector folder");
options.addOption("p", true, "Points folder");
options.addOption("d", true, "Destination point folder");
options.addOption("w", true, "Destination weight folder"); // folder where common weights are stored
options.addOption("s", true, "Symbol List");
CommandLineParser commandLineParser = new BasicParser();
try {
CommandLine cmd = commandLineParser.parse(options, args);
String globalPointFile = cmd.getOptionValue("gp");
String globalFile = cmd.getOptionValue("g");
String vectorFile = cmd.getOptionValue("v");
String pointsFolder = cmd.getOptionValue("p");
String distFolder = cmd.getOptionValue("d");
String weightFolder = cmd.getOptionValue("w");
String symbolList = cmd.getOptionValue("s");
String stockFile = cmd.getOptionValue("sf");
PointTransformer pointTransformer = new PointTransformer(globalFile, pointsFolder, vectorFile,
distFolder, globalPointFile, weightFolder, symbolList, stockFile);
pointTransformer.process();
} catch (ParseException e) {
e.printStackTrace();
}
}
public PointTransformer(String globalVectorFile, String pointFolder, String vectorFolder,
String destPointFolder, String globalPointFile, String weightFolder, String symbolList, String stockFile) {
this.globalVectorFile = globalVectorFile;
this.pointFolder = pointFolder;
this.vectorFolder = vectorFolder;
this.destPointFolder = destPointFolder;
this.globalPointFile = globalPointFile;
this.weightFolder = weightFolder;
this.symbolList = symbolList;
this.stocksFile = stockFile;
}
public void process() {
File inFolder = new File(vectorFolder);
if (!inFolder.isDirectory()) {
System.out.println("In should be a folder");
return;
}
// make the common weight folder
File commonWeightFolder = new File(weightFolder);
if (!commonWeightFolder.exists()) {
commonWeightFolder.mkdirs();
}
// first get the global vector file and its keys
File globalFile = new File(globalVectorFile);
Map<Integer, String> keysToSymbols = loadKeys(stocksFile, symbolList);
List<Integer> globalKeys = Utils.readVectorKeys(globalFile);
TreeSet<Integer> commonKeys = new TreeSet<Integer>();
Map<String, Map<Integer, Point>> filesToPoint = new HashMap<String, Map<Integer, Point>>();
if (keysToSymbols != null && keysToSymbols.size() > 0) {
commonKeys.addAll(keysToSymbols.keySet());
} else {
commonKeys.addAll(globalKeys);
}
// go through every vector file and get the common keys
for (int i = 0; i < inFolder.listFiles().length; i++) {
File inFile = inFolder.listFiles()[i];
List<Integer> partKeys = Utils.readVectorKeys(inFile);
// load the corresponding points file
String fileName = inFile.getName();
String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);
String pointFile = pointFolder + "/" + fileNameWithOutExt + ".txt";
Map<Integer, Point> points = Utils.loadPoints(new File(pointFile), partKeys);
filesToPoint.put(fileName, points);
commonKeys.retainAll(partKeys);
}
// write the global file
String commonGlobalPointFile = destPointFolder + "/" + globalFile.getName();
String commonGlobalWectorFile = weightFolder + "/" + FilenameUtils.removeExtension(globalFile.getName()) + ".csv";
Map<Integer, Point> globalPoints = Utils.loadPoints(new File(globalPointFile), globalKeys);
Map<Integer, Double> globalCaps = Utils.loadCaps(globalFile);
writePoints(commonKeys, globalPoints, commonGlobalPointFile, commonGlobalWectorFile, globalCaps);
for (Map.Entry<String, Map<Integer, Point>> entry : filesToPoint.entrySet()) {
// now write the common keys back as new files, we need to preserve the order as well
// get the file
Map<Integer, Point> pointMap = entry.getValue();
String file = entry.getKey();
String fileNameWithOutExt = FilenameUtils.removeExtension(file);
String weightFile = weightFolder + "/" + fileNameWithOutExt + ".csv";
Map<Integer, Double> caps = Utils.loadCaps(new File(vectorFolder + "/" + entry.getKey()));
writePoints(commonKeys, pointMap, destPointFolder + "/" + file, weightFile, caps);
}
}
private void writePoints(TreeSet<Integer> commonKeys, Map<Integer, Point> pointMap, String file, String weightFile, Map<Integer, Double> caps) {
BufferedWriter bufWriter = null;
WriterWrapper weightWriter = null;
try {
double max = Double.MIN_VALUE;
for (Double d : caps.values()) {
if (max < d) {
max = d;
}
}
FileOutputStream fos = new FileOutputStream(file);
bufWriter = new BufferedWriter(new OutputStreamWriter(fos));
weightWriter = new WriterWrapper(weightFile, true);
int i = 0;
for (Integer key : commonKeys) {
Point p = pointMap.get(key);
p.setIndex(i++);
bufWriter.write(p.serialize());
bufWriter.newLine();
weightWriter.write(caps.get(key) / max);
weightWriter.line();
}
} catch (IOException e) {
throw new RuntimeException("Failed to write file", e);
} finally {
if (bufWriter != null) {
try {
bufWriter.close();
} catch (IOException ignore) {
}
}
if (weightWriter != null) {
weightWriter.close();
}
}
}
public static Map<Integer, String> loadKeys(String inFile, String symbols) {
List<String> symbolsList = new ArrayList<String>();
if (symbols != null && !symbols.trim().equals("")) {
String []splits = symbols.split(",");
Collections.addAll(symbolsList, splits);
}
if (!symbolsList.isEmpty()) {
System.out.println("Reading original stock file: " + inFile);
BufferedReader bufRead = null;
Map<Integer, String> maps = new HashMap<Integer, String>();
try {
FileReader input = new FileReader(inFile);
bufRead = new BufferedReader(input);
Record record;
while ((record = Utils.parseFile(bufRead)) != null) {
String s = record.getSymbolString();
if (symbolsList.contains(s)) {
maps.put(record.getSymbol(), record.getSymbolString());
}
}
System.out.println("No of stocks: " + maps.size());
} catch (FileNotFoundException e) {
throw new RuntimeException("Failed to open file");
}
return maps;
}
return null;
}
}